@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.
- package/README.md +17 -1
- package/README.zh.md +17 -1
- package/dist/acp.d.ts +1 -116
- package/dist/acp.js +1 -310
- package/dist/api.d.ts +4 -2
- package/dist/api.js +4 -1
- package/dist/cli/chat-interactive.d.ts +24 -0
- package/dist/cli/chat-interactive.js +244 -0
- package/dist/cli/chat-rendering.d.ts +9 -0
- package/dist/cli/chat-rendering.js +102 -0
- package/dist/cli/chat-stream.d.ts +23 -0
- package/dist/cli/chat-stream.js +330 -0
- package/dist/cli/chat-ui.d.ts +20 -0
- package/dist/cli/chat-ui.js +198 -0
- package/dist/cli/chat-workspace.d.ts +15 -0
- package/dist/cli/chat-workspace.js +205 -0
- package/dist/cli/main.d.ts +52 -0
- package/dist/cli/main.js +323 -0
- package/dist/cli/managed-service-commands.d.ts +23 -0
- package/dist/cli/managed-service-commands.js +63 -0
- package/dist/cli/managed-service.d.ts +27 -0
- package/dist/cli/managed-service.js +61 -0
- package/dist/cli/options-init-chat.d.ts +16 -0
- package/dist/cli/options-init-chat.js +108 -0
- package/dist/cli/options-runtime.d.ts +27 -0
- package/dist/cli/options-runtime.js +158 -0
- package/dist/cli/options-serve.d.ts +24 -0
- package/dist/cli/options-serve.js +166 -0
- package/dist/cli/options.d.ts +5 -0
- package/dist/cli/options.js +47 -0
- package/dist/cli/process-guards.d.ts +14 -0
- package/dist/cli/process-guards.js +139 -0
- package/dist/cli/request-tree.d.ts +12 -0
- package/dist/cli/request-tree.js +296 -0
- package/dist/cli/runtime-commands.d.ts +15 -0
- package/dist/cli/runtime-commands.js +247 -0
- package/dist/cli/runtime-output.d.ts +5 -0
- package/dist/cli/runtime-output.js +124 -0
- package/dist/cli/server-commands.d.ts +36 -0
- package/dist/cli/server-commands.js +250 -0
- package/dist/cli/workspace.d.ts +6 -0
- package/dist/cli/workspace.js +71 -0
- package/dist/cli.d.ts +1 -67
- package/dist/cli.js +2 -2734
- package/dist/client/acp.d.ts +1 -50
- package/dist/client/acp.js +1 -219
- package/dist/client/in-process.d.ts +5 -5
- package/dist/client/index.d.ts +2 -2
- package/dist/client/index.js +1 -1
- package/dist/contracts/runtime-evaluation.d.ts +103 -0
- package/dist/contracts/runtime-evaluation.js +1 -0
- package/dist/contracts/runtime-memory.d.ts +162 -0
- package/dist/contracts/runtime-memory.js +1 -0
- package/dist/contracts/runtime-observability.d.ts +248 -0
- package/dist/contracts/runtime-observability.js +1 -0
- package/dist/contracts/runtime-requests.d.ts +342 -0
- package/dist/contracts/runtime-requests.js +1 -0
- package/dist/contracts/runtime-scheduling.d.ts +146 -0
- package/dist/contracts/runtime-scheduling.js +1 -0
- package/dist/contracts/runtime.d.ts +5 -1042
- package/dist/contracts/runtime.js +27 -1
- package/dist/flow/build-flow-graph.js +4 -875
- package/dist/flow/flow-graph-normalization.d.ts +56 -0
- package/dist/flow/flow-graph-normalization.js +214 -0
- package/dist/flow/flow-graph-runtime.d.ts +8 -0
- package/dist/flow/flow-graph-runtime.js +107 -0
- package/dist/flow/flow-graph-upstream.d.ts +18 -0
- package/dist/flow/flow-graph-upstream.js +498 -0
- package/dist/flow/types.d.ts +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.js +2 -2
- package/dist/init-project.d.ts +1 -12
- package/dist/init-project.js +1 -651
- package/dist/{procedural → knowledge/procedural}/manager.d.ts +3 -3
- package/dist/{procedural → knowledge/procedural}/manager.js +6 -6
- package/dist/mcp.d.ts +2 -62
- package/dist/mcp.js +2 -253
- package/dist/package-version.d.ts +1 -1
- package/dist/package-version.js +1 -1
- package/dist/persistence/file-store.js +1 -1
- package/dist/persistence/sqlite-runtime.d.ts +19 -0
- package/dist/persistence/sqlite-runtime.js +86 -0
- package/dist/persistence/sqlite-store.js +11 -99
- package/dist/{request-events.d.ts → projections/request-events.d.ts} +1 -1
- package/dist/{upstream-events.js → projections/upstream-events.js} +1 -1
- package/dist/protocol/a2a/http-discovery.d.ts +39 -0
- package/dist/protocol/a2a/http-discovery.js +178 -0
- package/dist/protocol/a2a/http-rpc.d.ts +28 -0
- package/dist/protocol/a2a/http-rpc.js +623 -0
- package/dist/protocol/a2a/http.d.ts +72 -1
- package/dist/protocol/a2a/http.js +14 -1124
- package/dist/protocol/a2a/task-state.d.ts +29 -0
- package/dist/protocol/a2a/task-state.js +317 -0
- package/dist/protocol/acp/client.js +1 -1
- package/dist/protocol/acp/harness-client.d.ts +50 -0
- package/dist/protocol/acp/harness-client.js +219 -0
- package/dist/protocol/acp/server.d.ts +116 -0
- package/dist/protocol/acp/server.js +310 -0
- package/dist/protocol/ag-ui/http.js +1 -1
- package/dist/protocol/mcp/server.d.ts +76 -0
- package/dist/protocol/mcp/server.js +428 -0
- package/dist/resource/backend/workspace-scoped-backend.d.ts +40 -0
- package/dist/resource/backend/workspace-scoped-backend.js +296 -0
- package/dist/resource/mcp/tool-support.d.ts +35 -0
- package/dist/resource/mcp/tool-support.js +296 -0
- package/dist/resource/mcp-tool-support.d.ts +2 -35
- package/dist/resource/mcp-tool-support.js +2 -296
- package/dist/resource/providers/resource-provider.d.ts +22 -0
- package/dist/resource/providers/resource-provider.js +215 -0
- package/dist/resource/resource-impl.d.ts +3 -33
- package/dist/resource/resource-impl.js +2 -808
- package/dist/resource/resource-types.d.ts +33 -0
- package/dist/resource/resource-types.js +1 -0
- package/dist/resource/tools/function-tool-resolver.d.ts +2 -0
- package/dist/resource/tools/function-tool-resolver.js +306 -0
- package/dist/runtime/adapter/middleware-assembly.js +1 -1
- package/dist/runtime/adapter/model/invocation-request.js +2 -2
- package/dist/runtime/adapter/model/message-assembly.js +1 -1
- package/dist/runtime/agent-runtime-adapter.d.ts +3 -63
- package/dist/runtime/agent-runtime-adapter.js +5 -233
- package/dist/runtime/agent-runtime-assembly.d.ts +67 -0
- package/dist/runtime/agent-runtime-assembly.js +211 -0
- package/dist/runtime/harness/background-runtime.d.ts +1 -1
- package/dist/runtime/harness/events/event-sink.js +1 -1
- package/dist/runtime/harness/events/runtime-event-operations.d.ts +1 -1
- package/dist/runtime/harness/events/streaming.js +1 -1
- package/dist/runtime/harness/public-shapes.d.ts +43 -0
- package/dist/runtime/harness/public-shapes.js +186 -0
- package/dist/runtime/harness/run/inspection.js +2 -2
- package/dist/runtime/harness/run/resources.js +1 -1
- package/dist/runtime/harness/run/surface-semantics.js +1 -1
- package/dist/runtime/harness/system/inventory.d.ts +1 -1
- package/dist/runtime/harness/system/inventory.js +2 -2
- package/dist/runtime/harness/system/policy-engine.js +1 -1
- package/dist/runtime/harness/system/runtime-memory-manager.js +1 -1
- package/dist/runtime/harness/system/skill-requirements.d.ts +1 -1
- package/dist/runtime/harness/system/skill-requirements.js +1 -1
- package/dist/runtime/harness.d.ts +3 -2
- package/dist/runtime/harness.js +11 -191
- package/dist/runtime/maintenance/checkpoint-maintenance.js +1 -1
- package/dist/runtime/maintenance/runtime-record-maintenance.js +1 -1
- package/dist/runtime/parsing/output-content.d.ts +11 -0
- package/dist/runtime/parsing/output-content.js +442 -0
- package/dist/runtime/parsing/output-parsing.d.ts +3 -29
- package/dist/runtime/parsing/output-parsing.js +3 -806
- package/dist/runtime/parsing/output-recovery.d.ts +14 -0
- package/dist/runtime/parsing/output-recovery.js +288 -0
- package/dist/runtime/parsing/output-tool-args.d.ts +4 -0
- package/dist/runtime/parsing/output-tool-args.js +120 -0
- package/dist/runtime/support/runtime-factories.js +1 -1
- package/dist/scaffold/init-project.d.ts +12 -0
- package/dist/scaffold/init-project.js +651 -0
- package/dist/{extensions.d.ts → tooling/extensions.d.ts} +1 -1
- package/dist/{extensions.js → tooling/extensions.js} +3 -3
- package/dist/{tool-modules.d.ts → tooling/module-loader.d.ts} +1 -1
- package/dist/{tool-modules.js → tooling/module-loader.js} +2 -2
- package/dist/workspace/agent-binding-compiler.js +2 -2
- package/dist/workspace/compile.js +2 -2
- package/dist/workspace/object-loader-paths.d.ts +11 -0
- package/dist/workspace/object-loader-paths.js +75 -0
- package/dist/workspace/object-loader-readers.d.ts +21 -0
- package/dist/workspace/object-loader-readers.js +187 -0
- package/dist/workspace/object-loader.d.ts +0 -1
- package/dist/workspace/object-loader.js +6 -260
- package/dist/workspace/resource-compilers.js +1 -1
- package/dist/workspace/support/discovery.js +1 -1
- package/package.json +1 -1
- package/dist/runtime/adapter/index.d.ts +0 -13
- package/dist/runtime/adapter/index.js +0 -13
- package/dist/runtime/harness/index.d.ts +0 -19
- package/dist/runtime/harness/index.js +0 -19
- package/dist/runtime/maintenance/index.d.ts +0 -4
- package/dist/runtime/maintenance/index.js +0 -4
- package/dist/runtime/parsing/index.d.ts +0 -2
- package/dist/runtime/parsing/index.js +0 -2
- package/dist/runtime/support/index.d.ts +0 -4
- package/dist/runtime/support/index.js +0 -4
- package/dist/workspace/support/index.d.ts +0 -2
- package/dist/workspace/support/index.js +0 -2
- /package/dist/{procedural → knowledge/procedural}/config.d.ts +0 -0
- /package/dist/{procedural → knowledge/procedural}/config.js +0 -0
- /package/dist/{procedural → knowledge/procedural}/index.d.ts +0 -0
- /package/dist/{procedural → knowledge/procedural}/index.js +0 -0
- /package/dist/{presentation.d.ts → projections/presentation.d.ts} +0 -0
- /package/dist/{presentation.js → projections/presentation.js} +0 -0
- /package/dist/{request-events.js → projections/request-events.js} +0 -0
- /package/dist/{upstream-events.d.ts → projections/upstream-events.d.ts} +0 -0
- /package/dist/runtime/{support → env}/runtime-env.d.ts +0 -0
- /package/dist/runtime/{support → env}/runtime-env.js +0 -0
- /package/dist/runtime/{support → layout}/runtime-layout.d.ts +0 -0
- /package/dist/runtime/{support → layout}/runtime-layout.js +0 -0
- /package/dist/runtime/{support → prompts}/runtime-prompts.d.ts +0 -0
- /package/dist/runtime/{support → prompts}/runtime-prompts.js +0 -0
- /package/dist/runtime/{support → skills}/skill-metadata.d.ts +0 -0
- /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>;
|