xiaotime 0.5.0 → 0.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__tests__/ansi_tags.test.d.ts +9 -0
- package/dist/__tests__/ansi_tags.test.d.ts.map +1 -0
- package/dist/__tests__/ansi_tags.test.js +58 -0
- package/dist/__tests__/ansi_tags.test.js.map +1 -0
- package/dist/__tests__/paste_transform_submit.test.d.ts +2 -0
- package/dist/__tests__/paste_transform_submit.test.d.ts.map +1 -0
- package/dist/__tests__/paste_transform_submit.test.js +74 -0
- package/dist/__tests__/paste_transform_submit.test.js.map +1 -0
- package/dist/__tests__/session_match.test.d.ts +10 -0
- package/dist/__tests__/session_match.test.d.ts.map +1 -0
- package/dist/__tests__/session_match.test.js +55 -0
- package/dist/__tests__/session_match.test.js.map +1 -0
- package/dist/__tests__/tools.test.js +165 -0
- package/dist/__tests__/tools.test.js.map +1 -1
- package/dist/__tests__/ui_state_listener_lifecycle.test.d.ts +2 -0
- package/dist/__tests__/ui_state_listener_lifecycle.test.d.ts.map +1 -0
- package/dist/__tests__/ui_state_listener_lifecycle.test.js +152 -0
- package/dist/__tests__/ui_state_listener_lifecycle.test.js.map +1 -0
- package/dist/ansi_tags.d.ts +20 -0
- package/dist/ansi_tags.d.ts.map +1 -0
- package/dist/ansi_tags.js +38 -0
- package/dist/ansi_tags.js.map +1 -0
- package/dist/config.d.ts +1 -1
- package/dist/config.js +1 -1
- package/dist/display.d.ts +53 -22
- package/dist/display.d.ts.map +1 -1
- package/dist/display.js +773 -47
- package/dist/display.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +34 -3
- package/dist/index.js.map +1 -1
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +5 -2
- package/dist/session.js.map +1 -1
- package/dist/session_match.d.ts +19 -0
- package/dist/session_match.d.ts.map +1 -0
- package/dist/session_match.js +9 -0
- package/dist/session_match.js.map +1 -0
- package/dist/sidebar.d.ts +84 -0
- package/dist/sidebar.d.ts.map +1 -0
- package/dist/sidebar.js +310 -0
- package/dist/sidebar.js.map +1 -0
- package/dist/tools.d.ts +4 -0
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +64 -49
- package/dist/tools.js.map +1 -1
- package/dist/ui_state.d.ts +41 -87
- package/dist/ui_state.d.ts.map +1 -1
- package/dist/ui_state.js +216 -162
- package/dist/ui_state.js.map +1 -1
- package/dist/ws.d.ts +10 -14
- package/dist/ws.d.ts.map +1 -1
- package/dist/ws.js +236 -119
- package/dist/ws.js.map +1 -1
- package/package.json +10 -5
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
/**
|
|
4
|
+
* Stdin keypress listener lifecycle tests.
|
|
5
|
+
*
|
|
6
|
+
* SPRINT-CLI-INPUT-AND-TOOL-HARDENING-1 (#7299) PR2.
|
|
7
|
+
*
|
|
8
|
+
* The bug being guarded: each `_makeRl` call attaches a fresh readline
|
|
9
|
+
* `Interface` with `terminal: true`, which in turn registers a keypress
|
|
10
|
+
* listener on `process.stdin`. Node's `rl.close()` is documented to
|
|
11
|
+
* detach that listener, but the cleanup is unreliable when stdin's raw
|
|
12
|
+
* mode was toggled mid-cycle (the approval-menu path does that). The
|
|
13
|
+
* pre-fix accumulation: every `promptApprovalMenu` cycle left one extra
|
|
14
|
+
* keypress listener attached, and every active listener echoes
|
|
15
|
+
* keystrokes independently. Stephan observed 6-8x character
|
|
16
|
+
* multiplication after a session with several approval-required tool
|
|
17
|
+
* calls 2026-05-25.
|
|
18
|
+
*
|
|
19
|
+
* The fix in `_makeRl` strips leftover `keypress` listeners before
|
|
20
|
+
* `readline.createInterface` attaches the new one — Node's
|
|
21
|
+
* `emitKeypressEvents` re-bootstraps on the next createInterface, so
|
|
22
|
+
* the keypress event infrastructure is preserved.
|
|
23
|
+
*
|
|
24
|
+
* These tests pin the listener-count contract: after any number of rl
|
|
25
|
+
* recreations, the count of `keypress` listeners on `process.stdin`
|
|
26
|
+
* stays at exactly 1 (the live rl's). Each test drives at least one
|
|
27
|
+
* full approval-menu cycle via the no-TTY fall-through path that
|
|
28
|
+
* `approval_menu.test.ts` already exercises (vitest's stdin is not a
|
|
29
|
+
* TTY, so `setRawMode` throws and the menu returns `(no TTY)` —
|
|
30
|
+
* `_makeRl` still fires in the `finally` block, which is the
|
|
31
|
+
* load-bearing path for this guard).
|
|
32
|
+
*/
|
|
33
|
+
const vitest_1 = require("vitest");
|
|
34
|
+
const ui_state_js_1 = require("../ui_state.js");
|
|
35
|
+
/** Listener types `_makeRl` strips, by stream. Each
|
|
36
|
+
* readline.createInterface({ terminal: true }) registers one of each
|
|
37
|
+
* on the indicated stream. `resize` lives on stdout (readline tracks
|
|
38
|
+
* terminal width from the output stream); the other three on stdin.
|
|
39
|
+
* Keep these in sync with `_makeRl`. */
|
|
40
|
+
const STDIN_EVENTS = ["keypress", "end", "error"];
|
|
41
|
+
const STDOUT_EVENTS = ["resize"];
|
|
42
|
+
function _stripAll() {
|
|
43
|
+
for (const ev of STDIN_EVENTS)
|
|
44
|
+
process.stdin.removeAllListeners(ev);
|
|
45
|
+
for (const ev of STDOUT_EVENTS)
|
|
46
|
+
process.stdout.removeAllListeners(ev);
|
|
47
|
+
}
|
|
48
|
+
(0, vitest_1.beforeEach)(() => {
|
|
49
|
+
// Suppress menu output; we only care about listener counts.
|
|
50
|
+
vitest_1.vi.spyOn(process.stdout, "write").mockImplementation(() => true);
|
|
51
|
+
});
|
|
52
|
+
(0, vitest_1.afterEach)(() => {
|
|
53
|
+
vitest_1.vi.restoreAllMocks();
|
|
54
|
+
// Clean slate for the next test — otherwise an accidental leak
|
|
55
|
+
// here would surface as a failure in an unrelated downstream test.
|
|
56
|
+
_stripAll();
|
|
57
|
+
});
|
|
58
|
+
(0, vitest_1.describe)("stdin keypress listener lifecycle — ISC-7299-003", () => {
|
|
59
|
+
(0, vitest_1.test)("single SessionUI instantiation attaches exactly one keypress listener", () => {
|
|
60
|
+
process.stdin.removeAllListeners("keypress");
|
|
61
|
+
const ui = new ui_state_js_1.SessionUI();
|
|
62
|
+
// _makeRl ran once in the constructor → one new keypress listener.
|
|
63
|
+
(0, vitest_1.expect)(process.stdin.listenerCount("keypress")).toBe(1);
|
|
64
|
+
ui.getRl().close();
|
|
65
|
+
});
|
|
66
|
+
(0, vitest_1.test)("count stays at 1 after one approval-menu cycle", async () => {
|
|
67
|
+
process.stdin.removeAllListeners("keypress");
|
|
68
|
+
const ui = new ui_state_js_1.SessionUI();
|
|
69
|
+
(0, vitest_1.expect)(process.stdin.listenerCount("keypress")).toBe(1);
|
|
70
|
+
// promptApprovalMenu bails on no-TTY but the finally block still
|
|
71
|
+
// runs `_makeRl`, so this exercises the recreate path. Pre-fix,
|
|
72
|
+
// this would leave the previous rl's keypress listener attached
|
|
73
|
+
// and the count would jump to 2.
|
|
74
|
+
await ui.promptApprovalMenu();
|
|
75
|
+
(0, vitest_1.expect)(process.stdin.listenerCount("keypress")).toBe(1);
|
|
76
|
+
ui.getRl().close();
|
|
77
|
+
});
|
|
78
|
+
(0, vitest_1.test)("count stays at 1 after five sequential approval-menu cycles", async () => {
|
|
79
|
+
// The user-observed bug: 6-8x character echo after several tool
|
|
80
|
+
// calls. This test replays the exact accumulation path and asserts
|
|
81
|
+
// it does not grow.
|
|
82
|
+
process.stdin.removeAllListeners("keypress");
|
|
83
|
+
const ui = new ui_state_js_1.SessionUI();
|
|
84
|
+
for (let i = 0; i < 5; i++) {
|
|
85
|
+
await ui.promptApprovalMenu();
|
|
86
|
+
// After EACH cycle the count must still be 1 — not 2, not 6.
|
|
87
|
+
(0, vitest_1.expect)(process.stdin.listenerCount("keypress")).toBe(1);
|
|
88
|
+
}
|
|
89
|
+
ui.getRl().close();
|
|
90
|
+
});
|
|
91
|
+
(0, vitest_1.test)("end / error / resize listeners also stay bounded across cycles", async () => {
|
|
92
|
+
// Adjacent leaks — same root cause as the keypress leak
|
|
93
|
+
// (rl.close() doesn't reliably detach on setRawMode-toggled
|
|
94
|
+
// stdin), different event types. `end` / `error` accumulate on
|
|
95
|
+
// stdin; `resize` accumulates on stdout (readline tracks terminal
|
|
96
|
+
// width from the output stream). Pre-fix these crossed Node's
|
|
97
|
+
// default MaxListeners (10) after ~11 recreations and logged
|
|
98
|
+
// MaxListenersExceededWarning to stderr. Post-fix the strip in
|
|
99
|
+
// `_makeRl` keeps each at ≤ a single-digit ceiling across an
|
|
100
|
+
// unbounded number of cycles.
|
|
101
|
+
_stripAll();
|
|
102
|
+
const ui = new ui_state_js_1.SessionUI();
|
|
103
|
+
for (let i = 0; i < 15; i++) {
|
|
104
|
+
await ui.promptApprovalMenu();
|
|
105
|
+
}
|
|
106
|
+
// Each event type ends up with the live rl's single listener.
|
|
107
|
+
// Cap the assertion at 2 to leave headroom for Node-version-
|
|
108
|
+
// specific listener-shape changes — the bug was unbounded growth,
|
|
109
|
+
// not a precise count. Pre-fix this would be ~16 per event type.
|
|
110
|
+
for (const ev of STDIN_EVENTS) {
|
|
111
|
+
(0, vitest_1.expect)(process.stdin.listenerCount(ev)).toBeLessThanOrEqual(2);
|
|
112
|
+
}
|
|
113
|
+
for (const ev of STDOUT_EVENTS) {
|
|
114
|
+
(0, vitest_1.expect)(process.stdout.listenerCount(ev)).toBeLessThanOrEqual(2);
|
|
115
|
+
}
|
|
116
|
+
ui.getRl().close();
|
|
117
|
+
});
|
|
118
|
+
(0, vitest_1.test)("count returns to 0 after the live rl closes", () => {
|
|
119
|
+
process.stdin.removeAllListeners("keypress");
|
|
120
|
+
const ui = new ui_state_js_1.SessionUI();
|
|
121
|
+
(0, vitest_1.expect)(process.stdin.listenerCount("keypress")).toBe(1);
|
|
122
|
+
ui.getRl().close();
|
|
123
|
+
// Node's rl.close() detaches its own keypress listener cleanly in
|
|
124
|
+
// the normal (no-raw-mode-toggle) shutdown path. This is the
|
|
125
|
+
// baseline that the bug breaks — keypress count should land at 0
|
|
126
|
+
// after close in normal teardown.
|
|
127
|
+
(0, vitest_1.expect)(process.stdin.listenerCount("keypress")).toBe(0);
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
(0, vitest_1.describe)("character-multiplication regression — ISC-7299-004", () => {
|
|
131
|
+
// Direct integration of the multiplication scenario: drive 5
|
|
132
|
+
// approval cycles, then assert that a single emitted keypress would
|
|
133
|
+
// be handled by exactly one listener. We can't observe stdout-echo
|
|
134
|
+
// counts directly under vitest (no real TTY), but the listener
|
|
135
|
+
// count IS the proximate cause — N listeners produces N+1 echo.
|
|
136
|
+
// This test wraps the listener-count guarantee in the user-visible
|
|
137
|
+
// failure-mode framing so a future regression is read as the
|
|
138
|
+
// multiplication bug it would surface as in production.
|
|
139
|
+
(0, vitest_1.test)("after 5 simulated failed tool-approval cycles, exactly one keypress handler is active", async () => {
|
|
140
|
+
process.stdin.removeAllListeners("keypress");
|
|
141
|
+
const ui = new ui_state_js_1.SessionUI();
|
|
142
|
+
for (let i = 0; i < 5; i++) {
|
|
143
|
+
await ui.promptApprovalMenu();
|
|
144
|
+
}
|
|
145
|
+
// Pre-fix observed at this point: 6 listeners → user types 'a',
|
|
146
|
+
// terminal renders 'aaaaaa'. Post-fix: 1 listener → 'a' renders
|
|
147
|
+
// exactly once.
|
|
148
|
+
(0, vitest_1.expect)(process.stdin.listenerCount("keypress")).toBe(1);
|
|
149
|
+
ui.getRl().close();
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
//# sourceMappingURL=ui_state_listener_lifecycle.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui_state_listener_lifecycle.test.js","sourceRoot":"","sources":["../../src/__tests__/ui_state_listener_lifecycle.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal ANSI → blessed {tags} converter.
|
|
3
|
+
*
|
|
4
|
+
* Pure, dependency-free, and unit-tested (see __tests__/ansi_tags.test.ts) so
|
|
5
|
+
* regressions surface when the chalk palette in display.ts changes.
|
|
6
|
+
*
|
|
7
|
+
* Supported subset (only the codes display.ts actually emits):
|
|
8
|
+
* - SGR reset \x1b[0m → {/}
|
|
9
|
+
* - dim \x1b[2m → {#45475a-fg}
|
|
10
|
+
* - bold \x1b[1m → {bold}
|
|
11
|
+
* - italic \x1b[3m → {italic}
|
|
12
|
+
* - 24-bit fg (the eight chalk truecolours below)
|
|
13
|
+
*
|
|
14
|
+
* Anything else (other SGR codes, nested/overlapping sequences, partial resets
|
|
15
|
+
* like \x1b[22m) is NOT translated — the trailing catch-all strips unrecognized
|
|
16
|
+
* `\x1b[…m` runs so raw escape bytes never leak into the blessed buffer. If a
|
|
17
|
+
* new style is added to display.ts, add its mapping here AND a test case.
|
|
18
|
+
*/
|
|
19
|
+
export declare function ansiToBlessedTags(text: string): string;
|
|
20
|
+
//# sourceMappingURL=ansi_tags.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ansi_tags.d.ts","sourceRoot":"","sources":["../src/ansi_tags.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAetD"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ansiToBlessedTags = ansiToBlessedTags;
|
|
4
|
+
/**
|
|
5
|
+
* Minimal ANSI → blessed {tags} converter.
|
|
6
|
+
*
|
|
7
|
+
* Pure, dependency-free, and unit-tested (see __tests__/ansi_tags.test.ts) so
|
|
8
|
+
* regressions surface when the chalk palette in display.ts changes.
|
|
9
|
+
*
|
|
10
|
+
* Supported subset (only the codes display.ts actually emits):
|
|
11
|
+
* - SGR reset \x1b[0m → {/}
|
|
12
|
+
* - dim \x1b[2m → {#45475a-fg}
|
|
13
|
+
* - bold \x1b[1m → {bold}
|
|
14
|
+
* - italic \x1b[3m → {italic}
|
|
15
|
+
* - 24-bit fg (the eight chalk truecolours below)
|
|
16
|
+
*
|
|
17
|
+
* Anything else (other SGR codes, nested/overlapping sequences, partial resets
|
|
18
|
+
* like \x1b[22m) is NOT translated — the trailing catch-all strips unrecognized
|
|
19
|
+
* `\x1b[…m` runs so raw escape bytes never leak into the blessed buffer. If a
|
|
20
|
+
* new style is added to display.ts, add its mapping here AND a test case.
|
|
21
|
+
*/
|
|
22
|
+
function ansiToBlessedTags(text) {
|
|
23
|
+
return text
|
|
24
|
+
.replace(/\x1b\[0m/g, "{/}")
|
|
25
|
+
.replace(/\x1b\[2m/g, "{#45475a-fg}")
|
|
26
|
+
.replace(/\x1b\[1m/g, "{bold}")
|
|
27
|
+
.replace(/\x1b\[3m/g, "{italic}")
|
|
28
|
+
.replace(/\x1b\[38;2;192;56;75m/g, "{#c0384b-fg}")
|
|
29
|
+
.replace(/\x1b\[38;2;137;180;250m/g, "{#89b4fa-fg}")
|
|
30
|
+
.replace(/\x1b\[38;2;166;227;161m/g, "{#a6e3a1-fg}")
|
|
31
|
+
.replace(/\x1b\[38;2;243;139;168m/g, "{#f38ba8-fg}")
|
|
32
|
+
.replace(/\x1b\[38;2;148;226;213m/g, "{#94e2d5-fg}")
|
|
33
|
+
.replace(/\x1b\[38;2;249;226;175m/g, "{#f9e2af-fg}")
|
|
34
|
+
.replace(/\x1b\[38;2;205;214;244m/g, "{#cdd6f4-fg}")
|
|
35
|
+
.replace(/\x1b\[38;2;108;112;134m/g, "{#6c7086-fg}")
|
|
36
|
+
.replace(/\x1b\[[0-9;]*m/g, "");
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=ansi_tags.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ansi_tags.js","sourceRoot":"","sources":["../src/ansi_tags.ts"],"names":[],"mappings":";;AAkBA,8CAeC;AAjCD;;;;;;;;;;;;;;;;;GAiBG;AACH,SAAgB,iBAAiB,CAAC,IAAY;IAC5C,OAAO,IAAI;SACR,OAAO,CAAC,WAAW,EAAE,KAAK,CAAC;SAC3B,OAAO,CAAC,WAAW,EAAE,cAAc,CAAC;SACpC,OAAO,CAAC,WAAW,EAAE,QAAQ,CAAC;SAC9B,OAAO,CAAC,WAAW,EAAE,UAAU,CAAC;SAChC,OAAO,CAAC,wBAAwB,EAAE,cAAc,CAAC;SACjD,OAAO,CAAC,0BAA0B,EAAE,cAAc,CAAC;SACnD,OAAO,CAAC,0BAA0B,EAAE,cAAc,CAAC;SACnD,OAAO,CAAC,0BAA0B,EAAE,cAAc,CAAC;SACnD,OAAO,CAAC,0BAA0B,EAAE,cAAc,CAAC;SACnD,OAAO,CAAC,0BAA0B,EAAE,cAAc,CAAC;SACnD,OAAO,CAAC,0BAA0B,EAAE,cAAc,CAAC;SACnD,OAAO,CAAC,0BAA0B,EAAE,cAAc,CAAC;SACnD,OAAO,CAAC,iBAAiB,EAAE,EAAE,CAAC,CAAC;AACpC,CAAC"}
|
package/dist/config.d.ts
CHANGED
|
@@ -30,5 +30,5 @@ export declare const WS_URL: string;
|
|
|
30
30
|
* MUST stay in sync with `version` in package.json; the drift-guard
|
|
31
31
|
* test in `__tests__/legacy_compat.test.ts` enforces it.
|
|
32
32
|
*/
|
|
33
|
-
export declare const CLI_VERSION = "0.5.
|
|
33
|
+
export declare const CLI_VERSION = "0.5.2";
|
|
34
34
|
//# sourceMappingURL=config.d.ts.map
|
package/dist/config.js
CHANGED
|
@@ -42,5 +42,5 @@ exports.WS_URL = toWsUrl(exports.ORCHESTRATOR_URL);
|
|
|
42
42
|
* MUST stay in sync with `version` in package.json; the drift-guard
|
|
43
43
|
* test in `__tests__/legacy_compat.test.ts` enforces it.
|
|
44
44
|
*/
|
|
45
|
-
exports.CLI_VERSION = "0.5.
|
|
45
|
+
exports.CLI_VERSION = "0.5.2";
|
|
46
46
|
//# sourceMappingURL=config.js.map
|
package/dist/display.d.ts
CHANGED
|
@@ -1,30 +1,61 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Output formatting — streaming text, session list,
|
|
2
|
+
* Output formatting — streaming text, session list, status bar, tool lines.
|
|
3
|
+
*
|
|
4
|
+
* SPRINT-CLI-UX-POLISH-5:
|
|
5
|
+
* - Thinking spinner (animates between submit and first token)
|
|
6
|
+
* - Animated tool lines (spinner → ✓ with elapsed on completion)
|
|
7
|
+
* - Diff view for write_file tool calls
|
|
8
|
+
* - Approval prompt styled as yellow bordered box
|
|
9
|
+
* - Keyboard shortcut bar shown ONCE on welcome only
|
|
10
|
+
* - Session resume shows last message preview
|
|
11
|
+
* - "Xiaotime Labs" wordmark in status bar
|
|
12
|
+
* - Word-wrap at terminal width (no mid-word cuts)
|
|
13
|
+
* - Code fence double-render fix
|
|
14
|
+
* - Sticky bottom status bar (no bg, connected dot, turn counter, last tool)
|
|
15
|
+
* - No cost in status bar
|
|
16
|
+
* - Double-border input box (╭─╮ top, you › inside, ╰─╯ on submit)
|
|
17
|
+
* - Red user/Junior text (#c0384b)
|
|
18
|
+
* - Claude Code-style turn headers (Junior ›)
|
|
19
|
+
* - Code blocks with full-width border + language tag
|
|
20
|
+
* - Turn separators between responses
|
|
21
|
+
* - Tool call lines with elapsed time + icons
|
|
22
|
+
*
|
|
23
|
+
* SPRINT-CLI-UX-POLISH-6:
|
|
24
|
+
* - Restored "Junior is thinking..." label.
|
|
25
|
+
* - Inline code backtick spans get subtle background tint
|
|
26
|
+
* - Auto-detect file paths in output — underlined + OSC 8 hyperlinks (iTerm2/Termius)
|
|
27
|
+
* - Tool call errors render as red-bordered box instead of inline text
|
|
28
|
+
* - Removed "Junior is thinking..." spinner label
|
|
3
29
|
*/
|
|
4
30
|
import type { Session } from "./session.js";
|
|
5
|
-
export declare function
|
|
31
|
+
export declare function initStatusBar(sessionId: string, sessionName: string | null, tenant?: string): void;
|
|
32
|
+
export declare function setConnected(connected: boolean): void;
|
|
33
|
+
export declare function incrementTurn(): void;
|
|
34
|
+
export declare function setLastTool(toolName: string): void;
|
|
35
|
+
export declare function updateStatusBarCost(_turnCostUsd: number): void;
|
|
36
|
+
export declare function startSpinner(label: string): void;
|
|
37
|
+
export declare function stopSpinner(finalLabel?: string, success?: boolean): void;
|
|
38
|
+
export declare function startToolLine(name: string, detail: string): void;
|
|
39
|
+
export declare function finishToolLine(success?: boolean, errorMessage?: string): void;
|
|
40
|
+
export declare function printToolError(toolName: string, errorMessage: string, durationMs?: number): void;
|
|
41
|
+
export declare function printFileDiff(path: string, before: string | null, after: string): void;
|
|
42
|
+
export declare function printApprovalPrompt(title: string, body: string): void;
|
|
6
43
|
export declare function printTextDelta(text: string): void;
|
|
44
|
+
export declare function printTurnStart(): void;
|
|
45
|
+
export declare function printThinkingStart(): void;
|
|
46
|
+
export declare function printThinkingStop(): void;
|
|
7
47
|
export declare function printTurnEnd(costUsd: number): void;
|
|
48
|
+
export declare function consumeFirstPrompt(): boolean;
|
|
49
|
+
export declare function printPrompt(showHint?: boolean): void;
|
|
50
|
+
export declare function printPromptEnd(): void;
|
|
51
|
+
export declare function printWelcome(sessionId: string, sessionName: string | null, resumed: boolean, messageCount: number, lastMessagePreview?: string): void;
|
|
8
52
|
export declare function printError(message: string): void;
|
|
9
53
|
export declare function printSessionList(sessions: Session[]): void;
|
|
10
|
-
export declare function
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
* `server_tool_call` WS event the orchestrator now emits before each
|
|
18
|
-
* server-side dispatch, matching the visual style of the existing
|
|
19
|
-
* client-tool inline logs in cli/src/tools.ts (`[read_file] /path
|
|
20
|
-
* (N lines)`, `[git_status]`, etc.).
|
|
21
|
-
*
|
|
22
|
-
* `inputSummary` is built server-side (see
|
|
23
|
-
* `terminal_orchestrator/main.py::_build_server_tool_input_summary`)
|
|
24
|
-
* — ≤120 chars, preferred-keys-per-tool, middle-truncated values,
|
|
25
|
-
* no newlines. Empty inputSummary (e.g. librarian_list_collections,
|
|
26
|
-
* which has no meaningful input to render) drops to just the
|
|
27
|
-
* `[server:<name>]` prefix.
|
|
28
|
-
*/
|
|
29
|
-
export declare function printServerToolCall(name: string, inputSummary: string): void;
|
|
54
|
+
export declare function friendlyToolLabel(name: string): string;
|
|
55
|
+
export declare function friendlyError(raw: string): string;
|
|
56
|
+
export declare function printHelp(): void;
|
|
57
|
+
export declare function printDisconnectBanner(reconnecting?: boolean): void;
|
|
58
|
+
export declare function printExitConfirmation(): void;
|
|
59
|
+
export declare function printToolCallLine(name: string, detail: string, durationMs?: number, success?: boolean): void;
|
|
60
|
+
export declare function printServerToolCall(name: string, inputSummary: string, durationMs?: number): void;
|
|
30
61
|
//# sourceMappingURL=display.d.ts.map
|
package/dist/display.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"display.d.ts","sourceRoot":"","sources":["../src/display.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"display.d.ts","sourceRoot":"","sources":["../src/display.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAIH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAoP5C,wBAAgB,aAAa,CAC3B,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,GAAG,IAAI,EAC1B,MAAM,CAAC,EAAE,MAAM,QAQhB;AAED,wBAAgB,YAAY,CAAC,SAAS,EAAE,OAAO,QAG9C;AAED,wBAAgB,aAAa,SAG5B;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,QAG3C;AAED,wBAAgB,mBAAmB,CAAC,YAAY,EAAE,MAAM,QAEvD;AAgBD,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAYhD;AAED,wBAAgB,WAAW,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,OAAO,UAAO,GAAG,IAAI,CAWrE;AAgBD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAoBhE;AAED,wBAAgB,cAAc,CAAC,OAAO,UAAO,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAoB1E;AAMD,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAuBhG;AAMD,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,GAAG,IAAI,EACrB,KAAK,EAAE,MAAM,GACZ,IAAI,CA4CN;AAMD,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,GACX,IAAI,CAsBN;AAYD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,QAc1C;AA2DD,wBAAgB,cAAc,SAS7B;AAED,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC;AAED,wBAAgB,iBAAiB,IAAI,IAAI,CAExC;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,QAkB3C;AAYD,wBAAgB,kBAAkB,IAAI,OAAO,CAI5C;AAED,wBAAgB,WAAW,CAAC,QAAQ,UAAQ,QAiB3C;AAED,wBAAgB,cAAc,SAO7B;AAMD,wBAAgB,YAAY,CAC1B,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,GAAG,IAAI,EAC1B,OAAO,EAAE,OAAO,EAChB,YAAY,EAAE,MAAM,EACpB,kBAAkB,CAAC,EAAE,MAAM,QA6C5B;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,QAOzC;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,OAAO,EAAE,QAmCnD;AAyED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEtD;AAkBD,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAOjD;AAMD,wBAAgB,SAAS,IAAI,IAAI,CAmChC;AAMD,wBAAgB,qBAAqB,CAAC,YAAY,UAAO,GAAG,IAAI,CAK/D;AAMD,wBAAgB,qBAAqB,IAAI,IAAI,CAG5C;AAED,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,UAAU,CAAC,EAAE,MAAM,EACnB,OAAO,UAAO,QASf;AAED,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,MAAM,EACpB,UAAU,CAAC,EAAE,MAAM,GAClB,IAAI,CAQN"}
|