@duetso/agent 0.1.80 → 0.1.82
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/package.json +1 -1
- package/dist/src/memory/observational.d.ts +8 -1
- package/dist/src/memory/observational.d.ts.map +1 -1
- package/dist/src/memory/observational.js +9 -3
- package/dist/src/memory/observational.js.map +1 -1
- package/dist/src/session/session.d.ts +31 -13
- package/dist/src/session/session.d.ts.map +1 -1
- package/dist/src/session/session.js +63 -23
- package/dist/src/session/session.js.map +1 -1
- package/dist/src/tui/app.d.ts +25 -35
- package/dist/src/tui/app.d.ts.map +1 -1
- package/dist/src/tui/app.js +195 -2308
- package/dist/src/tui/app.js.map +1 -1
- package/dist/src/tui/autocomplete-controller.d.ts +83 -0
- package/dist/src/tui/autocomplete-controller.d.ts.map +1 -0
- package/dist/src/tui/autocomplete-controller.js +308 -0
- package/dist/src/tui/autocomplete-controller.js.map +1 -0
- package/dist/src/tui/boot-screen.d.ts +64 -0
- package/dist/src/tui/boot-screen.d.ts.map +1 -0
- package/dist/src/tui/boot-screen.js +137 -0
- package/dist/src/tui/boot-screen.js.map +1 -0
- package/dist/src/tui/controllers.d.ts +39 -0
- package/dist/src/tui/controllers.d.ts.map +1 -0
- package/dist/src/tui/controllers.js +53 -0
- package/dist/src/tui/controllers.js.map +1 -0
- package/dist/src/tui/copy-controller.d.ts +75 -0
- package/dist/src/tui/copy-controller.d.ts.map +1 -0
- package/dist/src/tui/copy-controller.js +140 -0
- package/dist/src/tui/copy-controller.js.map +1 -0
- package/dist/src/tui/history-replay.d.ts +33 -0
- package/dist/src/tui/history-replay.d.ts.map +1 -0
- package/dist/src/tui/history-replay.js +47 -0
- package/dist/src/tui/history-replay.js.map +1 -0
- package/dist/src/tui/initial-prompt.d.ts +24 -0
- package/dist/src/tui/initial-prompt.d.ts.map +1 -0
- package/dist/src/tui/initial-prompt.js +29 -0
- package/dist/src/tui/initial-prompt.js.map +1 -0
- package/dist/src/tui/key-handlers.d.ts +49 -0
- package/dist/src/tui/key-handlers.d.ts.map +1 -0
- package/dist/src/tui/key-handlers.js +192 -0
- package/dist/src/tui/key-handlers.js.map +1 -0
- package/dist/src/tui/layout.d.ts +71 -0
- package/dist/src/tui/layout.d.ts.map +1 -0
- package/dist/src/tui/layout.js +245 -0
- package/dist/src/tui/layout.js.map +1 -0
- package/dist/src/tui/paste-controller.d.ts +90 -0
- package/dist/src/tui/paste-controller.d.ts.map +1 -0
- package/dist/src/tui/paste-controller.js +234 -0
- package/dist/src/tui/paste-controller.js.map +1 -0
- package/dist/src/tui/question-picker.d.ts +111 -0
- package/dist/src/tui/question-picker.d.ts.map +1 -0
- package/dist/src/tui/question-picker.js +308 -0
- package/dist/src/tui/question-picker.js.map +1 -0
- package/dist/src/tui/renderer-lifecycle.d.ts +20 -0
- package/dist/src/tui/renderer-lifecycle.d.ts.map +1 -0
- package/dist/src/tui/renderer-lifecycle.js +50 -0
- package/dist/src/tui/renderer-lifecycle.js.map +1 -0
- package/dist/src/tui/session-subscription.d.ts +30 -0
- package/dist/src/tui/session-subscription.d.ts.map +1 -0
- package/dist/src/tui/session-subscription.js +78 -0
- package/dist/src/tui/session-subscription.js.map +1 -0
- package/dist/src/tui/sidebar.d.ts +2 -2
- package/dist/src/tui/sidebar.d.ts.map +1 -1
- package/dist/src/tui/sidebar.js +1 -1
- package/dist/src/tui/sidebar.js.map +1 -1
- package/dist/src/tui/slash-commands.d.ts +23 -0
- package/dist/src/tui/slash-commands.d.ts.map +1 -0
- package/dist/src/tui/slash-commands.js +79 -0
- package/dist/src/tui/slash-commands.js.map +1 -0
- package/dist/src/tui/starter-section.d.ts +99 -0
- package/dist/src/tui/starter-section.d.ts.map +1 -0
- package/dist/src/tui/starter-section.js +254 -0
- package/dist/src/tui/starter-section.js.map +1 -0
- package/dist/src/tui/status-controller.d.ts +94 -0
- package/dist/src/tui/status-controller.d.ts.map +1 -0
- package/dist/src/tui/status-controller.js +186 -0
- package/dist/src/tui/status-controller.js.map +1 -0
- package/dist/src/tui/step-renderer.d.ts +55 -0
- package/dist/src/tui/step-renderer.d.ts.map +1 -0
- package/dist/src/tui/step-renderer.js +246 -0
- package/dist/src/tui/step-renderer.js.map +1 -0
- package/dist/src/tui/transcript-writer.d.ts +63 -0
- package/dist/src/tui/transcript-writer.d.ts.map +1 -0
- package/dist/src/tui/transcript-writer.js +130 -0
- package/dist/src/tui/transcript-writer.js.map +1 -0
- package/dist/src/turn-runner/turn-runner.d.ts +77 -1
- package/dist/src/turn-runner/turn-runner.d.ts.map +1 -1
- package/dist/src/turn-runner/turn-runner.js +150 -12
- package/dist/src/turn-runner/turn-runner.js.map +1 -1
- package/dist/src/turn-runner/usage-accounting.d.ts +18 -1
- package/dist/src/turn-runner/usage-accounting.d.ts.map +1 -1
- package/dist/src/turn-runner/usage-accounting.js +48 -27
- package/dist/src/turn-runner/usage-accounting.js.map +1 -1
- package/dist/src/types/protocol.d.ts +48 -17
- package/dist/src/types/protocol.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { HINT_IDLE, HINT_RUNNING, HINT_SELECTION_COPY } from "./theme.js";
|
|
2
|
+
import { isTextBufferDestroyedError } from "./transcript-writer.js";
|
|
3
|
+
/**
|
|
4
|
+
* Owns the "is a turn running?" surface of the TUI: the working-status line,
|
|
5
|
+
* the bottom hint row, and the 1 s ticker that advances both while a turn is
|
|
6
|
+
* in flight. Also remembers the most recent terminal event so `runTui` can
|
|
7
|
+
* return it to the caller after the renderer is destroyed.
|
|
8
|
+
*
|
|
9
|
+
* Preserves the v0.1.68 dual-mechanism guard against the OpenTUI race where
|
|
10
|
+
* child TextBuffers are destroyed synchronously *before* the `destroy` event
|
|
11
|
+
* fires: writes short-circuit on `destroyed`, and a `try/catch` around the
|
|
12
|
+
* actual buffer mutation swallows the late-arriving exception and tears down
|
|
13
|
+
* the ticker so the next callback does not throw again.
|
|
14
|
+
*/
|
|
15
|
+
export class StatusController {
|
|
16
|
+
opts;
|
|
17
|
+
destroyed = false;
|
|
18
|
+
running = false;
|
|
19
|
+
workingStartedAt;
|
|
20
|
+
workingTicker;
|
|
21
|
+
workingMessage = "working…";
|
|
22
|
+
queuedFollowUps = 0;
|
|
23
|
+
pendingImageCount = 0;
|
|
24
|
+
lastSelectionText = "";
|
|
25
|
+
terminal;
|
|
26
|
+
constructor(opts) {
|
|
27
|
+
this.opts = opts;
|
|
28
|
+
}
|
|
29
|
+
isRunning() {
|
|
30
|
+
return this.running;
|
|
31
|
+
}
|
|
32
|
+
lastTerminal() {
|
|
33
|
+
return this.terminal;
|
|
34
|
+
}
|
|
35
|
+
/** Wall-clock start of the current turn, or undefined while idle. Read by
|
|
36
|
+
* the "● turn finished in Ns" and sleep banners which live outside this
|
|
37
|
+
* controller but want to show the same elapsed counter. */
|
|
38
|
+
getWorkingStartedAt() {
|
|
39
|
+
return this.workingStartedAt;
|
|
40
|
+
}
|
|
41
|
+
setWorkingMessage(message) {
|
|
42
|
+
this.workingMessage = message;
|
|
43
|
+
this.refreshWorkingStatus();
|
|
44
|
+
}
|
|
45
|
+
setQueuedFollowUps(count) {
|
|
46
|
+
this.queuedFollowUps = count;
|
|
47
|
+
this.refreshWorkingStatus();
|
|
48
|
+
}
|
|
49
|
+
/** Mirror of the most recent drag-selection text. Stored here so the hint
|
|
50
|
+
* row can advertise the copy keystroke only while something is selectable;
|
|
51
|
+
* the canonical selection state lives in `runTui`. */
|
|
52
|
+
setSelectionText(text) {
|
|
53
|
+
this.lastSelectionText = text;
|
|
54
|
+
this.refreshHint();
|
|
55
|
+
}
|
|
56
|
+
/** Mirror of `pendingImages.length`. Stored here so the hint row can show
|
|
57
|
+
* the attachment count without dragging the whole `PendingImage[]` into
|
|
58
|
+
* the controller. */
|
|
59
|
+
setPendingImageCount(count) {
|
|
60
|
+
this.pendingImageCount = count;
|
|
61
|
+
this.refreshHint();
|
|
62
|
+
}
|
|
63
|
+
markRunning() {
|
|
64
|
+
this.running = true;
|
|
65
|
+
this.workingMessage = "working…";
|
|
66
|
+
this.workingStartedAt = Date.now();
|
|
67
|
+
this.refreshHint();
|
|
68
|
+
this.refreshWorkingStatus();
|
|
69
|
+
this.startWorkingTicker();
|
|
70
|
+
}
|
|
71
|
+
/** Settle the working-status surface and optionally record the terminal
|
|
72
|
+
* event that ended the turn. The terminal is exposed via `lastTerminal()`
|
|
73
|
+
* so `runTui` can return it to its caller after renderer teardown. */
|
|
74
|
+
markIdle(terminal) {
|
|
75
|
+
if (terminal !== undefined)
|
|
76
|
+
this.terminal = terminal;
|
|
77
|
+
this.running = false;
|
|
78
|
+
this.stopWorkingTicker();
|
|
79
|
+
this.workingStartedAt = undefined;
|
|
80
|
+
this.workingMessage = "working…";
|
|
81
|
+
this.refreshHint();
|
|
82
|
+
this.refreshWorkingStatus();
|
|
83
|
+
}
|
|
84
|
+
setStatus(text) {
|
|
85
|
+
// Renderer teardown destroys the underlying TextBuffer synchronously, but
|
|
86
|
+
// in-flight async work (session events, ticker callbacks, upgrade-status
|
|
87
|
+
// pushes) may still drive chrome updates on the next microtask. The
|
|
88
|
+
// `destroyed` flag catches writes after our destroy handler runs; the
|
|
89
|
+
// try/catch backstops the window between OpenTUI tearing down child
|
|
90
|
+
// TextBuffers and emitting the `destroy` event, which is when the ticker
|
|
91
|
+
// callback typically lands.
|
|
92
|
+
if (this.destroyed)
|
|
93
|
+
return;
|
|
94
|
+
try {
|
|
95
|
+
this.opts.status.content = text;
|
|
96
|
+
}
|
|
97
|
+
catch (error) {
|
|
98
|
+
if (isTextBufferDestroyedError(error)) {
|
|
99
|
+
this.shutdown();
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
throw error;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/** Recompose the bottom hint row from the controller's current running
|
|
106
|
+
* state plus any active attachment / selection segments. Called from any
|
|
107
|
+
* input that changes a hint segment (attachments, selection) and from
|
|
108
|
+
* the running-state transitions in `markRunning` / `markIdle`. */
|
|
109
|
+
refreshHint() {
|
|
110
|
+
if (this.destroyed)
|
|
111
|
+
return;
|
|
112
|
+
const base = this.running ? HINT_RUNNING : HINT_IDLE;
|
|
113
|
+
const segments = [];
|
|
114
|
+
if (this.pendingImageCount > 0)
|
|
115
|
+
segments.push(this.attachmentHint());
|
|
116
|
+
segments.push(base);
|
|
117
|
+
if (this.lastSelectionText.trim().length > 0)
|
|
118
|
+
segments.push(HINT_SELECTION_COPY);
|
|
119
|
+
try {
|
|
120
|
+
this.opts.hint.content = segments.join(" · ");
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
if (isTextBufferDestroyedError(error)) {
|
|
124
|
+
this.shutdown();
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
throw error;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
refreshWorkingStatus() {
|
|
131
|
+
if (this.destroyed)
|
|
132
|
+
return;
|
|
133
|
+
this.opts.refreshActiveToolBlocks();
|
|
134
|
+
if (this.workingStartedAt === undefined) {
|
|
135
|
+
this.setStatus(this.queuedFollowUps > 0 ? `queued follow-ups: ${this.queuedFollowUps}` : "");
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
const elapsed = formatElapsed(Date.now() - this.workingStartedAt);
|
|
139
|
+
const queued = this.queuedFollowUps > 0 ? ` · queued follow-ups: ${this.queuedFollowUps}` : "";
|
|
140
|
+
this.setStatus(`● ${this.workingMessage} (${elapsed})${queued}`);
|
|
141
|
+
}
|
|
142
|
+
/** Flip the destroyed flag and stop the ticker. Invoked from the renderer
|
|
143
|
+
* destroy handler and from our own try/catch when a buffer write fires the
|
|
144
|
+
* destroyed-buffer guard mid-flight. Subsequent chrome writes no-op. */
|
|
145
|
+
shutdown() {
|
|
146
|
+
this.destroyed = true;
|
|
147
|
+
this.stopWorkingTicker();
|
|
148
|
+
}
|
|
149
|
+
startWorkingTicker() {
|
|
150
|
+
if (this.workingTicker !== undefined)
|
|
151
|
+
return;
|
|
152
|
+
this.workingTicker = setInterval(() => this.refreshWorkingStatus(), 1000);
|
|
153
|
+
}
|
|
154
|
+
stopWorkingTicker() {
|
|
155
|
+
if (this.workingTicker !== undefined) {
|
|
156
|
+
clearInterval(this.workingTicker);
|
|
157
|
+
this.workingTicker = undefined;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
attachmentHint() {
|
|
161
|
+
const n = this.pendingImageCount;
|
|
162
|
+
return n === 1 ? "📎 1 image attached" : `📎 ${n} images attached`;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Renders an elapsed millisecond span as `${seconds}s` below a minute, and
|
|
167
|
+
* `${minutes}m ${seconds}s` past it. Exported because the tool-call finalizer
|
|
168
|
+
* and the post-turn banners share the same format.
|
|
169
|
+
*/
|
|
170
|
+
export function formatElapsed(ms) {
|
|
171
|
+
const totalSeconds = Math.max(0, Math.floor(ms / 1000));
|
|
172
|
+
if (totalSeconds < 60)
|
|
173
|
+
return `${totalSeconds}s`;
|
|
174
|
+
const minutes = Math.floor(totalSeconds / 60);
|
|
175
|
+
const seconds = totalSeconds % 60;
|
|
176
|
+
return `${minutes}m ${seconds}s`;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Spinner marker for an in-flight tool call. Sub-second runs drop the
|
|
180
|
+
* elapsed counter so a transcript of fast tools is not littered with "0s"
|
|
181
|
+
* markers.
|
|
182
|
+
*/
|
|
183
|
+
export function runningMarker(elapsedMs) {
|
|
184
|
+
return elapsedMs >= 1000 ? `⏳ ${formatElapsed(elapsedMs)}` : "⏳";
|
|
185
|
+
}
|
|
186
|
+
//# sourceMappingURL=status-controller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status-controller.js","sourceRoot":"","sources":["../../../src/tui/status-controller.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { type CliRenderer, type ScrollBoxRenderable } from "@opentui/core";
|
|
2
|
+
import { StatusController } from "./status-controller.js";
|
|
3
|
+
import { TranscriptWriter } from "./transcript-writer.js";
|
|
4
|
+
import type { TurnEvent, TurnStep, TurnTokenUsage } from "../types/protocol.js";
|
|
5
|
+
export interface StepRendererOptions {
|
|
6
|
+
renderer: CliRenderer;
|
|
7
|
+
transcript: ScrollBoxRenderable;
|
|
8
|
+
transcriptWriter: TranscriptWriter;
|
|
9
|
+
statusController: StatusController;
|
|
10
|
+
/** Invoked at the start of `renderStep` so a stale question picker
|
|
11
|
+
* panel is dismissed before the next agent activity lands; the next
|
|
12
|
+
* step supersedes the open question. */
|
|
13
|
+
onStepStart?: () => void;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Renders the streaming surface of a turn: text deltas, reasoning deltas,
|
|
17
|
+
* tool-call blocks (live spinner → ✓/✗), memory phase banners, and the
|
|
18
|
+
* post-turn usage / elapsed / sleep lines.
|
|
19
|
+
*
|
|
20
|
+
* Owns the in-flight stream/tool-block bookkeeping so the StatusController
|
|
21
|
+
* ticker can call `refreshActiveToolBlocks()` to advance spinners without
|
|
22
|
+
* cracking open the renderer state.
|
|
23
|
+
*/
|
|
24
|
+
export declare class StepRenderer {
|
|
25
|
+
private readonly opts;
|
|
26
|
+
private activeTextStream;
|
|
27
|
+
private activeReasoningStream;
|
|
28
|
+
private readonly activeToolBlocks;
|
|
29
|
+
constructor(opts: StepRendererOptions);
|
|
30
|
+
renderStep(step: TurnStep): void;
|
|
31
|
+
/** Repaint every in-flight tool block header with a fresh spinner +
|
|
32
|
+
* elapsed counter. Invoked from StatusController's 1 s ticker so the
|
|
33
|
+
* spinner column advances in step with the working-status line. */
|
|
34
|
+
refreshActiveToolBlocks(): void;
|
|
35
|
+
renderUsage(usage?: TurnTokenUsage): void;
|
|
36
|
+
renderTurnElapsed(): void;
|
|
37
|
+
renderSleeping(wakeAt: number): void;
|
|
38
|
+
renderMemoryStatus(event: Extract<TurnEvent, {
|
|
39
|
+
type: "memory";
|
|
40
|
+
}>): void;
|
|
41
|
+
private renderDelta;
|
|
42
|
+
private renderToolCall;
|
|
43
|
+
private finalizeToolCall;
|
|
44
|
+
private finalizeDelta;
|
|
45
|
+
private toolBlockColumns;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Format the body of a memory phase event for display. Returns the empty
|
|
49
|
+
* string when there are no observations or usage bumps to show, so the
|
|
50
|
+
* caller can elide the block entirely.
|
|
51
|
+
*/
|
|
52
|
+
export declare function formatMemoryEventBody(event: Extract<TurnEvent, {
|
|
53
|
+
type: "memory";
|
|
54
|
+
}>): string;
|
|
55
|
+
//# sourceMappingURL=step-renderer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"step-renderer.d.ts","sourceRoot":"","sources":["../../../src/tui/step-renderer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,mBAAmB,EAAkB,MAAM,eAAe,CAAC;AAC3F,OAAO,EAAgC,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAIxF,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAiChF,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,WAAW,CAAC;IACtB,UAAU,EAAE,mBAAmB,CAAC;IAChC,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,gBAAgB,EAAE,gBAAgB,CAAC;IACnC;;6CAEyC;IACzC,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;CAC1B;AAED;;;;;;;;GAQG;AACH,qBAAa,YAAY;IAQX,OAAO,CAAC,QAAQ,CAAC,IAAI;IAPjC,OAAO,CAAC,gBAAgB,CAA6B;IACrD,OAAO,CAAC,qBAAqB,CAA6B;IAI1D,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAgC;gBAEpC,IAAI,EAAE,mBAAmB;IAEtD,UAAU,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI;IA+ChC;;wEAEoE;IACpE,uBAAuB,IAAI,IAAI;IAa/B,WAAW,CAAC,KAAK,CAAC,EAAE,cAAc,GAAG,IAAI;IAwBzC,iBAAiB,IAAI,IAAI;IAazB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAWpC,kBAAkB,CAAC,KAAK,EAAE,OAAO,CAAC,SAAS,EAAE;QAAE,IAAI,EAAE,QAAQ,CAAA;KAAE,CAAC,GAAG,IAAI;IAcvE,OAAO,CAAC,WAAW;IAgCnB,OAAO,CAAC,cAAc;IA2CtB,OAAO,CAAC,gBAAgB;IAqBxB,OAAO,CAAC,aAAa;IAUrB,OAAO,CAAC,gBAAgB;CAIzB;AAOD;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,CAAC,SAAS,EAAE;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAC,GAAG,MAAM,CAa3F"}
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
import { TextRenderable } from "@opentui/core";
|
|
2
|
+
import { formatElapsed, runningMarker } from "./status-controller.js";
|
|
3
|
+
import { SIDEBAR_WIDTH } from "./sidebar.js";
|
|
4
|
+
import { COLORS } from "./theme.js";
|
|
5
|
+
import { assembleToolBlock, formatToolBlock, truncateToolText } from "./tool-formatters.js";
|
|
6
|
+
/**
|
|
7
|
+
* Renders the streaming surface of a turn: text deltas, reasoning deltas,
|
|
8
|
+
* tool-call blocks (live spinner → ✓/✗), memory phase banners, and the
|
|
9
|
+
* post-turn usage / elapsed / sleep lines.
|
|
10
|
+
*
|
|
11
|
+
* Owns the in-flight stream/tool-block bookkeeping so the StatusController
|
|
12
|
+
* ticker can call `refreshActiveToolBlocks()` to advance spinners without
|
|
13
|
+
* cracking open the renderer state.
|
|
14
|
+
*/
|
|
15
|
+
export class StepRenderer {
|
|
16
|
+
opts;
|
|
17
|
+
activeTextStream;
|
|
18
|
+
activeReasoningStream;
|
|
19
|
+
// Tool calls fire twice (running → completed/error). Track the rendered
|
|
20
|
+
// block by toolCallId so the second event updates the same line in place
|
|
21
|
+
// instead of pushing a separate block.
|
|
22
|
+
activeToolBlocks = new Map();
|
|
23
|
+
constructor(opts) {
|
|
24
|
+
this.opts = opts;
|
|
25
|
+
}
|
|
26
|
+
renderStep(step) {
|
|
27
|
+
this.opts.onStepStart?.();
|
|
28
|
+
if (step.type === "text_delta") {
|
|
29
|
+
this.activeTextStream = this.renderDelta(this.activeTextStream, null, step.delta, COLORS.agent);
|
|
30
|
+
}
|
|
31
|
+
else if (step.type === "reasoning_delta") {
|
|
32
|
+
this.activeReasoningStream = this.renderDelta(this.activeReasoningStream, "[reasoning]", step.delta, COLORS.reasoning, true);
|
|
33
|
+
}
|
|
34
|
+
else if (step.type === "text") {
|
|
35
|
+
this.opts.transcriptWriter.recordEntry("agent", step.text);
|
|
36
|
+
if (this.activeTextStream) {
|
|
37
|
+
this.finalizeDelta(this.activeTextStream, step.text);
|
|
38
|
+
this.activeTextStream = undefined;
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
this.opts.transcriptWriter.appendBlock(null, step.text, COLORS.agent);
|
|
42
|
+
}
|
|
43
|
+
else if (step.type === "reasoning") {
|
|
44
|
+
const trimmed = step.text.trim();
|
|
45
|
+
if (this.activeReasoningStream) {
|
|
46
|
+
this.finalizeDelta(this.activeReasoningStream, trimmed);
|
|
47
|
+
this.activeReasoningStream = undefined;
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (trimmed) {
|
|
51
|
+
this.opts.transcriptWriter.appendBlock("[reasoning]", truncateToolText(trimmed), COLORS.reasoning);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
else if (step.type === "tool_call") {
|
|
55
|
+
this.renderToolCall(step);
|
|
56
|
+
}
|
|
57
|
+
else if (step.type === "system") {
|
|
58
|
+
this.opts.transcriptWriter.appendBlock("[system]", step.message, COLORS.system);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/** Repaint every in-flight tool block header with a fresh spinner +
|
|
62
|
+
* elapsed counter. Invoked from StatusController's 1 s ticker so the
|
|
63
|
+
* spinner column advances in step with the working-status line. */
|
|
64
|
+
refreshActiveToolBlocks() {
|
|
65
|
+
if (this.activeToolBlocks.size === 0)
|
|
66
|
+
return;
|
|
67
|
+
const columns = this.toolBlockColumns();
|
|
68
|
+
for (const block of this.activeToolBlocks.values()) {
|
|
69
|
+
if (block.startedAt === undefined)
|
|
70
|
+
continue;
|
|
71
|
+
block.line.content = assembleToolBlock({ header: block.header, body: block.body || undefined }, runningMarker(Date.now() - block.startedAt), { columns });
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
renderUsage(usage) {
|
|
75
|
+
if (!usage)
|
|
76
|
+
return;
|
|
77
|
+
// Cumulative cost is updated on the session when the terminal event is
|
|
78
|
+
// handled; sidebar refreshes from `getSessionCostUsd()` via `refreshSidebar`.
|
|
79
|
+
// Tokens stay terse (just in/out) since the cost breakdown below is
|
|
80
|
+
// where the cache wins actually matter. Cost is split across all four
|
|
81
|
+
// buckets (in / out / cache read / cache write) so prompt-cache hits and
|
|
82
|
+
// writes are visible at a glance; zero buckets collapse out.
|
|
83
|
+
const tokens = `Tokens: in=${usage.input} out=${usage.output}`;
|
|
84
|
+
const costParts = [
|
|
85
|
+
["in", usage.cost.input],
|
|
86
|
+
["out", usage.cost.output],
|
|
87
|
+
["cr", usage.cost.cacheRead],
|
|
88
|
+
["cw", usage.cost.cacheWrite],
|
|
89
|
+
]
|
|
90
|
+
.filter(([, value]) => value > 0)
|
|
91
|
+
.map(([label, value]) => `${label}=$${value.toFixed(4)}`);
|
|
92
|
+
const cost = usage.cost.total === 0
|
|
93
|
+
? ""
|
|
94
|
+
: ` · Cost: $${usage.cost.total.toFixed(4)}${costParts.length > 1 ? ` (${costParts.join(" ")})` : ""}`;
|
|
95
|
+
this.opts.transcriptWriter.appendLine(`[usage] ${tokens}${cost}`, COLORS.hint);
|
|
96
|
+
}
|
|
97
|
+
renderTurnElapsed() {
|
|
98
|
+
const startedAt = this.opts.statusController.getWorkingStartedAt();
|
|
99
|
+
if (startedAt === undefined)
|
|
100
|
+
return;
|
|
101
|
+
this.opts.transcriptWriter.appendLine(`● turn finished in ${formatElapsed(Date.now() - startedAt)}`, COLORS.status);
|
|
102
|
+
}
|
|
103
|
+
// Sleep terminals replace the usual "turn finished" line because the session
|
|
104
|
+
// is going back to sleep, not wrapping up. When a turn ran before the sleep
|
|
105
|
+
// (e.g. an injected prompt while waiting on a state machine), include its
|
|
106
|
+
// duration so the user can still see how long the work took.
|
|
107
|
+
renderSleeping(wakeAt) {
|
|
108
|
+
const wakeLabel = new Date(wakeAt).toLocaleTimeString();
|
|
109
|
+
const startedAt = this.opts.statusController.getWorkingStartedAt();
|
|
110
|
+
const turnDuration = startedAt === undefined ? "" : ` · turn took ${formatElapsed(Date.now() - startedAt)}`;
|
|
111
|
+
this.opts.transcriptWriter.appendLine(`● sleeping until ${wakeLabel}${turnDuration}`, COLORS.status);
|
|
112
|
+
}
|
|
113
|
+
renderMemoryStatus(event) {
|
|
114
|
+
if (event.status === "running") {
|
|
115
|
+
this.opts.statusController.setWorkingMessage(event.message);
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
const body = formatMemoryEventBody(event);
|
|
119
|
+
if (body) {
|
|
120
|
+
this.opts.transcriptWriter.appendBlock(`[memory:${event.phase}]`, body, COLORS.memory);
|
|
121
|
+
}
|
|
122
|
+
if (this.opts.statusController.isRunning()) {
|
|
123
|
+
this.opts.statusController.setWorkingMessage("working…");
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
renderDelta(block, label, delta, fg, truncate = false) {
|
|
127
|
+
const next = block ??
|
|
128
|
+
{
|
|
129
|
+
line: new TextRenderable(this.opts.renderer, { content: "", fg }),
|
|
130
|
+
label,
|
|
131
|
+
body: "",
|
|
132
|
+
truncate,
|
|
133
|
+
};
|
|
134
|
+
if (!block) {
|
|
135
|
+
this.opts.transcriptWriter.beginBlock();
|
|
136
|
+
this.opts.transcript.add(next.line);
|
|
137
|
+
}
|
|
138
|
+
next.body += delta;
|
|
139
|
+
updateStreamingBlock(next);
|
|
140
|
+
return next;
|
|
141
|
+
}
|
|
142
|
+
// Render a tool call as a single, self-updating block. The first event
|
|
143
|
+
// (`status: "running"`) creates the block with a spinner; the second event
|
|
144
|
+
// (`completed` or `error`) replaces the spinner with ✓/✗ and appends the
|
|
145
|
+
// truncated result inline so the call and its outcome stay visually paired.
|
|
146
|
+
// Per-tool formatters in `tool-formatters.ts` decide the header text and
|
|
147
|
+
// whether the call should appear in the transcript at all (e.g.
|
|
148
|
+
// ask_user_question hides itself live and lets the `ask` terminal event
|
|
149
|
+
// own the question display).
|
|
150
|
+
renderToolCall(step) {
|
|
151
|
+
const existing = this.activeToolBlocks.get(step.toolCallId);
|
|
152
|
+
if (existing) {
|
|
153
|
+
this.finalizeToolCall(step, existing);
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
const isLive = step.status === "running" || step.status === "pending";
|
|
157
|
+
const formatStatus = isLive ? "running" : step.status === "error" ? "error" : "completed";
|
|
158
|
+
const formatted = formatToolBlock({
|
|
159
|
+
toolName: step.toolName,
|
|
160
|
+
status: formatStatus,
|
|
161
|
+
input: step.input,
|
|
162
|
+
output: step.output,
|
|
163
|
+
mode: "live",
|
|
164
|
+
});
|
|
165
|
+
if (formatted.hidden)
|
|
166
|
+
return;
|
|
167
|
+
const startedAt = isLive ? Date.now() : undefined;
|
|
168
|
+
const marker = "⏳";
|
|
169
|
+
const fg = step.status === "error" ? COLORS.error : COLORS.tool;
|
|
170
|
+
const columns = this.toolBlockColumns();
|
|
171
|
+
const line = new TextRenderable(this.opts.renderer, {
|
|
172
|
+
content: assembleToolBlock(formatted, marker, { columns }),
|
|
173
|
+
fg,
|
|
174
|
+
});
|
|
175
|
+
this.opts.transcriptWriter.beginBlock();
|
|
176
|
+
this.opts.transcript.add(line);
|
|
177
|
+
const block = {
|
|
178
|
+
line,
|
|
179
|
+
header: formatted.header,
|
|
180
|
+
body: formatted.body ?? "",
|
|
181
|
+
input: step.input,
|
|
182
|
+
startedAt,
|
|
183
|
+
};
|
|
184
|
+
this.activeToolBlocks.set(step.toolCallId, block);
|
|
185
|
+
// The same event may already carry a terminal status (cached/replayed
|
|
186
|
+
// history). Fall through to finalize against the just-created block.
|
|
187
|
+
if (!isLive) {
|
|
188
|
+
this.finalizeToolCall(step, block);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
finalizeToolCall(step, block) {
|
|
192
|
+
const isError = step.status === "error";
|
|
193
|
+
const glyph = isError ? "✗" : "✓";
|
|
194
|
+
const elapsedMs = block.startedAt === undefined ? 0 : Date.now() - block.startedAt;
|
|
195
|
+
// Sub-second runs drop the elapsed suffix so the transcript does not get
|
|
196
|
+
// littered with "0s" markers from fast tools (read, ls, todo_write, …).
|
|
197
|
+
const durationSuffix = elapsedMs >= 1000 ? ` ${formatElapsed(elapsedMs)}` : "";
|
|
198
|
+
const formatted = formatToolBlock({
|
|
199
|
+
toolName: step.toolName,
|
|
200
|
+
status: isError ? "error" : "completed",
|
|
201
|
+
input: block.input,
|
|
202
|
+
output: step.output,
|
|
203
|
+
mode: "live",
|
|
204
|
+
});
|
|
205
|
+
block.line.content = assembleToolBlock(formatted, `${glyph}${durationSuffix}`, {
|
|
206
|
+
columns: this.toolBlockColumns(),
|
|
207
|
+
});
|
|
208
|
+
block.line.fg = isError ? COLORS.error : COLORS.tool;
|
|
209
|
+
this.activeToolBlocks.delete(step.toolCallId);
|
|
210
|
+
}
|
|
211
|
+
finalizeDelta(block, body) {
|
|
212
|
+
block.body = body;
|
|
213
|
+
updateStreamingBlock(block);
|
|
214
|
+
}
|
|
215
|
+
// Width budget for a tool block: terminal width minus the fixed sidebar
|
|
216
|
+
// column and a small fudge for borders/padding. Recomputed per render so a
|
|
217
|
+
// resize after a tool block lands updates new blocks; existing blocks keep
|
|
218
|
+
// the width they were rendered at, which is acceptable since the renderer
|
|
219
|
+
// would otherwise re-wrap and could exceed the row cap.
|
|
220
|
+
toolBlockColumns() {
|
|
221
|
+
const transcriptColumnPadding = 4;
|
|
222
|
+
return Math.max(20, this.opts.renderer.terminalWidth - SIDEBAR_WIDTH - transcriptColumnPadding);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
function updateStreamingBlock(block) {
|
|
226
|
+
const body = block.truncate ? truncateToolText(block.body) : block.body;
|
|
227
|
+
block.line.content = block.label ? `${block.label}\n${body}` : body;
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Format the body of a memory phase event for display. Returns the empty
|
|
231
|
+
* string when there are no observations or usage bumps to show, so the
|
|
232
|
+
* caller can elide the block entirely.
|
|
233
|
+
*/
|
|
234
|
+
export function formatMemoryEventBody(event) {
|
|
235
|
+
const hasObservations = Boolean(event.observations && event.observations.length > 0);
|
|
236
|
+
const hasBumps = Boolean(event.usageBumpedObservations && event.usageBumpedObservations.length > 0);
|
|
237
|
+
if (!hasObservations && !hasBumps) {
|
|
238
|
+
return "";
|
|
239
|
+
}
|
|
240
|
+
const sections = [event.message];
|
|
241
|
+
if (hasObservations) {
|
|
242
|
+
sections.push(event.observations.map((observation) => observation.content).join("\n\n"));
|
|
243
|
+
}
|
|
244
|
+
return truncateToolText(sections.join("\n"));
|
|
245
|
+
}
|
|
246
|
+
//# sourceMappingURL=step-renderer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"step-renderer.js","sourceRoot":"","sources":["../../../src/tui/step-renderer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { type CliRenderer, type KeyEvent, type ScrollBoxRenderable, TextRenderable } from "@opentui/core";
|
|
2
|
+
import type { TranscriptEntry } from "./transcript-log.js";
|
|
3
|
+
export interface TranscriptWriterOptions {
|
|
4
|
+
/** Reads the last drag-selected text; surfaced in `/diag` key dumps so we
|
|
5
|
+
* can correlate "key fired" with "selection state at that moment". */
|
|
6
|
+
getLastSelectionText: () => string;
|
|
7
|
+
/** Invoked when the underlying TextBuffer is observed to be destroyed
|
|
8
|
+
* mid-mutation (the OpenTUI race the v0.1.68 fix targets). The caller
|
|
9
|
+
* uses this to tear down timers (working ticker) that would otherwise
|
|
10
|
+
* fire again on a dead buffer. */
|
|
11
|
+
onBufferDestroyed?: () => void;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Owns every write to the transcript ScrollBox plus the `/diag` key+selection
|
|
15
|
+
* event log. Centralizing here keeps the post-teardown try/catch that swallows
|
|
16
|
+
* "TextBuffer is destroyed" in exactly one place (v0.1.68 fix), and gives the
|
|
17
|
+
* status/hint controllers a single `isDestroyed()` source of truth.
|
|
18
|
+
*/
|
|
19
|
+
export declare class TranscriptWriter {
|
|
20
|
+
private readonly renderer;
|
|
21
|
+
private readonly transcript;
|
|
22
|
+
private readonly options;
|
|
23
|
+
private destroyed;
|
|
24
|
+
private hasRenderedAnyBlock;
|
|
25
|
+
private keyDiagnostics;
|
|
26
|
+
private readonly log;
|
|
27
|
+
constructor(renderer: CliRenderer, transcript: ScrollBoxRenderable, options: TranscriptWriterOptions);
|
|
28
|
+
/** Append a single line. Empty content is ignored so callers can guard with
|
|
29
|
+
* raw input without producing blank rows; use `addLine` instead when a
|
|
30
|
+
* spacer is wanted and a renderable handle is needed. */
|
|
31
|
+
appendLine(content: string, fg: string): void;
|
|
32
|
+
/** Append a labelled block. `beginBlock()` inserts a blank separator before
|
|
33
|
+
* every block except the first so distinct steps stay visually distinct. */
|
|
34
|
+
appendBlock(label: string | null, body: string, fg: string): void;
|
|
35
|
+
beginBlock(): void;
|
|
36
|
+
/** Append a line and return the renderable handle. Used by the starter
|
|
37
|
+
* block (which destroys its own refs on dismiss) and substitutes a single
|
|
38
|
+
* space for empty content so the renderable still occupies a row. */
|
|
39
|
+
addLine(content: string, fg: string): TextRenderable;
|
|
40
|
+
/** Records a user/agent message body in the parallel log read by `/copy`
|
|
41
|
+
* and the copy keystroke. Trims and drops empty payloads so noisy
|
|
42
|
+
* presentation-only writes (spacers, etc.) do not pollute the log. */
|
|
43
|
+
recordEntry(kind: TranscriptEntry["kind"], text: string): void;
|
|
44
|
+
entries(): readonly TranscriptEntry[];
|
|
45
|
+
/** Flipped from the renderer `destroy` handler. Subsequent transcript
|
|
46
|
+
* writes short-circuit instead of throwing from a destroyed buffer. */
|
|
47
|
+
markDestroyed(): void;
|
|
48
|
+
isDestroyed(): boolean;
|
|
49
|
+
setKeyDiagnosticsEnabled(enabled: boolean): void;
|
|
50
|
+
isKeyDiagnosticsEnabled(): boolean;
|
|
51
|
+
logKey(label: string, key: KeyEvent): void;
|
|
52
|
+
logSelection(text: string): void;
|
|
53
|
+
private handleBufferDestroyed;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* OpenTUI's TextBuffer throws a plain Error with this exact message from its
|
|
57
|
+
* `guard()` method when any setter is touched after destroy. We sniff the
|
|
58
|
+
* message to distinguish post-teardown races (swallow) from real bugs
|
|
59
|
+
* (rethrow). Exported so the status/hint controllers can share the same
|
|
60
|
+
* sniff without re-importing OpenTUI internals.
|
|
61
|
+
*/
|
|
62
|
+
export declare function isTextBufferDestroyedError(error: unknown): boolean;
|
|
63
|
+
//# sourceMappingURL=transcript-writer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transcript-writer.d.ts","sourceRoot":"","sources":["../../../src/tui/transcript-writer.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,QAAQ,EACb,KAAK,mBAAmB,EACxB,cAAc,EACf,MAAM,eAAe,CAAC;AAEvB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3D,MAAM,WAAW,uBAAuB;IACtC;2EACuE;IACvE,oBAAoB,EAAE,MAAM,MAAM,CAAC;IACnC;;;uCAGmC;IACnC,iBAAiB,CAAC,EAAE,MAAM,IAAI,CAAC;CAChC;AAED;;;;;GAKG;AACH,qBAAa,gBAAgB;IAOzB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,OAAO;IAR1B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,mBAAmB,CAAS;IACpC,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAyB;gBAG1B,QAAQ,EAAE,WAAW,EACrB,UAAU,EAAE,mBAAmB,EAC/B,OAAO,EAAE,uBAAuB;IAKnD;;8DAE0D;IAC1D,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI;IAe7C;iFAC6E;IAC7E,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI;IAMjE,UAAU,IAAI,IAAI;IAKlB;;0EAEsE;IACtE,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,cAAc;IAQpD;;2EAEuE;IACvE,WAAW,CAAC,IAAI,EAAE,eAAe,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAM9D,OAAO,IAAI,SAAS,eAAe,EAAE;IAMrC;4EACwE;IACxE,aAAa,IAAI,IAAI;IAIrB,WAAW,IAAI,OAAO;IAMtB,wBAAwB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAIhD,uBAAuB,IAAI,OAAO;IAIlC,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,GAAG,IAAI;IAgB1C,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAShC,OAAO,CAAC,qBAAqB;CAI9B;AAED;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAElE"}
|