@botbotgo/agent-harness 0.0.308 → 0.0.310

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.
Files changed (195) hide show
  1. package/README.md +17 -1
  2. package/README.zh.md +17 -1
  3. package/dist/acp.d.ts +1 -116
  4. package/dist/acp.js +1 -310
  5. package/dist/api.d.ts +4 -2
  6. package/dist/api.js +4 -1
  7. package/dist/cli/chat-interactive.d.ts +24 -0
  8. package/dist/cli/chat-interactive.js +244 -0
  9. package/dist/cli/chat-rendering.d.ts +9 -0
  10. package/dist/cli/chat-rendering.js +102 -0
  11. package/dist/cli/chat-stream.d.ts +23 -0
  12. package/dist/cli/chat-stream.js +330 -0
  13. package/dist/cli/chat-ui.d.ts +20 -0
  14. package/dist/cli/chat-ui.js +198 -0
  15. package/dist/cli/chat-workspace.d.ts +15 -0
  16. package/dist/cli/chat-workspace.js +205 -0
  17. package/dist/cli/main.d.ts +52 -0
  18. package/dist/cli/main.js +323 -0
  19. package/dist/cli/managed-service-commands.d.ts +23 -0
  20. package/dist/cli/managed-service-commands.js +63 -0
  21. package/dist/cli/managed-service.d.ts +27 -0
  22. package/dist/cli/managed-service.js +61 -0
  23. package/dist/cli/options-init-chat.d.ts +16 -0
  24. package/dist/cli/options-init-chat.js +108 -0
  25. package/dist/cli/options-runtime.d.ts +27 -0
  26. package/dist/cli/options-runtime.js +158 -0
  27. package/dist/cli/options-serve.d.ts +24 -0
  28. package/dist/cli/options-serve.js +166 -0
  29. package/dist/cli/options.d.ts +5 -0
  30. package/dist/cli/options.js +47 -0
  31. package/dist/cli/process-guards.d.ts +14 -0
  32. package/dist/cli/process-guards.js +139 -0
  33. package/dist/cli/request-tree.d.ts +12 -0
  34. package/dist/cli/request-tree.js +296 -0
  35. package/dist/cli/runtime-commands.d.ts +15 -0
  36. package/dist/cli/runtime-commands.js +247 -0
  37. package/dist/cli/runtime-output.d.ts +5 -0
  38. package/dist/cli/runtime-output.js +124 -0
  39. package/dist/cli/server-commands.d.ts +36 -0
  40. package/dist/cli/server-commands.js +250 -0
  41. package/dist/cli/workspace.d.ts +6 -0
  42. package/dist/cli/workspace.js +71 -0
  43. package/dist/cli.d.ts +1 -67
  44. package/dist/cli.js +2 -2734
  45. package/dist/client/acp.d.ts +1 -50
  46. package/dist/client/acp.js +1 -219
  47. package/dist/client/in-process.d.ts +5 -5
  48. package/dist/client/index.d.ts +2 -2
  49. package/dist/client/index.js +1 -1
  50. package/dist/contracts/runtime-evaluation.d.ts +103 -0
  51. package/dist/contracts/runtime-evaluation.js +1 -0
  52. package/dist/contracts/runtime-memory.d.ts +162 -0
  53. package/dist/contracts/runtime-memory.js +1 -0
  54. package/dist/contracts/runtime-observability.d.ts +248 -0
  55. package/dist/contracts/runtime-observability.js +1 -0
  56. package/dist/contracts/runtime-requests.d.ts +342 -0
  57. package/dist/contracts/runtime-requests.js +1 -0
  58. package/dist/contracts/runtime-scheduling.d.ts +146 -0
  59. package/dist/contracts/runtime-scheduling.js +1 -0
  60. package/dist/contracts/runtime.d.ts +5 -1042
  61. package/dist/contracts/runtime.js +27 -1
  62. package/dist/flow/build-flow-graph.js +4 -875
  63. package/dist/flow/flow-graph-normalization.d.ts +56 -0
  64. package/dist/flow/flow-graph-normalization.js +214 -0
  65. package/dist/flow/flow-graph-runtime.d.ts +8 -0
  66. package/dist/flow/flow-graph-runtime.js +107 -0
  67. package/dist/flow/flow-graph-upstream.d.ts +18 -0
  68. package/dist/flow/flow-graph-upstream.js +498 -0
  69. package/dist/flow/types.d.ts +1 -1
  70. package/dist/index.d.ts +4 -4
  71. package/dist/index.js +2 -2
  72. package/dist/init-project.d.ts +1 -12
  73. package/dist/init-project.js +1 -651
  74. package/dist/{procedural → knowledge/procedural}/manager.d.ts +3 -3
  75. package/dist/{procedural → knowledge/procedural}/manager.js +6 -6
  76. package/dist/mcp.d.ts +2 -62
  77. package/dist/mcp.js +2 -253
  78. package/dist/package-version.d.ts +1 -1
  79. package/dist/package-version.js +1 -1
  80. package/dist/persistence/file-store.js +1 -1
  81. package/dist/persistence/sqlite-runtime.d.ts +19 -0
  82. package/dist/persistence/sqlite-runtime.js +86 -0
  83. package/dist/persistence/sqlite-store.js +11 -99
  84. package/dist/{request-events.d.ts → projections/request-events.d.ts} +1 -1
  85. package/dist/{upstream-events.js → projections/upstream-events.js} +1 -1
  86. package/dist/protocol/a2a/http-discovery.d.ts +39 -0
  87. package/dist/protocol/a2a/http-discovery.js +178 -0
  88. package/dist/protocol/a2a/http-rpc.d.ts +28 -0
  89. package/dist/protocol/a2a/http-rpc.js +623 -0
  90. package/dist/protocol/a2a/http.d.ts +72 -1
  91. package/dist/protocol/a2a/http.js +14 -1124
  92. package/dist/protocol/a2a/task-state.d.ts +29 -0
  93. package/dist/protocol/a2a/task-state.js +317 -0
  94. package/dist/protocol/acp/client.js +1 -1
  95. package/dist/protocol/acp/harness-client.d.ts +50 -0
  96. package/dist/protocol/acp/harness-client.js +219 -0
  97. package/dist/protocol/acp/server.d.ts +116 -0
  98. package/dist/protocol/acp/server.js +310 -0
  99. package/dist/protocol/ag-ui/http.js +1 -1
  100. package/dist/protocol/mcp/server.d.ts +76 -0
  101. package/dist/protocol/mcp/server.js +428 -0
  102. package/dist/resource/backend/workspace-scoped-backend.d.ts +40 -0
  103. package/dist/resource/backend/workspace-scoped-backend.js +296 -0
  104. package/dist/resource/mcp/tool-support.d.ts +35 -0
  105. package/dist/resource/mcp/tool-support.js +296 -0
  106. package/dist/resource/mcp-tool-support.d.ts +2 -35
  107. package/dist/resource/mcp-tool-support.js +2 -296
  108. package/dist/resource/providers/resource-provider.d.ts +22 -0
  109. package/dist/resource/providers/resource-provider.js +215 -0
  110. package/dist/resource/resource-impl.d.ts +3 -33
  111. package/dist/resource/resource-impl.js +2 -808
  112. package/dist/resource/resource-types.d.ts +33 -0
  113. package/dist/resource/resource-types.js +1 -0
  114. package/dist/resource/tools/function-tool-resolver.d.ts +2 -0
  115. package/dist/resource/tools/function-tool-resolver.js +306 -0
  116. package/dist/runtime/adapter/middleware-assembly.js +1 -1
  117. package/dist/runtime/adapter/model/invocation-request.js +2 -2
  118. package/dist/runtime/adapter/model/message-assembly.js +1 -1
  119. package/dist/runtime/agent-runtime-adapter.d.ts +3 -63
  120. package/dist/runtime/agent-runtime-adapter.js +5 -233
  121. package/dist/runtime/agent-runtime-assembly.d.ts +67 -0
  122. package/dist/runtime/agent-runtime-assembly.js +211 -0
  123. package/dist/runtime/harness/background-runtime.d.ts +1 -1
  124. package/dist/runtime/harness/events/event-sink.js +1 -1
  125. package/dist/runtime/harness/events/runtime-event-operations.d.ts +1 -1
  126. package/dist/runtime/harness/events/streaming.js +1 -1
  127. package/dist/runtime/harness/public-shapes.d.ts +43 -0
  128. package/dist/runtime/harness/public-shapes.js +186 -0
  129. package/dist/runtime/harness/run/inspection.js +2 -2
  130. package/dist/runtime/harness/run/resources.js +1 -1
  131. package/dist/runtime/harness/run/surface-semantics.js +1 -1
  132. package/dist/runtime/harness/system/inventory.d.ts +1 -1
  133. package/dist/runtime/harness/system/inventory.js +2 -2
  134. package/dist/runtime/harness/system/policy-engine.js +1 -1
  135. package/dist/runtime/harness/system/runtime-memory-manager.js +1 -1
  136. package/dist/runtime/harness/system/skill-requirements.d.ts +1 -1
  137. package/dist/runtime/harness/system/skill-requirements.js +1 -1
  138. package/dist/runtime/harness.d.ts +3 -2
  139. package/dist/runtime/harness.js +11 -191
  140. package/dist/runtime/maintenance/checkpoint-maintenance.js +1 -1
  141. package/dist/runtime/maintenance/runtime-record-maintenance.js +1 -1
  142. package/dist/runtime/parsing/output-content.d.ts +11 -0
  143. package/dist/runtime/parsing/output-content.js +442 -0
  144. package/dist/runtime/parsing/output-parsing.d.ts +3 -29
  145. package/dist/runtime/parsing/output-parsing.js +3 -806
  146. package/dist/runtime/parsing/output-recovery.d.ts +14 -0
  147. package/dist/runtime/parsing/output-recovery.js +288 -0
  148. package/dist/runtime/parsing/output-tool-args.d.ts +4 -0
  149. package/dist/runtime/parsing/output-tool-args.js +120 -0
  150. package/dist/runtime/support/runtime-factories.js +1 -1
  151. package/dist/scaffold/init-project.d.ts +12 -0
  152. package/dist/scaffold/init-project.js +651 -0
  153. package/dist/{extensions.d.ts → tooling/extensions.d.ts} +1 -1
  154. package/dist/{extensions.js → tooling/extensions.js} +3 -3
  155. package/dist/{tool-modules.d.ts → tooling/module-loader.d.ts} +1 -1
  156. package/dist/{tool-modules.js → tooling/module-loader.js} +2 -2
  157. package/dist/workspace/agent-binding-compiler.js +2 -2
  158. package/dist/workspace/compile.js +2 -2
  159. package/dist/workspace/object-loader-paths.d.ts +11 -0
  160. package/dist/workspace/object-loader-paths.js +75 -0
  161. package/dist/workspace/object-loader-readers.d.ts +21 -0
  162. package/dist/workspace/object-loader-readers.js +187 -0
  163. package/dist/workspace/object-loader.d.ts +0 -1
  164. package/dist/workspace/object-loader.js +6 -260
  165. package/dist/workspace/resource-compilers.js +1 -1
  166. package/dist/workspace/support/discovery.js +1 -1
  167. package/package.json +1 -1
  168. package/dist/runtime/adapter/index.d.ts +0 -13
  169. package/dist/runtime/adapter/index.js +0 -13
  170. package/dist/runtime/harness/index.d.ts +0 -19
  171. package/dist/runtime/harness/index.js +0 -19
  172. package/dist/runtime/maintenance/index.d.ts +0 -4
  173. package/dist/runtime/maintenance/index.js +0 -4
  174. package/dist/runtime/parsing/index.d.ts +0 -2
  175. package/dist/runtime/parsing/index.js +0 -2
  176. package/dist/runtime/support/index.d.ts +0 -4
  177. package/dist/runtime/support/index.js +0 -4
  178. package/dist/workspace/support/index.d.ts +0 -2
  179. package/dist/workspace/support/index.js +0 -2
  180. /package/dist/{procedural → knowledge/procedural}/config.d.ts +0 -0
  181. /package/dist/{procedural → knowledge/procedural}/config.js +0 -0
  182. /package/dist/{procedural → knowledge/procedural}/index.d.ts +0 -0
  183. /package/dist/{procedural → knowledge/procedural}/index.js +0 -0
  184. /package/dist/{presentation.d.ts → projections/presentation.d.ts} +0 -0
  185. /package/dist/{presentation.js → projections/presentation.js} +0 -0
  186. /package/dist/{request-events.js → projections/request-events.js} +0 -0
  187. /package/dist/{upstream-events.d.ts → projections/upstream-events.d.ts} +0 -0
  188. /package/dist/runtime/{support → env}/runtime-env.d.ts +0 -0
  189. /package/dist/runtime/{support → env}/runtime-env.js +0 -0
  190. /package/dist/runtime/{support → layout}/runtime-layout.d.ts +0 -0
  191. /package/dist/runtime/{support → layout}/runtime-layout.js +0 -0
  192. /package/dist/runtime/{support → prompts}/runtime-prompts.d.ts +0 -0
  193. /package/dist/runtime/{support → prompts}/runtime-prompts.js +0 -0
  194. /package/dist/runtime/{support → skills}/skill-metadata.d.ts +0 -0
  195. /package/dist/runtime/{support → skills}/skill-metadata.js +0 -0
@@ -0,0 +1,330 @@
1
+ import { countRenderedLines, renderChatRequestRunning, renderChatTextChunk, summarizeChatToolResult } from "./chat-rendering.js";
2
+ import { buildTerminalRequestSnapshot, buildTodoContinuationSignature, flattenRequestExecutionSteps, renderRequestEventContinuation, renderRequestSnapshotTree, renderRequestTodoContinuation, } from "./request-tree.js";
3
+ export async function streamChatMessage(input) {
4
+ const requestStartedAt = Date.now();
5
+ let firstSnapshotAt;
6
+ let firstDataAt;
7
+ let latestSnapshot;
8
+ let latestSessionId = input.sessionId;
9
+ let latestRequestId;
10
+ let latestAgentId = input.agentId;
11
+ let wroteContent = false;
12
+ let wroteRenderableBlocks = false;
13
+ let lastRenderedRequestTreeKey;
14
+ let lastRenderedRequestTree = "";
15
+ let lastRenderedRequestTreeLineCount = 0;
16
+ let lastRenderedRequestTreeAt = 0;
17
+ let announcedRunningState = false;
18
+ let requestTreeVisible = false;
19
+ let requestTreePersisted = false;
20
+ let liveRequestAnnotations = [];
21
+ let persistedRequestTreeEventCount = 0;
22
+ let persistedRequestTreeTodoSignature = "";
23
+ const requestTreeRenderThrottleMs = 75;
24
+ let suppressRequestTreeRendering = false;
25
+ let lastStableRequestTreeKey;
26
+ let stdoutWriteChain = Promise.resolve();
27
+ let stderrWriteChain = Promise.resolve();
28
+ const enqueueChatWrite = (sink, _stream, chain, message) => chain.then(async () => {
29
+ sink(message);
30
+ });
31
+ const summarizeRequestTreeSteps = (steps) => steps
32
+ .map((step) => [
33
+ step.id ?? "",
34
+ step.kind,
35
+ step.name,
36
+ step.status,
37
+ step.startedAt ?? "",
38
+ step.endedAt ?? "",
39
+ ].join("|"))
40
+ .join(";");
41
+ const buildRequestSnapshotRenderKey = (snapshot) => {
42
+ const todoSignatures = snapshot.plan.items
43
+ .map((item) => [
44
+ item.id ?? "",
45
+ item.content,
46
+ item.status,
47
+ item.ownerAgentId ?? "",
48
+ item.startedAt ?? "",
49
+ item.endedAt ?? "",
50
+ item.result === undefined ? "" : String(item.result),
51
+ summarizeRequestTreeSteps(item.events),
52
+ ].join("|"))
53
+ .join(";");
54
+ const approvalSignature = snapshot.approval
55
+ ? [
56
+ snapshot.approval.approvalId,
57
+ snapshot.approval.status,
58
+ snapshot.approval.toolName ?? "",
59
+ ].join("|")
60
+ : "";
61
+ return [
62
+ snapshot.sessionId,
63
+ snapshot.requestId,
64
+ snapshot.state,
65
+ snapshot.agentId ?? "",
66
+ snapshot.plan.version,
67
+ snapshot.plan.updatedAt,
68
+ snapshot.plan.summary.total,
69
+ snapshot.plan.summary.inProgress,
70
+ snapshot.plan.summary.completed,
71
+ snapshot.plan.summary.failed,
72
+ approvalSignature,
73
+ summarizeRequestTreeSteps(snapshot.events),
74
+ todoSignatures,
75
+ ].join("||");
76
+ };
77
+ const formatPerfClock = (timestamp) => {
78
+ const value = new Date(timestamp);
79
+ return value.toLocaleTimeString("en-US", {
80
+ hour12: false,
81
+ hour: "2-digit",
82
+ minute: "2-digit",
83
+ second: "2-digit",
84
+ fractionalSecondDigits: 3,
85
+ });
86
+ };
87
+ const formatElapsed = (timestamp) => `${((timestamp - requestStartedAt) / 1000).toFixed(3)}s`;
88
+ const buildTimingSummary = (completedAt) => {
89
+ const parts = [`start ${formatPerfClock(requestStartedAt)}`];
90
+ if (firstSnapshotAt) {
91
+ parts.push(`first event +${formatElapsed(firstSnapshotAt)}`);
92
+ }
93
+ if (firstDataAt) {
94
+ parts.push(`first data +${formatElapsed(firstDataAt)}`);
95
+ }
96
+ if (completedAt) {
97
+ parts.push(`done +${formatElapsed(completedAt)}`);
98
+ }
99
+ else {
100
+ parts.push(`live +${formatElapsed(Date.now())}`);
101
+ }
102
+ return parts.join(" · ");
103
+ };
104
+ const buildLiveRequestTreeBlock = () => {
105
+ if (!lastRenderedRequestTree) {
106
+ return "";
107
+ }
108
+ const annotationBlock = liveRequestAnnotations.length > 0
109
+ ? `\n${liveRequestAnnotations.join("")}`
110
+ : "";
111
+ return `${lastRenderedRequestTree}${annotationBlock}`;
112
+ };
113
+ const clearLiveRequestTree = () => {
114
+ if (!input.requestEvents || !input.liveRequestTree || !requestTreeVisible || lastRenderedRequestTreeLineCount <= 0) {
115
+ return;
116
+ }
117
+ stderrWriteChain = enqueueChatWrite(input.stderr, input.stderrStream, stderrWriteChain, `\x1b[${lastRenderedRequestTreeLineCount}F\x1b[0J`);
118
+ requestTreeVisible = false;
119
+ };
120
+ const drawLiveRequestTree = () => {
121
+ if (!input.requestEvents || !input.liveRequestTree || !lastRenderedRequestTree) {
122
+ return;
123
+ }
124
+ const block = buildLiveRequestTreeBlock();
125
+ stderrWriteChain = enqueueChatWrite(input.stderr, input.stderrStream, stderrWriteChain, block);
126
+ lastRenderedRequestTreeLineCount = countRenderedLines(block);
127
+ requestTreeVisible = true;
128
+ };
129
+ const persistLiveRequestTree = () => {
130
+ if (!input.requestEvents || !input.liveRequestTree || requestTreePersisted || !lastRenderedRequestTree) {
131
+ return;
132
+ }
133
+ if (requestTreeVisible && lastRenderedRequestTreeLineCount > 0) {
134
+ stderrWriteChain = enqueueChatWrite(input.stderr, input.stderrStream, stderrWriteChain, `\x1b[${lastRenderedRequestTreeLineCount}F\x1b[0J`);
135
+ requestTreeVisible = false;
136
+ }
137
+ const combinedBlock = buildLiveRequestTreeBlock();
138
+ const treeBlock = combinedBlock.endsWith("\n")
139
+ ? combinedBlock
140
+ : `${combinedBlock}\n`;
141
+ stderrWriteChain = enqueueChatWrite(input.stderr, input.stderrStream, stderrWriteChain, treeBlock);
142
+ persistedRequestTreeEventCount = latestSnapshot ? flattenRequestExecutionSteps(latestSnapshot).length : 0;
143
+ persistedRequestTreeTodoSignature = latestSnapshot ? buildTodoContinuationSignature(latestSnapshot) : "";
144
+ requestTreePersisted = true;
145
+ };
146
+ const enqueueOrderedStdout = (message) => {
147
+ const barrier = Promise.allSettled([stdoutWriteChain, stderrWriteChain]).then(() => undefined);
148
+ stdoutWriteChain = enqueueChatWrite(input.stdout, input.stdoutStream, barrier, message);
149
+ };
150
+ const writeChatStdout = (message) => {
151
+ if (input.requestEvents && input.liveRequestTree && !suppressRequestTreeRendering) {
152
+ clearLiveRequestTree();
153
+ enqueueOrderedStdout(message);
154
+ drawLiveRequestTree();
155
+ return;
156
+ }
157
+ if (input.requestEvents && input.liveRequestTree) {
158
+ enqueueOrderedStdout(message);
159
+ return;
160
+ }
161
+ stdoutWriteChain = enqueueChatWrite(input.stdout, input.stdoutStream, stdoutWriteChain, message);
162
+ };
163
+ const writeChatStderr = (message) => {
164
+ if (input.requestEvents && input.liveRequestTree && !suppressRequestTreeRendering) {
165
+ clearLiveRequestTree();
166
+ stderrWriteChain = enqueueChatWrite(input.stderr, input.stderrStream, stderrWriteChain, message);
167
+ drawLiveRequestTree();
168
+ return;
169
+ }
170
+ stderrWriteChain = enqueueChatWrite(input.stderr, input.stderrStream, stderrWriteChain, message);
171
+ };
172
+ const suspendRequestTreeRendering = () => {
173
+ if (!input.requestEvents || !input.liveRequestTree) {
174
+ return;
175
+ }
176
+ persistLiveRequestTree();
177
+ suppressRequestTreeRendering = true;
178
+ clearLiveRequestTree();
179
+ };
180
+ const renderContentBlocks = (contentBlocks, agentId) => {
181
+ latestAgentId = agentId || latestAgentId;
182
+ if (!wroteContent) {
183
+ const rendered = contentBlocks
184
+ .map((block) => {
185
+ if (typeof block === "string") {
186
+ return block;
187
+ }
188
+ if (block && typeof block === "object" && "text" in block && typeof block.text === "string") {
189
+ return block.text;
190
+ }
191
+ return "";
192
+ })
193
+ .filter((block) => block.trim().length > 0)
194
+ .join("");
195
+ if (rendered) {
196
+ if (input.requestEvents) {
197
+ suspendRequestTreeRendering();
198
+ }
199
+ writeChatStdout(renderChatTextChunk(rendered, input.modelInfo));
200
+ wroteRenderableBlocks = true;
201
+ }
202
+ }
203
+ };
204
+ const result = await input.client.request({
205
+ ...(input.agentId ? { agentId: input.agentId } : {}),
206
+ ...(input.sessionId ? { sessionId: input.sessionId } : {}),
207
+ input: input.message,
208
+ eventListener(snapshot) {
209
+ latestSessionId = snapshot.sessionId || latestSessionId;
210
+ latestRequestId = snapshot.requestId || latestRequestId;
211
+ latestAgentId = snapshot.agentId || latestAgentId;
212
+ latestSnapshot = snapshot;
213
+ firstSnapshotAt ??= Date.now();
214
+ if (input.requestEvents && !suppressRequestTreeRendering) {
215
+ const now = Date.now();
216
+ const nextTreeKey = buildRequestSnapshotRenderKey(snapshot);
217
+ const terminalSnapshot = snapshot.state !== "queued" && snapshot.state !== "claimed" && snapshot.state !== "running";
218
+ const snapshotCarriesRenderableOutput = snapshot.output.trim().length > 0;
219
+ const shouldRenderSnapshot = !snapshotCarriesRenderableOutput
220
+ && nextTreeKey !== lastRenderedRequestTreeKey
221
+ && nextTreeKey !== lastStableRequestTreeKey
222
+ && ((terminalSnapshot && !input.liveRequestTree)
223
+ || !input.liveRequestTree
224
+ || now - lastRenderedRequestTreeAt >= requestTreeRenderThrottleMs);
225
+ if (shouldRenderSnapshot) {
226
+ lastRenderedRequestTree = renderRequestSnapshotTree(snapshot, input.colorRequestTree === true, buildTimingSummary());
227
+ if (input.liveRequestTree) {
228
+ clearLiveRequestTree();
229
+ drawLiveRequestTree();
230
+ }
231
+ else {
232
+ input.stderr(`\n${lastRenderedRequestTree}`);
233
+ }
234
+ lastRenderedRequestTreeKey = nextTreeKey;
235
+ if (!snapshot.activeEventId && snapshot.state !== "running") {
236
+ lastStableRequestTreeKey = nextTreeKey;
237
+ }
238
+ lastRenderedRequestTreeAt = now;
239
+ }
240
+ }
241
+ if ((input.showRunningState ?? true) && !input.requestEvents && !announcedRunningState && !wroteContent && !wroteRenderableBlocks) {
242
+ input.stderr(renderChatRequestRunning({
243
+ sessionId: snapshot.sessionId,
244
+ requestId: snapshot.requestId,
245
+ agentId: snapshot.agentId,
246
+ }));
247
+ announcedRunningState = true;
248
+ }
249
+ },
250
+ dataListener(delta) {
251
+ latestSessionId = delta.sessionId || latestSessionId;
252
+ latestRequestId = delta.requestId || latestRequestId;
253
+ firstDataAt ??= Date.now();
254
+ if (delta.type === "output.text.delta") {
255
+ latestAgentId = delta.agentId || latestAgentId;
256
+ if (input.requestEvents) {
257
+ suspendRequestTreeRendering();
258
+ }
259
+ writeChatStdout(renderChatTextChunk(delta.text, input.modelInfo));
260
+ wroteContent = true;
261
+ return;
262
+ }
263
+ if (delta.type === "output.content-blocks") {
264
+ suspendRequestTreeRendering();
265
+ renderContentBlocks(delta.contentBlocks, delta.agentId);
266
+ return;
267
+ }
268
+ if (delta.type === "tool.result") {
269
+ latestAgentId = delta.agentId || latestAgentId;
270
+ if ((input.showToolResults ?? true) && !input.requestEvents) {
271
+ writeChatStderr(`\n[${formatPerfClock(Date.now())} +${formatElapsed(Date.now())}] [tool:${delta.toolName}] ${summarizeChatToolResult(delta.output, delta.isError === true)}${delta.isError ? " (error)" : ""}\n`);
272
+ }
273
+ return;
274
+ }
275
+ if (delta.type === "progress.commentary") {
276
+ latestAgentId = delta.agentId || latestAgentId;
277
+ if (wroteContent || wroteRenderableBlocks) {
278
+ return;
279
+ }
280
+ const progressLine = `[${formatPerfClock(Date.now())} +${formatElapsed(Date.now())}] ${delta.text}\n`;
281
+ if (input.requestEvents && input.liveRequestTree && !suppressRequestTreeRendering && lastRenderedRequestTree) {
282
+ liveRequestAnnotations.push(progressLine);
283
+ clearLiveRequestTree();
284
+ drawLiveRequestTree();
285
+ return;
286
+ }
287
+ writeChatStderr(progressLine);
288
+ }
289
+ },
290
+ });
291
+ if (!result) {
292
+ throw new Error("chat request completed without a terminal result");
293
+ }
294
+ latestSessionId = result.sessionId;
295
+ latestRequestId = result.requestId;
296
+ latestAgentId = result.agentId ?? latestAgentId;
297
+ const completedAt = Date.now();
298
+ if (input.requestEvents && latestSnapshot) {
299
+ const terminalSnapshot = buildTerminalRequestSnapshot(latestSnapshot, { state: result.state, output: result.output });
300
+ lastRenderedRequestTree = renderRequestSnapshotTree(terminalSnapshot, input.colorRequestTree === true, buildTimingSummary(completedAt));
301
+ if (input.liveRequestTree && !requestTreePersisted) {
302
+ clearLiveRequestTree();
303
+ drawLiveRequestTree();
304
+ }
305
+ else if (input.liveRequestTree && requestTreePersisted) {
306
+ const todoContinuation = renderRequestTodoContinuation(terminalSnapshot, persistedRequestTreeTodoSignature, input.colorRequestTree === true);
307
+ const continuation = renderRequestEventContinuation(terminalSnapshot, persistedRequestTreeEventCount, input.colorRequestTree === true);
308
+ if (todoContinuation) {
309
+ stderrWriteChain = enqueueChatWrite(input.stderr, input.stderrStream, stderrWriteChain, `\n${todoContinuation}`);
310
+ }
311
+ if (continuation) {
312
+ stderrWriteChain = enqueueChatWrite(input.stderr, input.stderrStream, stderrWriteChain, `\n${continuation}`);
313
+ }
314
+ }
315
+ else if (!input.liveRequestTree) {
316
+ input.stderr(`\n${lastRenderedRequestTree}`);
317
+ }
318
+ }
319
+ if (!wroteContent && !wroteRenderableBlocks && result.output.trim().length > 0) {
320
+ writeChatStdout(renderChatTextChunk(result.output, input.modelInfo));
321
+ }
322
+ if (result.state === "waiting_for_approval") {
323
+ writeChatStderr(`\nRequest is waiting for approval${result.approvalId ? ` (${result.approvalId})` : ""}.\n`);
324
+ }
325
+ else if (wroteContent || wroteRenderableBlocks || result.output.trim().length > 0) {
326
+ writeChatStdout("\n");
327
+ }
328
+ await Promise.allSettled([stdoutWriteChain, stderrWriteChain]);
329
+ return { sessionId: latestSessionId, requestId: latestRequestId, agentId: latestAgentId };
330
+ }
@@ -0,0 +1,20 @@
1
+ export declare function renderChatPromptLine(input: {
2
+ agentId?: string;
3
+ sessionId?: string;
4
+ requestId?: string;
5
+ color: boolean;
6
+ }): string;
7
+ export declare function renderChatBanner(input: {
8
+ workspacePath: string;
9
+ transport: "stdio" | "http";
10
+ agentId?: string;
11
+ sessionId?: string;
12
+ color: boolean;
13
+ }): string;
14
+ export declare function renderRequestEvents(events: Array<Record<string, unknown>>): string;
15
+ export declare function renderChatContext(input: {
16
+ agentId?: string;
17
+ sessionId?: string;
18
+ requestId?: string;
19
+ }): string;
20
+ export declare function renderChatHelp(): string;
@@ -0,0 +1,198 @@
1
+ function formatTimestamp(value) {
2
+ return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
3
+ }
4
+ function trimAsciiBlock(block) {
5
+ return block
6
+ .split("\n")
7
+ .map((line) => line.replace(/\s+$/u, ""))
8
+ .join("\n");
9
+ }
10
+ const CHAT_ASCII_BOTBOTGO = trimAsciiBlock(" ____ ___ _____ ____ ___ _____ ____ ___ \n" +
11
+ " | __ ) / _ \\_ _| __ ) / _ \\_ _/ ___|/ _ \\ \n" +
12
+ " | _ \\| | | || | | _ \\| | | || || | _| | | |\n" +
13
+ " | |_) | |_| || | | |_) | |_| || || |_| | |_| |\n" +
14
+ " |____/ \\___/ |_| |____/ \\___/ |_| \\____|\\___/");
15
+ const CHAT_ASCII_AGENT_HARNESS = trimAsciiBlock(" _ ____ _____ _ _ _____ _ _ _ ____ _ _ _____ ____ ____ \n" +
16
+ " / \\ / ___| ____| \\ | |_ _| | | | | / \\ | _ \\| \\ | | ____/ ___/ ___| \n" +
17
+ " / _ \\| | _| _| | \\| | | | | |_| | / _ \\ | |_) | \\| | _| \\___ \\___ \\ \n" +
18
+ " / ___ \\ |_| | |___| |\\ | | | | _ |/ ___ \\| _ <| |\\ | |___ ___) |__) |\n" +
19
+ " /_/ \\_\\____|_____|_| \\_| |_| |_| |_/_/ \\_\\_| \\_\\_| \\_|_____|____/____/");
20
+ const CHAT_LOGO_BRAND_LINE_COLORS = [25, 238, 160, 238, 160];
21
+ const CHAT_LOGO_PRODUCT_LINE_COLORS = [136, 136, 160, 160, 160];
22
+ function colorizeSolidAsciiBlock(block, lineColors, enabled) {
23
+ const trimmed = trimAsciiBlock(block);
24
+ const lines = trimmed.split("\n");
25
+ if (!enabled) {
26
+ return trimmed;
27
+ }
28
+ return lines
29
+ .map((line, i) => {
30
+ const code = lineColors[Math.min(i, lineColors.length - 1)] ?? lineColors[lineColors.length - 1];
31
+ return `\x1b[38;5;${code}m${line}\x1b[0m`;
32
+ })
33
+ .join("\n");
34
+ }
35
+ function ellipsizeChatId(value, maxChars) {
36
+ if (value.length <= maxChars) {
37
+ return value;
38
+ }
39
+ if (maxChars <= 1) {
40
+ return "…";
41
+ }
42
+ return `${value.slice(0, maxChars - 1)}…`;
43
+ }
44
+ export function renderChatPromptLine(input) {
45
+ const agent = input.agentId ?? "—";
46
+ const sessionShort = input.sessionId ? ellipsizeChatId(input.sessionId, 8) : null;
47
+ if (!input.color) {
48
+ return `❯ agent:${agent}${sessionShort ? ` [${sessionShort}]` : ""} › `;
49
+ }
50
+ const labelColor = "\x1b[1;37m";
51
+ const valueColor = "\x1b[38;5;252m";
52
+ const mutedColor = "\x1b[38;5;242m";
53
+ const sigilColor = "\x1b[38;5;246m";
54
+ const reset = "\x1b[0m";
55
+ return `${sigilColor}❯${reset} ${labelColor}agent${reset}:${valueColor}${agent}${reset}${sessionShort ? ` ${mutedColor}[${sessionShort}]${reset}` : ""} ${sigilColor}›${reset} `;
56
+ }
57
+ export function renderChatBanner(input) {
58
+ const { color } = input;
59
+ const brandArt = colorizeSolidAsciiBlock(CHAT_ASCII_BOTBOTGO, CHAT_LOGO_BRAND_LINE_COLORS, color);
60
+ const productArt = colorizeSolidAsciiBlock(CHAT_ASCII_AGENT_HARNESS, CHAT_LOGO_PRODUCT_LINE_COLORS, color);
61
+ const logoWidth = Math.max(...CHAT_ASCII_BOTBOTGO.split("\n").map((l) => l.length), ...CHAT_ASCII_AGENT_HARNESS.split("\n").map((l) => l.length));
62
+ const ruleLen = Math.min(logoWidth + 4, 96);
63
+ const dimRule = (ch, len) => color ? `\x1b[38;5;237m${ch.repeat(len)}\x1b[0m` : ch.repeat(len);
64
+ const labelColor = color ? "\x1b[38;5;242m" : "";
65
+ const valueColor = color ? "\x1b[38;5;252m" : "";
66
+ const accentColor = color ? "\x1b[38;5;33m" : "";
67
+ const resetColor = color ? "\x1b[0m" : "";
68
+ const mutedColor = color ? "\x1b[38;5;238m" : "";
69
+ const borderColor = color ? "\x1b[38;5;237m" : "";
70
+ const kvRow = (label, value, labelW, accent = false) => {
71
+ const lPad = label.padEnd(labelW);
72
+ const lFormatted = `${labelColor}${lPad}${resetColor}`;
73
+ const vFormatted = accent
74
+ ? `${accentColor}${value}${resetColor}`
75
+ : `${valueColor}${value}${resetColor}`;
76
+ return ` ${borderColor}│${resetColor} ${lFormatted} ${mutedColor}·${resetColor} ${vFormatted}`;
77
+ };
78
+ const rows = [
79
+ ["workspace", input.workspacePath, false],
80
+ ["transport", input.transport, false],
81
+ ];
82
+ if (input.agentId)
83
+ rows.push(["agent", input.agentId, true]);
84
+ if (input.sessionId)
85
+ rows.push(["session", input.sessionId, false]);
86
+ const labelW = Math.max(...rows.map(([l]) => l.length));
87
+ const panelInner = Math.max(...rows.map(([, v]) => labelW + 4 + v.length), 44);
88
+ const hLine = (l, m, r) => color
89
+ ? ` ${borderColor}${l}${resetColor}${borderColor}${m.repeat(panelInner + 2)}${r}${resetColor}`
90
+ : ` ${l}${m.repeat(panelInner + 2)}${r}`;
91
+ const versionTagText = "agent-harness";
92
+ const versionTag = color ? `${mutedColor}agent-harness${resetColor}` : versionTagText;
93
+ const versionDividerSpan = Math.max(36, ruleLen);
94
+ const versionGap = 2;
95
+ const versionRuleBudget = Math.max(24, versionDividerSpan - versionTagText.length - versionGap * 2);
96
+ const versionRuleLeftLen = Math.floor(versionRuleBudget / 2);
97
+ const versionRuleRightLen = versionRuleBudget - versionRuleLeftLen;
98
+ const hint = color
99
+ ? ` ${mutedColor}Type \x1b[38;5;246m/help\x1b[0m${mutedColor} for commands · \x1b[38;5;246m/exit\x1b[0m${mutedColor} to quit${resetColor}`
100
+ : ` Type /help for commands · /exit to quit`;
101
+ return [
102
+ "",
103
+ brandArt,
104
+ "",
105
+ ` ${dimRule("─", Math.max(36, ruleLen - 4))}`,
106
+ "",
107
+ productArt,
108
+ "",
109
+ ` ${dimRule("─", versionRuleLeftLen)}${" ".repeat(versionGap)}${versionTag}${" ".repeat(versionGap)}${dimRule("─", versionRuleRightLen)}`,
110
+ "",
111
+ hLine("╭", "─", "╮"),
112
+ ...rows.map(([l, v, accent]) => kvRow(l, v, labelW, accent)),
113
+ hLine("╰", "─", "╯"),
114
+ "",
115
+ hint,
116
+ "",
117
+ ].join("\n");
118
+ }
119
+ export function renderRequestEvents(events) {
120
+ if (events.length === 0) {
121
+ return "No events recorded.\n";
122
+ }
123
+ return events.map((event) => {
124
+ const timestamp = formatTimestamp(event.timestamp) ?? "unknown-time";
125
+ const eventType = typeof event.eventType === "string" ? event.eventType : "unknown-event";
126
+ return `${timestamp} ${eventType}`;
127
+ }).join("\n") + "\n";
128
+ }
129
+ export function renderChatContext(input) {
130
+ const rows = [
131
+ ["agent", input.agentId ?? "—"],
132
+ ["session", input.sessionId ?? "—"],
133
+ ["request", input.requestId ?? "—"],
134
+ ];
135
+ const labelW = Math.max(...rows.map(([l]) => l.length));
136
+ const lines = rows.map(([label, value]) => ` ${label.padEnd(labelW)} ${value}`);
137
+ return ["", " Context", " ───────", ...lines, ""].join("\n");
138
+ }
139
+ export function renderChatHelp() {
140
+ const sections = [
141
+ {
142
+ heading: "Context & navigation",
143
+ rows: [
144
+ ["/context", "Show current agent / session / request"],
145
+ ["/new", "Clear session — start a fresh conversation"],
146
+ ["/agent <id>", "Switch agent for new requests"],
147
+ ["/session", "Print current session id"],
148
+ ["/sessions", "List recent sessions"],
149
+ ["/resume <id>", "Resume an existing session"],
150
+ ["/request [id]", "Show or select active request"],
151
+ ["/requests", "List requests for current session / agent"],
152
+ ],
153
+ },
154
+ {
155
+ heading: "Approvals",
156
+ rows: [
157
+ ["/approvals", "List pending approvals"],
158
+ ["/approve <id>", "Approve a pending approval"],
159
+ ["/reject <id>", "Reject a pending approval"],
160
+ ["/cancel", "Cancel the latest active request"],
161
+ ],
162
+ },
163
+ {
164
+ heading: "Diagnostics",
165
+ rows: [
166
+ ["/events", "Persisted events for the latest request"],
167
+ ["/trace", "Trace items for the latest request"],
168
+ ["/health", "Runtime health snapshot"],
169
+ ["/overview", "Runtime operator overview"],
170
+ ],
171
+ },
172
+ {
173
+ heading: "Session",
174
+ rows: [
175
+ ["/help", "Show this help"],
176
+ ["/exit", "Quit chat"],
177
+ ],
178
+ },
179
+ ];
180
+ const allRows = sections.flatMap((s) => s.rows);
181
+ const cmdW = Math.max(...allRows.map(([cmd]) => cmd.length));
182
+ const out = [""];
183
+ for (const section of sections) {
184
+ out.push(` ${section.heading}`);
185
+ out.push(` ${"─".repeat(section.heading.length)}`);
186
+ for (const [cmd, desc] of section.rows) {
187
+ out.push(` ${cmd.padEnd(cmdW)} ${desc}`);
188
+ }
189
+ out.push("");
190
+ }
191
+ out.push(" Starter tasks:");
192
+ out.push(" ─────────────");
193
+ out.push(" Inspect this workspace and explain the main entry points.");
194
+ out.push(" Review this project structure before making any edits.");
195
+ out.push(" Find the likeliest config issue and propose the smallest fix.");
196
+ out.push("");
197
+ return out.join("\n");
198
+ }
@@ -0,0 +1,15 @@
1
+ export type ChatWorkspaceModelInfo = {
2
+ provider?: string;
3
+ model?: string;
4
+ baseUrl?: string;
5
+ };
6
+ export declare function normalizeChatCommand(line: string): {
7
+ name: string;
8
+ arg?: string;
9
+ } | null;
10
+ export declare function readChatWorkspaceModelInfo(workspaceRoot: string, agentId?: string): ChatWorkspaceModelInfo | undefined;
11
+ export declare function renderChatRuntimeFailure(output: string, modelInfo?: ChatWorkspaceModelInfo): string;
12
+ export declare function probeChatWorkspace(input: {
13
+ workspaceRoot: string;
14
+ agentId?: string;
15
+ }): Promise<string | undefined>;