Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion apps/desktop/.storybook/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ const config: StorybookConfig = {
{ find: 'node:crypto', replacement: STORYBOOK_NODE_CRYPTO_BOUNDARY },
{ find: '@maka/ui/icons', replacement: resolve(UI_SRC, 'icons.tsx') },
{ find: '@maka/ui/artifact-preview-registry', replacement: resolve(UI_SRC, 'artifact-preview-registry.ts') },
{ find: '@maka/ui/assistant-stream', replacement: resolve(UI_SRC, 'assistant-stream.ts') },
{ find: '@maka/ui/maka-uri', replacement: resolve(UI_SRC, 'maka-uri.ts') },
{ find: /^@maka\/ui$/, replacement: resolve(UI_SRC, 'index.ts') },
],
Expand Down
196 changes: 0 additions & 196 deletions apps/desktop/src/main/__tests__/assistant-stream.test.ts

This file was deleted.

74 changes: 0 additions & 74 deletions apps/desktop/src/main/__tests__/thinking-stream.test.ts

This file was deleted.

1 change: 0 additions & 1 deletion apps/desktop/tsconfig.storybook.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
"@maka/ui": ["../../packages/ui/src/index.ts"],
"@maka/ui/icons": ["../../packages/ui/src/icons.tsx"],
"@maka/ui/artifact-preview-registry": ["../../packages/ui/src/artifact-preview-registry.ts"],
"@maka/ui/assistant-stream": ["../../packages/ui/src/assistant-stream.ts"],
"@maka/ui/maka-uri": ["../../packages/ui/src/maka-uri.ts"],
}
},
Expand Down
1 change: 0 additions & 1 deletion apps/desktop/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ export default defineConfig({
{ find: '@maka/ui/client-plugin', replacement: resolve(UI_SRC, 'client-plugin-slots.tsx') },
{ find: '@maka/ui/icons', replacement: resolve(UI_SRC, 'icons.tsx') },
{ find: '@maka/ui/artifact-preview-registry', replacement: resolve(UI_SRC, 'artifact-preview-registry.ts') },
{ find: '@maka/ui/assistant-stream', replacement: resolve(UI_SRC, 'assistant-stream.ts') },
{ find: '@maka/ui/maka-uri', replacement: resolve(UI_SRC, 'maka-uri.ts') },
{ find: /^@maka\/ui$/, replacement: resolve(UI_SRC, 'index.ts') },
],
Expand Down
5 changes: 1 addition & 4 deletions packages/cli/src/acp/session-event-mapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,10 +188,7 @@ function deltaText(
event: Extract<SessionEvent, { type: 'text_delta' | 'thinking_delta' }>,
current = '',
): string {
return foldRuntimeHostAssistantDelta(current, {
startOffset: event.startOffset ?? current.length,
text: event.text,
}).text;
return foldRuntimeHostAssistantDelta(current, event).text;
}

function streamKey(kind: StreamKind, messageId: string): string {
Expand Down
18 changes: 18 additions & 0 deletions packages/core/src/__tests__/events.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,27 @@ import {
decodeToolStepProgress,
encodeToolStepProgress,
decodeMessageContent,
foldAssistantDelta,
isQuoteRef,
} from '../events.js';

test('folds assistant deltas idempotently by source offset', () => {
assert.deepStrictEqual(foldAssistantDelta(0, { startOffset: 0, text: 'Hello' }), {
tail: 'Hello',
endOffset: 5,
});
assert.deepStrictEqual(foldAssistantDelta(5, { startOffset: 0, text: 'Hello world' }), {
tail: ' world',
endOffset: 11,
});
assert.deepStrictEqual(foldAssistantDelta(11, { startOffset: 0, text: 'Hello' }), {
tail: '',
endOffset: 11,
});
assert.deepStrictEqual(foldAssistantDelta(3, { text: 'abc' }), { tail: 'abc', endOffset: 6 });
assert.strictEqual(foldAssistantDelta(3, { startOffset: 4, text: 'gap' }), undefined);
});

test('aggregates inline references against the combined display text', () => {
assert.deepStrictEqual(
aggregateMessageContents([
Expand Down
20 changes: 20 additions & 0 deletions packages/core/src/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -680,6 +680,8 @@ export interface TextDeltaEvent extends BaseEvent {
export interface TextCompleteEvent extends BaseEvent {
type: 'text_complete';
interrupted?: true;
/** `text` replaces the streamed deltas instead of extending them. */
replaced?: true;
messageId: string;
text: string;
/** Provider-owned text metadata such as Responses URL citations. */
Expand All @@ -694,9 +696,27 @@ export interface ThinkingDeltaEvent extends BaseEvent {
text: string;
}

/**
* Apply a text/thinking delta to a stream that has consumed `currentEnd`
* source characters. Overlap with consumed text is dropped, so replayed and
* reseeded deltas are idempotent. A delta that starts past `currentEnd` is a
* gap and returns `undefined`; one without `startOffset` appends.
*/
export function foldAssistantDelta(
currentEnd: number,
delta: { readonly startOffset?: number; readonly text: string },
): { tail: string; endOffset: number } | undefined {
const startOffset = delta.startOffset ?? currentEnd;
if (startOffset > currentEnd) return undefined;
const tail = delta.text.slice(currentEnd - startOffset);
return { tail, endOffset: currentEnd + tail.length };
}

export interface ThinkingCompleteEvent extends BaseEvent {
type: 'thinking_complete';
interrupted?: true;
/** `text` replaces the streamed deltas instead of extending them. */
replaced?: true;
messageId: string;
text: string;
/** Anthropic signed thinking — MUST be re-sent on replay. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ test('applies authoritative replacement once and does not complete it again at T
deltaFrame(2, 5, '', { complete: true, interrupted: true }),
).events;
assert.ok(completed[0]?.type === 'text_complete' && completed[0].interrupted === true);
assert.equal(completed[0].replaced, true);
assert.deepEqual(
completed.map((event) => [event.type, 'text' in event ? event.text : '']),
[['text_complete', 'final']],
Expand Down
Loading