Skip to content

Commit f7a8e5d

Browse files
committed
fix: stream tool intent live and sync the ANSI sanitizer
1 parent 4e94b9a commit f7a8e5d

4 files changed

Lines changed: 15 additions & 2 deletions

File tree

apps/pythinker-code/src/tui/constant/rendering.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ export const THINKING_SPINNER_LABEL_INTERVAL_MS = 12_000;
134134

135135
const LIVE_INTENT_MAX_LENGTH = 120;
136136
// oxlint-disable-next-line no-control-regex -- wire text must not retain terminal escape sequences.
137-
const ANSI_ESCAPE = /\u001B(?:\[[0-?]*[ -/]*[@-~]|\][^\u0007]*(?:\u0007|$))/gu;
137+
const ANSI_ESCAPE = /\u001B(?:\[[0-?]*[ -/]*[@-~]|\][^\u0007\u001B]*(?:\u0007|\u001B\\|$))/gu;
138138
const CONTROL_CHARACTER = /\p{Cc}/gu;
139139
let liveIntent: string | undefined;
140140

apps/pythinker-code/src/tui/constant/streaming.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Extracts useful string fields from partially streamed JSON tool args.
22
// This is intentionally a preview parser, not a full JSON parser.
33
export const STREAMING_ARGS_FIELD_RE =
4-
/"(path|file_path|command|pattern|query|url|description|title|name)"\s*:\s*"((?:\\.|[^"\\])*)"/g;
4+
/"(i|path|file_path|command|pattern|query|url|description|title|name)"\s*:\s*"((?:\\.|[^"\\])*)"/g;
55

66
// Bounds live tool-argument previews; final tool.call payloads remain complete.
77
export const STREAMING_ARGS_PREVIEW_MAX_CHARS = 64 * 1024;

apps/pythinker-code/test/tui/tool-intent-label.test.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,13 @@ describe('tool intent thinking label', () => {
5454
expect(formatThinkingSpinnerLabel(0)).toBe('check failing test…');
5555
});
5656

57+
it('removes ST-terminated OSC hyperlinks before display', () => {
58+
setLiveIntent(
59+
'\u001B]8;;https://example.com\u001B\\click\u001B]8;;\u001B\\ done',
60+
);
61+
expect(formatThinkingSpinnerLabel(0)).toBe('click done…');
62+
});
63+
5764
it('sets intent from a tool delta and clears it on the result', () => {
5865
const driver = new PythinkerTUI({} as never, makeStartupInput());
5966
const dispatch = (event: Event): void =>

apps/pythinker-code/test/tui/utils/event-payload.test.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ describe('streaming tool argument payload helpers', () => {
1818
});
1919
});
2020

21+
it('parses intent from partial streaming arguments', () => {
22+
expect(parseStreamingArgs('{"i":"scan configs","path":"/tmp/x')).toMatchObject({
23+
i: 'scan configs',
24+
});
25+
});
26+
2127
it('caps accumulated streaming preview text', () => {
2228
const current = 'a'.repeat(STREAMING_ARGS_PREVIEW_MAX_CHARS - 2);
2329

0 commit comments

Comments
 (0)