neoctl 0.2.31 → 0.2.32
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/agents/agent-activity.d.ts +3 -0
- package/dist/agents/agent-activity.js +33 -6
- package/dist/agents/agent-activity.js.map +1 -1
- package/dist/agents/agent-definition.d.ts +2 -2
- package/dist/agents/agent-definition.js +6 -6
- package/dist/agents/agent-definition.js.map +1 -1
- package/dist/agents/agent-report-tool.d.ts +1 -1
- package/dist/agents/agent-report-tool.js +4 -4
- package/dist/agents/agent-report-tool.js.map +1 -1
- package/dist/agents/agent-tool.d.ts +1 -1
- package/dist/agents/agent-tool.js +97 -18
- package/dist/agents/agent-tool.js.map +1 -1
- package/dist/agents/local-agent-task.d.ts +12 -0
- package/dist/agents/local-agent-task.js +38 -1
- package/dist/agents/local-agent-task.js.map +1 -1
- package/dist/agents/smoke-agents.js +37 -26
- package/dist/agents/smoke-agents.js.map +1 -1
- package/dist/context/compaction.js +1 -1
- package/dist/context/compaction.js.map +1 -1
- package/dist/context/prompts.js +6 -6
- package/dist/context/prompts.js.map +1 -1
- package/dist/context/smoke-context.js +15 -15
- package/dist/context/smoke-context.js.map +1 -1
- package/dist/core/query-engine.js +2 -0
- package/dist/core/query-engine.js.map +1 -1
- package/dist/core/query.js +88 -6
- package/dist/core/query.js.map +1 -1
- package/dist/core/run-agent.d.ts +13 -2
- package/dist/core/run-agent.js +16 -13
- package/dist/core/run-agent.js.map +1 -1
- package/dist/core/smoke-core-loop.js +55 -2
- package/dist/core/smoke-core-loop.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/plugins/smoke-plugin-system.js +14 -14
- package/dist/repl/index.js +14 -14
- package/dist/repl/index.js.map +1 -1
- package/dist/secrets/secret-redaction.d.ts +5 -0
- package/dist/secrets/secret-redaction.js +43 -0
- package/dist/secrets/secret-redaction.js.map +1 -1
- package/dist/secrets/secret-types.d.ts +4 -0
- package/dist/secrets/secret-types.js.map +1 -1
- package/dist/secrets/smoke-secrets.js +7 -3
- package/dist/secrets/smoke-secrets.js.map +1 -1
- package/dist/skills/smoke-skills.js +5 -5
- package/dist/skills/smoke-skills.js.map +1 -1
- package/dist/tasks/subagent-tools.d.ts +31 -0
- package/dist/tasks/{task-tools.js → subagent-tools.js} +26 -32
- package/dist/tasks/subagent-tools.js.map +1 -0
- package/dist/tools/builtins/edit-tool.js +24 -6
- package/dist/tools/builtins/edit-tool.js.map +1 -1
- package/dist/tools/builtins/exec-process-manager.d.ts +4 -0
- package/dist/tools/builtins/exec-process-manager.js +15 -6
- package/dist/tools/builtins/exec-process-manager.js.map +1 -1
- package/dist/tools/builtins/exec-tool.js +24 -8
- package/dist/tools/builtins/exec-tool.js.map +1 -1
- package/dist/tools/builtins/filesystem-tools.js +2 -4
- package/dist/tools/builtins/filesystem-tools.js.map +1 -1
- package/dist/tools/builtins/grep-tool.js +2 -3
- package/dist/tools/builtins/grep-tool.js.map +1 -1
- package/dist/tools/builtins/image-generation-tool.js +4 -4
- package/dist/tools/builtins/image-generation-tool.js.map +1 -1
- package/dist/tools/builtins/image-loader-tool.js +2 -3
- package/dist/tools/builtins/image-loader-tool.js.map +1 -1
- package/dist/tools/builtins/image-note-tool.js +0 -1
- package/dist/tools/builtins/image-note-tool.js.map +1 -1
- package/dist/tools/builtins/plan-tool.js +1 -1
- package/dist/tools/builtins/plan-tool.js.map +1 -1
- package/dist/tools/builtins/search-tool.js +3 -3
- package/dist/tools/builtins/search-tool.js.map +1 -1
- package/dist/tools/run-tool-use.js +3 -2
- package/dist/tools/run-tool-use.js.map +1 -1
- package/dist/tools/smoke-tool-system.js +44 -25
- package/dist/tools/smoke-tool-system.js.map +1 -1
- package/dist/tools/tool-catalog.d.ts +36 -0
- package/dist/tools/tool-catalog.js +64 -0
- package/dist/tools/tool-catalog.js.map +1 -0
- package/dist/tools/tool-orchestration.d.ts +20 -3
- package/dist/tools/tool-orchestration.js +29 -4
- package/dist/tools/tool-orchestration.js.map +1 -1
- package/dist/tools/tool.d.ts +13 -0
- package/dist/tools/tool.js.map +1 -1
- package/dist/types/events.d.ts +23 -0
- package/dist/web/index.d.ts +39 -0
- package/dist/web/index.js +293 -92
- package/dist/web/index.js.map +1 -1
- package/dist/web/runtime-context-protocol.d.ts +7 -0
- package/dist/web/runtime-context-protocol.js +3 -2
- package/dist/web/runtime-context-protocol.js.map +1 -1
- package/dist/web/smoke-runtime-context-protocol.js +10 -2
- package/dist/web/smoke-runtime-context-protocol.js.map +1 -1
- package/dist/web/smoke-web-history.js +59 -1
- package/dist/web/smoke-web-history.js.map +1 -1
- package/dist/web/smoke-web-terminal-tasks.js +1 -0
- package/dist/web/smoke-web-terminal-tasks.js.map +1 -1
- package/package.json +4 -4
- package/dist/tasks/task-tools.d.ts +0 -31
- package/dist/tasks/task-tools.js.map +0 -1
package/dist/web/index.js
CHANGED
|
@@ -14,6 +14,7 @@ import { findModelMetadata, loadModelCatalog, reasoningEffortsForModel, resolveC
|
|
|
14
14
|
import { CommunicationLogger, LoggingModelGateway } from "../model/communication-logger.js";
|
|
15
15
|
import { createModelGatewayFromConfig, createModelGatewayFromProcessEnv } from "../model/provider-factory.js";
|
|
16
16
|
import { ToolRegistry } from "../tools/registry.js";
|
|
17
|
+
import { builtinToolPresentation, toolPresentationForSource } from "../tools/tool-catalog.js";
|
|
17
18
|
import { editTool, writeTool } from "../tools/builtins/edit-tool.js";
|
|
18
19
|
import { createExecTool, createWriteStdinTool } from "../tools/builtins/exec-tool.js";
|
|
19
20
|
import { ExecProcessManager } from "../tools/builtins/exec-process-manager.js";
|
|
@@ -24,7 +25,7 @@ import { planTool } from "../tools/builtins/plan-tool.js";
|
|
|
24
25
|
import { createOpenAIImageGenerationTool } from "../tools/builtins/image-generation-tool.js";
|
|
25
26
|
import { createLoadImageTool } from "../tools/builtins/image-loader-tool.js";
|
|
26
27
|
import { createAgentTool, resumeAgentTask } from "../agents/agent-tool.js";
|
|
27
|
-
import {
|
|
28
|
+
import { createSubagentTools } from "../tasks/subagent-tools.js";
|
|
28
29
|
import { TaskStore } from "../tasks/task-store.js";
|
|
29
30
|
import { parseReplCommand, helpText, replCommandDefinitions } from "../repl/commands.js";
|
|
30
31
|
import { writeSessionMarkdownExport } from "../session/session-export.js";
|
|
@@ -136,7 +137,7 @@ export async function createWebRuntime(options = {}) {
|
|
|
136
137
|
if (catalogedToolNames.has(tool.name))
|
|
137
138
|
return;
|
|
138
139
|
catalogedToolNames.add(tool.name);
|
|
139
|
-
toolCatalog.push({ name: tool.name, ...item });
|
|
140
|
+
toolCatalog.push({ name: tool.name, presentation: toolPresentationForSource(tool.name, item.source), ...item });
|
|
140
141
|
};
|
|
141
142
|
const registerTool = (tool, item) => {
|
|
142
143
|
tools.register(tool);
|
|
@@ -175,7 +176,7 @@ export async function createWebRuntime(options = {}) {
|
|
|
175
176
|
};
|
|
176
177
|
return resumeAgentTask(taskId, directive, agentRuntime, taskStore, dummyContext);
|
|
177
178
|
};
|
|
178
|
-
for (const tool of
|
|
179
|
+
for (const tool of createSubagentTools(taskStore, resumeHandler))
|
|
179
180
|
registerTool(tool, { source: "builtin" });
|
|
180
181
|
const globalToolOverrides = normalizeToolOverrides(options.globalToolOverrides, toolCatalog);
|
|
181
182
|
const sessionToolOverrides = normalizeToolOverrides(options.sessionToolOverrides, toolCatalog);
|
|
@@ -290,7 +291,7 @@ function createTaskNotificationSource(taskStore) {
|
|
|
290
291
|
};
|
|
291
292
|
}
|
|
292
293
|
function syncImageGenerationTool(runtime, provider) {
|
|
293
|
-
runtime.tools.unregister("
|
|
294
|
+
runtime.tools.unregister("image_create");
|
|
294
295
|
if (provider === "openai")
|
|
295
296
|
runtime.tools.register(createOpenAIImageGenerationTool());
|
|
296
297
|
}
|
|
@@ -1004,7 +1005,7 @@ export class WebRepl {
|
|
|
1004
1005
|
this.pendingUserImageEchoIds = undefined;
|
|
1005
1006
|
this.pendingUserImageEchoMessageId = undefined;
|
|
1006
1007
|
this.finalizeForegroundView();
|
|
1007
|
-
this.
|
|
1008
|
+
this.cancelLiveToolLines(reason);
|
|
1008
1009
|
this.busy = false;
|
|
1009
1010
|
this.status = { ...this.status, phase: "ready", detail: undefined, currentTool: undefined, inputTokenUpdatedAt: undefined, outputTokenUpdatedAt: undefined, retryCooldownUntil: undefined };
|
|
1010
1011
|
this.broadcastSync();
|
|
@@ -1133,6 +1134,140 @@ export class WebRepl {
|
|
|
1133
1134
|
this.finalizeLiveLine(id);
|
|
1134
1135
|
this.liveToolLineIds.clear();
|
|
1135
1136
|
}
|
|
1137
|
+
cancelLiveToolLines(reason) {
|
|
1138
|
+
for (const id of this.liveToolLineIds.values()) {
|
|
1139
|
+
const line = this.lines.find((item) => item.id === id);
|
|
1140
|
+
const steps = (line?.toolStream?.steps ?? []).map((step) => step.status === "running" ? { ...step, status: "failed", phase: "cancelled" } : step);
|
|
1141
|
+
this.lines = this.lines.map((item) => item.id === id ? { ...item, live: false, kind: "error", titleStatus: "failure", bodyTitle: reason, toolStream: { ...item.toolStream, phase: "cancelled", message: reason, steps } } : item);
|
|
1142
|
+
this.queueDeltaOperation({ type: "line.patch", id, patch: { live: false, kind: "error", titleStatus: "failure", bodyTitle: reason, toolStream: { ...line?.toolStream, phase: "cancelled", message: reason, steps } } });
|
|
1143
|
+
}
|
|
1144
|
+
this.liveToolLineIds.clear();
|
|
1145
|
+
}
|
|
1146
|
+
patchLiveToolLine(toolUseId, patch) {
|
|
1147
|
+
const id = this.liveToolLineIds.get(toolUseId);
|
|
1148
|
+
if (id === undefined)
|
|
1149
|
+
return;
|
|
1150
|
+
const line = this.lines.find((item) => item.id === id);
|
|
1151
|
+
if (!line)
|
|
1152
|
+
return;
|
|
1153
|
+
this.lines = this.lines.map((item) => item.id === id ? { ...item, ...patch } : item);
|
|
1154
|
+
this.queueDeltaOperation({ type: "line.patch", id, patch });
|
|
1155
|
+
}
|
|
1156
|
+
applyToolProgress(event) {
|
|
1157
|
+
const id = this.liveToolLineIds.get(event.toolUse.id);
|
|
1158
|
+
if (id === undefined)
|
|
1159
|
+
return;
|
|
1160
|
+
const line = this.lines.find((item) => item.id === id);
|
|
1161
|
+
if (!line)
|
|
1162
|
+
return;
|
|
1163
|
+
const progress = event.progress;
|
|
1164
|
+
const previousStream = line.toolStream ?? {};
|
|
1165
|
+
if (progress.sequence !== undefined && previousStream.sequence !== undefined && progress.sequence <= previousStream.sequence)
|
|
1166
|
+
return;
|
|
1167
|
+
const channel = progress.channel ?? inferToolStreamChannel(progress.data);
|
|
1168
|
+
const operation = progress.operation ?? (channel === "stdout" || channel === "stderr" ? "append" : "replace");
|
|
1169
|
+
const stream = { ...previousStream };
|
|
1170
|
+
stream.channel = channel;
|
|
1171
|
+
stream.phase = progress.phase;
|
|
1172
|
+
stream.sequence = progress.sequence ?? stream.sequence;
|
|
1173
|
+
if (progress.progress) {
|
|
1174
|
+
stream.current = progress.progress.current;
|
|
1175
|
+
stream.total = progress.progress.total;
|
|
1176
|
+
stream.unit = progress.progress.unit;
|
|
1177
|
+
}
|
|
1178
|
+
const terminalDelta = terminalOutputDelta(progress.data);
|
|
1179
|
+
const textDelta = toolStreamTextDelta(progress.data);
|
|
1180
|
+
if (terminalDelta) {
|
|
1181
|
+
const key = terminalDelta.stream === "stderr" ? "stderr" : "stdout";
|
|
1182
|
+
stream[key] = operation === "replace"
|
|
1183
|
+
? trimToolStreamText(terminalDelta.text, 40_000)
|
|
1184
|
+
: appendToolStreamText(stream[key], terminalDelta.text, 40_000);
|
|
1185
|
+
stream.chunks = appendToolStreamChunk(stream.chunks, progress.sequence, key, terminalDelta.text, operation);
|
|
1186
|
+
}
|
|
1187
|
+
else if ((channel === "stdout" || channel === "stderr") && textDelta !== undefined) {
|
|
1188
|
+
stream[channel] = operation === "replace"
|
|
1189
|
+
? trimToolStreamText(textDelta, 40_000)
|
|
1190
|
+
: appendToolStreamText(stream[channel], textDelta, 40_000);
|
|
1191
|
+
stream.chunks = appendToolStreamChunk(stream.chunks, progress.sequence, channel, textDelta, operation);
|
|
1192
|
+
}
|
|
1193
|
+
else if ((channel === "patch" || channel === "artifact") && textDelta !== undefined) {
|
|
1194
|
+
stream.output = operation === "replace"
|
|
1195
|
+
? trimToolStreamText(textDelta, 40_000)
|
|
1196
|
+
: appendToolStreamText(stream.output, textDelta, 40_000);
|
|
1197
|
+
stream.chunks = appendToolStreamChunk(stream.chunks, progress.sequence, "output", textDelta, operation);
|
|
1198
|
+
stream.message = progress.message;
|
|
1199
|
+
}
|
|
1200
|
+
else if (channel === "item") {
|
|
1201
|
+
const key = progress.key || progress.phase || `step-${progress.sequence ?? Date.now()}`;
|
|
1202
|
+
const steps = [...(stream.steps ?? [])];
|
|
1203
|
+
const index = steps.findIndex((step) => step.key === key);
|
|
1204
|
+
if (operation === "remove") {
|
|
1205
|
+
if (index >= 0)
|
|
1206
|
+
steps.splice(index, 1);
|
|
1207
|
+
}
|
|
1208
|
+
else {
|
|
1209
|
+
const status = toolStreamStepStatus(progress.phase);
|
|
1210
|
+
const message = operation === "append" && index >= 0
|
|
1211
|
+
? `${steps[index].message}${progress.message}`
|
|
1212
|
+
: progress.message;
|
|
1213
|
+
const stepToolName = childToolName(progress.data) ?? steps[index]?.toolName;
|
|
1214
|
+
const step = {
|
|
1215
|
+
key,
|
|
1216
|
+
message,
|
|
1217
|
+
toolName: stepToolName,
|
|
1218
|
+
toolLabel: stepToolName ? toolTitle(stepToolName, "running") : steps[index]?.toolLabel,
|
|
1219
|
+
status,
|
|
1220
|
+
phase: progress.phase,
|
|
1221
|
+
sequence: progress.sequence,
|
|
1222
|
+
};
|
|
1223
|
+
if (index >= 0)
|
|
1224
|
+
steps[index] = step;
|
|
1225
|
+
else
|
|
1226
|
+
steps.push(step);
|
|
1227
|
+
}
|
|
1228
|
+
stream.steps = steps.slice(-24);
|
|
1229
|
+
stream.message = progress.message;
|
|
1230
|
+
}
|
|
1231
|
+
else if (operation === "append") {
|
|
1232
|
+
stream.message = `${stream.message ?? ""}${progress.message}`;
|
|
1233
|
+
}
|
|
1234
|
+
else if (operation === "remove") {
|
|
1235
|
+
stream.message = undefined;
|
|
1236
|
+
}
|
|
1237
|
+
else {
|
|
1238
|
+
stream.message = progress.message;
|
|
1239
|
+
}
|
|
1240
|
+
this.patchLiveToolLine(event.toolUse.id, { toolStream: stream });
|
|
1241
|
+
}
|
|
1242
|
+
applyAvailableToolResult(event) {
|
|
1243
|
+
const liveLineId = this.liveToolLineIds.get(event.toolUse.id);
|
|
1244
|
+
if (liveLineId === undefined)
|
|
1245
|
+
return;
|
|
1246
|
+
const liveLine = this.lines.find((item) => item.id === liveLineId);
|
|
1247
|
+
if (!liveLine)
|
|
1248
|
+
return;
|
|
1249
|
+
let replacement;
|
|
1250
|
+
for (const message of event.messages) {
|
|
1251
|
+
renderToolResultMessage(message, (line, toolUseId) => {
|
|
1252
|
+
if (toolUseId === event.toolUse.id)
|
|
1253
|
+
replacement = line;
|
|
1254
|
+
return liveLineId;
|
|
1255
|
+
}, runtimeToolResultPresenter(this.runtime));
|
|
1256
|
+
}
|
|
1257
|
+
const steps = (liveLine.toolStream?.steps ?? []).map((step) => step.status === "running" ? { ...step, status: event.ok ? "completed" : "failed" } : step);
|
|
1258
|
+
if (replacement) {
|
|
1259
|
+
this.replaceLine(liveLineId, {
|
|
1260
|
+
...replacement,
|
|
1261
|
+
live: false,
|
|
1262
|
+
presentationLevel: mergePresentationLevel(replacement.presentationLevel, liveLine.presentationLevel),
|
|
1263
|
+
toolDisplay: mergeToolDisplays(replacement.toolDisplay, liveLine.toolDisplay),
|
|
1264
|
+
toolStream: { ...liveLine.toolStream, steps, message: liveLine.toolStream?.message },
|
|
1265
|
+
});
|
|
1266
|
+
}
|
|
1267
|
+
else {
|
|
1268
|
+
this.replaceLine(liveLineId, { live: false, titleStatus: event.ok ? "success" : "failure", toolStream: { ...liveLine.toolStream, steps } });
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1136
1271
|
handleEvent(event) {
|
|
1137
1272
|
this.reduce(event);
|
|
1138
1273
|
if (event.type === "message" && this.matchesPendingUserImageEcho(event.message)) {
|
|
@@ -1169,6 +1304,18 @@ export class WebRepl {
|
|
|
1169
1304
|
this.appendLineText(id, event.text);
|
|
1170
1305
|
return;
|
|
1171
1306
|
}
|
|
1307
|
+
if (event.type === "tool.progress") {
|
|
1308
|
+
this.applyToolProgress(event);
|
|
1309
|
+
return;
|
|
1310
|
+
}
|
|
1311
|
+
if (event.type === "tool.result.available") {
|
|
1312
|
+
this.applyAvailableToolResult(event);
|
|
1313
|
+
return;
|
|
1314
|
+
}
|
|
1315
|
+
if (event.type === "tool.batch.completed") {
|
|
1316
|
+
this.broadcastSync();
|
|
1317
|
+
return;
|
|
1318
|
+
}
|
|
1172
1319
|
if (event.type === "message") {
|
|
1173
1320
|
let replacedStreamingContent = false;
|
|
1174
1321
|
if (event.message.role === "assistant" && this.assistantLineId !== undefined) {
|
|
@@ -1199,10 +1346,16 @@ export class WebRepl {
|
|
|
1199
1346
|
if (event.message.role === "tool_result") {
|
|
1200
1347
|
renderToolResultMessage(event.message, (line, toolUseId) => {
|
|
1201
1348
|
const liveLineId = this.liveToolLineIds.get(toolUseId);
|
|
1202
|
-
if (liveLineId === undefined)
|
|
1349
|
+
if (liveLineId === undefined) {
|
|
1350
|
+
const existing = this.lines.find((item) => item.toolUseId === toolUseId);
|
|
1351
|
+
if (existing) {
|
|
1352
|
+
this.replaceLine(existing.id, { ...line, toolStream: existing.toolStream, presentationLevel: mergePresentationLevel(line.presentationLevel, existing.presentationLevel), toolDisplay: mergeToolDisplays(line.toolDisplay, existing.toolDisplay) });
|
|
1353
|
+
return existing.id;
|
|
1354
|
+
}
|
|
1203
1355
|
return this.append(line);
|
|
1356
|
+
}
|
|
1204
1357
|
const liveLine = this.lines.find((item) => item.id === liveLineId);
|
|
1205
|
-
this.replaceLine(liveLineId, { ...line, presentationLevel: mergePresentationLevel(line.presentationLevel, liveLine?.presentationLevel), toolDisplay: mergeToolDisplays(line.toolDisplay, liveLine?.toolDisplay) });
|
|
1358
|
+
this.replaceLine(liveLineId, { ...line, toolStream: liveLine?.toolStream, presentationLevel: mergePresentationLevel(line.presentationLevel, liveLine?.presentationLevel), toolDisplay: mergeToolDisplays(line.toolDisplay, liveLine?.toolDisplay) });
|
|
1206
1359
|
this.liveToolLineIds.delete(toolUseId);
|
|
1207
1360
|
return liveLineId;
|
|
1208
1361
|
}, runtimeToolResultPresenter(this.runtime));
|
|
@@ -1233,10 +1386,8 @@ export class WebRepl {
|
|
|
1233
1386
|
}
|
|
1234
1387
|
if (event.type === "tool.finished") {
|
|
1235
1388
|
const id = this.liveToolLineIds.get(event.toolUse.id);
|
|
1236
|
-
if (id !== undefined)
|
|
1389
|
+
if (id !== undefined)
|
|
1237
1390
|
this.finalizeLiveLine(id);
|
|
1238
|
-
this.liveToolLineIds.delete(event.toolUse.id);
|
|
1239
|
-
}
|
|
1240
1391
|
return;
|
|
1241
1392
|
}
|
|
1242
1393
|
if (event.type === "terminal") {
|
|
@@ -1500,6 +1651,7 @@ export class WebRepl {
|
|
|
1500
1651
|
return createWebRuntimeContextPayload(snapshot, {
|
|
1501
1652
|
revision,
|
|
1502
1653
|
sessionId: this.runtime.engine.snapshot().session?.sessionId,
|
|
1654
|
+
toolPresentations: Object.fromEntries((this.runtime.toolSupport?.catalog ?? []).map((tool) => [tool.name, tool.presentation])),
|
|
1503
1655
|
});
|
|
1504
1656
|
}
|
|
1505
1657
|
publishRuntimeContext(targets) {
|
|
@@ -1971,6 +2123,71 @@ function pushTextBlock(blocks, text) {
|
|
|
1971
2123
|
else
|
|
1972
2124
|
blocks.push({ type: "text", text });
|
|
1973
2125
|
}
|
|
2126
|
+
function inferToolStreamChannel(data) {
|
|
2127
|
+
if (data && typeof data === "object" && !Array.isArray(data) && data.type === "terminal.output.delta") {
|
|
2128
|
+
return data.stream === "stderr" ? "stderr" : "stdout";
|
|
2129
|
+
}
|
|
2130
|
+
return "state";
|
|
2131
|
+
}
|
|
2132
|
+
function terminalOutputDelta(data) {
|
|
2133
|
+
if (!data || typeof data !== "object" || Array.isArray(data))
|
|
2134
|
+
return undefined;
|
|
2135
|
+
const record = data;
|
|
2136
|
+
if (record.type !== "terminal.output.delta" || typeof record.text !== "string")
|
|
2137
|
+
return undefined;
|
|
2138
|
+
return { stream: record.stream === "stderr" ? "stderr" : "stdout", text: record.text };
|
|
2139
|
+
}
|
|
2140
|
+
function toolStreamTextDelta(data) {
|
|
2141
|
+
if (typeof data === "string")
|
|
2142
|
+
return data;
|
|
2143
|
+
if (!data || typeof data !== "object" || Array.isArray(data))
|
|
2144
|
+
return undefined;
|
|
2145
|
+
const record = data;
|
|
2146
|
+
for (const value of [record.text, record.delta, record.patch, record.content]) {
|
|
2147
|
+
if (typeof value === "string")
|
|
2148
|
+
return value;
|
|
2149
|
+
}
|
|
2150
|
+
return undefined;
|
|
2151
|
+
}
|
|
2152
|
+
function childToolName(data) {
|
|
2153
|
+
if (!data || typeof data !== "object" || Array.isArray(data))
|
|
2154
|
+
return undefined;
|
|
2155
|
+
const childEvent = data.child_event;
|
|
2156
|
+
if (!childEvent || typeof childEvent !== "object" || Array.isArray(childEvent))
|
|
2157
|
+
return undefined;
|
|
2158
|
+
const toolUse = childEvent.toolUse;
|
|
2159
|
+
if (!toolUse || typeof toolUse !== "object" || Array.isArray(toolUse))
|
|
2160
|
+
return undefined;
|
|
2161
|
+
return stringValue(toolUse.name);
|
|
2162
|
+
}
|
|
2163
|
+
function appendToolStreamChunk(chunks, sequence, stream, text, operation) {
|
|
2164
|
+
const next = operation === "replace" ? [] : [...(chunks ?? [])];
|
|
2165
|
+
next.push({ sequence: sequence ?? (next.at(-1)?.sequence ?? 0) + 1, stream, text });
|
|
2166
|
+
let total = 0;
|
|
2167
|
+
const retained = [];
|
|
2168
|
+
for (let index = next.length - 1; index >= 0; index -= 1) {
|
|
2169
|
+
const chunk = next[index];
|
|
2170
|
+
if (total >= 40_000)
|
|
2171
|
+
break;
|
|
2172
|
+
retained.push(chunk);
|
|
2173
|
+
total += chunk.text.length;
|
|
2174
|
+
}
|
|
2175
|
+
return retained.reverse();
|
|
2176
|
+
}
|
|
2177
|
+
function trimToolStreamText(value, maxChars) {
|
|
2178
|
+
return value.length <= maxChars ? value : value.slice(value.length - maxChars);
|
|
2179
|
+
}
|
|
2180
|
+
function appendToolStreamText(current, delta, maxChars) {
|
|
2181
|
+
return trimToolStreamText(`${current ?? ""}${delta}`, maxChars);
|
|
2182
|
+
}
|
|
2183
|
+
function toolStreamStepStatus(phase) {
|
|
2184
|
+
const normalized = phase?.toLowerCase() ?? "";
|
|
2185
|
+
if (normalized.includes("fail") || normalized.includes("error") || normalized.includes("cancel") || normalized.includes("abort"))
|
|
2186
|
+
return "failed";
|
|
2187
|
+
if (normalized.includes("complete") || normalized.includes("finish") || normalized.includes("done") || normalized.includes("success"))
|
|
2188
|
+
return "completed";
|
|
2189
|
+
return "running";
|
|
2190
|
+
}
|
|
1974
2191
|
function reduceStatus(status, event) {
|
|
1975
2192
|
if (event.type === "state")
|
|
1976
2193
|
return { ...status, phase: event.phase, detail: event.detail, currentTool: event.phase === "running_tools" ? status.currentTool : undefined, usage: event.phase === "preparing" ? undefined : status.usage, streamedOutputTokens: event.phase === "preparing" ? 0 : status.streamedOutputTokens, inputTokenUpdatedAt: event.phase === "preparing" ? undefined : status.inputTokenUpdatedAt, outputTokenUpdatedAt: event.phase === "preparing" ? undefined : status.outputTokenUpdatedAt, retryCooldownUntil: event.phase === "preparing" ? undefined : status.retryCooldownUntil, activityTick: status.activityTick + 1 };
|
|
@@ -1990,8 +2207,10 @@ function reduceStatus(status, event) {
|
|
|
1990
2207
|
return { ...status, phase: "calling_model", detail: `retrying in ${(event.delayMs / 1000).toFixed(1)}s`, retryCooldownUntil: Date.now() + event.delayMs, activityTick: status.activityTick + 1 };
|
|
1991
2208
|
if (event.type === "tool.started")
|
|
1992
2209
|
return { ...status, phase: "running_tools", currentTool: { id: event.toolUse.id, name: event.toolUse.name, input: event.toolUse.input, startedAt: Date.now() }, activityTick: status.activityTick + 1 };
|
|
1993
|
-
if (event.type === "tool.
|
|
1994
|
-
return { ...status, currentTool: status.currentTool?.id === event.toolUse.id ?
|
|
2210
|
+
if (event.type === "tool.progress")
|
|
2211
|
+
return { ...status, phase: "running_tools", detail: event.progress.message || status.detail, currentTool: { id: event.toolUse.id, name: event.toolUse.name, input: event.toolUse.input, startedAt: status.currentTool?.id === event.toolUse.id ? status.currentTool.startedAt : Date.now() }, activityTick: status.activityTick + 1 };
|
|
2212
|
+
if (event.type === "tool.result.available" || event.type === "tool.finished" || event.type === "tool.batch.completed")
|
|
2213
|
+
return { ...status, currentTool: "toolUse" in event && status.currentTool?.id === event.toolUse.id ? undefined : status.currentTool, activityTick: status.activityTick + 1 };
|
|
1995
2214
|
if (event.type === "terminal")
|
|
1996
2215
|
return { ...status, phase: "stopped", detail: event.reason, currentTool: undefined, inputTokenUpdatedAt: undefined, outputTokenUpdatedAt: undefined, retryCooldownUntil: undefined, activityTick: status.activityTick + 1 };
|
|
1997
2216
|
if (event.type === "message" || event.type === "error")
|
|
@@ -2490,13 +2709,14 @@ function thinkingLine(text, live = false) {
|
|
|
2490
2709
|
return { kind: "thinking", title: titleForKind("thinking"), text, previewStyle: "summary", summaryMaxLines: THINKING_SUMMARY_MAX_LINES, live };
|
|
2491
2710
|
}
|
|
2492
2711
|
function formatToolUse(toolUse) {
|
|
2712
|
+
const toolPresentation = toolPresentationForSource(toolUse.name);
|
|
2493
2713
|
const presentationLevel = toolPresentationLevel(toolUse.name, toolUse.input);
|
|
2494
|
-
if (toolUse.name === "
|
|
2495
|
-
return { kind: "tool", toolName: toolUse.name, title:
|
|
2496
|
-
if (toolUse.name === "
|
|
2497
|
-
return { kind: "tool", toolName: toolUse.name, toolUseId: toolUse.id, title:
|
|
2714
|
+
if (toolUse.name === "plan_update" && isWebPlanPayload(toolUse.input))
|
|
2715
|
+
return { kind: "tool", toolName: toolUse.name, toolPresentation, title: toolPresentation.label, bodyTitle: webPlanBodyTitle(toolUse.input), text: serializeWebPlanPayload(toolUse.input), presentationLevel, collapsible: true };
|
|
2716
|
+
if (toolUse.name === "image_create")
|
|
2717
|
+
return { kind: "tool", toolName: toolUse.name, toolPresentation, toolUseId: toolUse.id, title: toolPresentation.label, bodyTitle: "图片模型处理中", text: JSON.stringify(toolUse.input ?? {}, null, 2), format: "plain", previewStyle: "summary", presentationLevel: "primary", collapsible: true };
|
|
2498
2718
|
const summary = summarizeToolUse(toolUse.name, toolUse.input);
|
|
2499
|
-
return { kind: "tool", toolName: toolUse.name, toolUseId: toolUse.id, title:
|
|
2719
|
+
return { kind: "tool", toolName: toolUse.name, toolPresentation, toolUseId: toolUse.id, title: toolPresentation.label, bodyTitle: summary.bodyTitle, text: summary.text, toolDisplay: buildToolUseDisplay(toolUse.name, toolUse.input), previewStyle: "summary", presentationLevel, collapsible: true };
|
|
2500
2720
|
}
|
|
2501
2721
|
function formatToolResultLine(toolName, output, ok, presentToolResult) {
|
|
2502
2722
|
const presentation = normalizeToolResultPresentation(presentToolResult?.(toolName, output, ok));
|
|
@@ -2507,6 +2727,7 @@ function formatToolResultLine(toolName, output, ok, presentToolResult) {
|
|
|
2507
2727
|
return {
|
|
2508
2728
|
kind: ok ? "tool" : "error",
|
|
2509
2729
|
toolName,
|
|
2730
|
+
toolPresentation: toolPresentationForSource(toolName),
|
|
2510
2731
|
title: presentation?.title ?? toolTitle(toolName, "finished"),
|
|
2511
2732
|
bodyTitle: presentation?.bodyTitle ?? formatted.bodyTitle,
|
|
2512
2733
|
titleStatus: ok ? "success" : "failure",
|
|
@@ -2522,7 +2743,7 @@ function formatToolResultLine(toolName, output, ok, presentToolResult) {
|
|
|
2522
2743
|
};
|
|
2523
2744
|
}
|
|
2524
2745
|
function toolPresentationLevel(toolName, payload) {
|
|
2525
|
-
if (toolName === "
|
|
2746
|
+
if (toolName === "image_create")
|
|
2526
2747
|
return "primary";
|
|
2527
2748
|
if (!isRecord(payload))
|
|
2528
2749
|
return "process";
|
|
@@ -2616,40 +2837,7 @@ function safeResourceUrl(value) {
|
|
|
2616
2837
|
return /^(?:https?:\/\/|\/)/i.test(value) && !/^\/\//.test(value);
|
|
2617
2838
|
}
|
|
2618
2839
|
function toolTitle(toolName, _phase) {
|
|
2619
|
-
|
|
2620
|
-
agent: "子任务",
|
|
2621
|
-
edit: "编辑文件",
|
|
2622
|
-
exec_command: "执行命令",
|
|
2623
|
-
write_stdin: "终端交互",
|
|
2624
|
-
expose_downloads: "文件下载",
|
|
2625
|
-
grep: "搜索文本",
|
|
2626
|
-
image2: "图片生成",
|
|
2627
|
-
image_note: "记录图片",
|
|
2628
|
-
list: "列出文件",
|
|
2629
|
-
load_image: "读取图片",
|
|
2630
|
-
plan: "任务计划",
|
|
2631
|
-
read: "读取文件",
|
|
2632
|
-
search: "网络搜索",
|
|
2633
|
-
write: "写入文件",
|
|
2634
|
-
SendMessage: "发送协作消息",
|
|
2635
|
-
sendmessage: "发送协作消息",
|
|
2636
|
-
TaskGet: "读取后台任务",
|
|
2637
|
-
taskget: "读取后台任务",
|
|
2638
|
-
TaskList: "后台任务列表",
|
|
2639
|
-
tasklist: "后台任务列表",
|
|
2640
|
-
TaskOutput: "读取任务输出",
|
|
2641
|
-
taskoutput: "读取任务输出",
|
|
2642
|
-
TaskResume: "继续后台任务",
|
|
2643
|
-
taskresume: "继续后台任务",
|
|
2644
|
-
TaskStop: "停止后台任务",
|
|
2645
|
-
taskstop: "停止后台任务",
|
|
2646
|
-
multi_tool_use: "并行执行工具",
|
|
2647
|
-
secret_list: "密钥列表",
|
|
2648
|
-
secret_info: "查看密钥",
|
|
2649
|
-
secret_request: "申请密钥",
|
|
2650
|
-
agent_report: "子任务报告",
|
|
2651
|
-
};
|
|
2652
|
-
return labels[toolName] ?? toolName;
|
|
2840
|
+
return builtinToolPresentation(toolName)?.label ?? toolName;
|
|
2653
2841
|
}
|
|
2654
2842
|
function summarizeToolUse(toolName, input) {
|
|
2655
2843
|
const purpose = toolUsePurpose(toolName, input);
|
|
@@ -2664,17 +2852,30 @@ function toolUsePurpose(toolName, input) {
|
|
|
2664
2852
|
const description = typeof input.description === "string" ? input.description.trim() : "";
|
|
2665
2853
|
if (description)
|
|
2666
2854
|
return description;
|
|
2855
|
+
const taskId = stringValue(input.task_id);
|
|
2856
|
+
if (toolName === "subagent_output")
|
|
2857
|
+
return taskId ? `读取子任务 ${taskId} 的输出` : "读取子任务输出";
|
|
2858
|
+
if (toolName === "subagent_list")
|
|
2859
|
+
return "查看子任务状态";
|
|
2860
|
+
if (toolName === "subagent_get")
|
|
2861
|
+
return taskId ? `查看子任务 ${taskId}` : "查看子任务";
|
|
2862
|
+
if (toolName === "subagent_stop")
|
|
2863
|
+
return taskId ? `停止子任务 ${taskId}` : "停止子任务";
|
|
2864
|
+
if (toolName === "subagent_resume")
|
|
2865
|
+
return taskId ? `恢复子任务 ${taskId}` : "恢复子任务";
|
|
2866
|
+
if (toolName === "subagent_message")
|
|
2867
|
+
return stringValue(input.target) ? `向 ${stringValue(input.target)} 发送消息` : "发送子任务消息";
|
|
2667
2868
|
if (toolName === "expose_downloads")
|
|
2668
2869
|
return "准备网页下载链接";
|
|
2669
|
-
if (toolName === "
|
|
2870
|
+
if (toolName === "file_read" && typeof input.path === "string")
|
|
2670
2871
|
return `读取 ${path.basename(input.path)}`;
|
|
2671
|
-
if (toolName === "
|
|
2872
|
+
if (toolName === "file_list" && typeof input.path === "string")
|
|
2672
2873
|
return `查看 ${input.path}`;
|
|
2673
|
-
if (toolName === "
|
|
2874
|
+
if (toolName === "file_search" && typeof input.query === "string")
|
|
2674
2875
|
return `搜索 ${input.query}`;
|
|
2675
|
-
if (toolName === "
|
|
2876
|
+
if (toolName === "file_write" && typeof input.path === "string")
|
|
2676
2877
|
return `写入 ${path.basename(input.path)}`;
|
|
2677
|
-
if (toolName === "
|
|
2878
|
+
if (toolName === "file_edit" && typeof input.path === "string")
|
|
2678
2879
|
return `修改 ${path.basename(input.path)}`;
|
|
2679
2880
|
return undefined;
|
|
2680
2881
|
}
|
|
@@ -2730,35 +2931,35 @@ function normalizeDisplayText(value) {
|
|
|
2730
2931
|
}
|
|
2731
2932
|
function buildToolUseDisplay(toolName, input) {
|
|
2732
2933
|
const data = isRecord(input) ? input : {};
|
|
2733
|
-
const purpose =
|
|
2734
|
-
const subject = toolName === "
|
|
2934
|
+
const purpose = toolUsePurpose(toolName, input);
|
|
2935
|
+
const subject = toolName === "terminal_run" ? undefined : toolDisplaySubject(toolName, data);
|
|
2735
2936
|
const facts = [];
|
|
2736
2937
|
const previews = [];
|
|
2737
|
-
if (toolName === "
|
|
2938
|
+
if (toolName === "terminal_run")
|
|
2738
2939
|
pushToolPreview(previews, "命令", "code", data.cmd);
|
|
2739
|
-
else if (toolName === "
|
|
2940
|
+
else if (toolName === "terminal_control") {
|
|
2740
2941
|
pushToolFact(facts, "会话", data.session_id, true);
|
|
2741
2942
|
pushToolFact(facts, "输入", data.chars, true);
|
|
2742
2943
|
}
|
|
2743
|
-
else if (toolName === "
|
|
2944
|
+
else if (toolName === "file_search")
|
|
2744
2945
|
pushToolFact(facts, "范围", data.path, true);
|
|
2745
|
-
else if (toolName === "
|
|
2946
|
+
else if (toolName === "image_inspect")
|
|
2746
2947
|
pushToolFact(facts, "图片", arrayLabel(data.imageRefs), true);
|
|
2747
|
-
else if (toolName === "
|
|
2948
|
+
else if (toolName === "image_create") {
|
|
2748
2949
|
pushToolFact(facts, "模式", data.mode === "edit" ? "编辑" : "生成");
|
|
2749
2950
|
pushToolFact(facts, "名称", data.semanticName);
|
|
2750
2951
|
}
|
|
2751
2952
|
else if (toolName === "expose_downloads")
|
|
2752
2953
|
pushToolFact(facts, "文件", arrayLabel(data.paths), true);
|
|
2753
|
-
else if (toolName === "
|
|
2954
|
+
else if (toolName === "subagent_message")
|
|
2754
2955
|
pushToolFact(facts, "接收方", data.target);
|
|
2755
|
-
else if (toolName.
|
|
2956
|
+
else if (toolName.startsWith("subagent_"))
|
|
2756
2957
|
pushToolFact(facts, "任务", data.task_id, true);
|
|
2757
2958
|
else if (toolName.startsWith("secret_")) {
|
|
2758
2959
|
pushToolFact(facts, "密钥", data.key, true);
|
|
2759
2960
|
pushToolFact(facts, "用途", data.reason);
|
|
2760
2961
|
}
|
|
2761
|
-
else if (toolName === "
|
|
2962
|
+
else if (toolName === "subagent_run") {
|
|
2762
2963
|
pushToolFact(facts, "任务", data.description ?? data.prompt);
|
|
2763
2964
|
pushToolFact(facts, "类型", data.subagent_type ?? data.mode);
|
|
2764
2965
|
}
|
|
@@ -2770,7 +2971,7 @@ function buildToolResultDisplay(toolName, output, ok) {
|
|
|
2770
2971
|
const previews = [];
|
|
2771
2972
|
let subject = toolDisplaySubject(toolName, data);
|
|
2772
2973
|
let purpose = stringValue(data.description);
|
|
2773
|
-
if ((toolName === "
|
|
2974
|
+
if ((toolName === "file_edit" || toolName === "file_write") && isEditToolOutput(data)) {
|
|
2774
2975
|
subject = data.path;
|
|
2775
2976
|
pushToolPreview(previews, undefined, "diff", compactEditDiff(data));
|
|
2776
2977
|
}
|
|
@@ -2782,43 +2983,43 @@ function buildToolResultDisplay(toolName, output, ok) {
|
|
|
2782
2983
|
if (outputText)
|
|
2783
2984
|
pushToolPreview(previews, data.stderr ? "输出 / 错误" : "输出", "code", outputText);
|
|
2784
2985
|
if (data.timed_out && !outputText)
|
|
2785
|
-
|
|
2986
|
+
pushToolFact(facts, "状态", "命令执行超时", false, "warning");
|
|
2786
2987
|
else if ((!ok || (typeof data.exit_code === "number" && data.exit_code !== 0)) && !outputText)
|
|
2787
|
-
|
|
2988
|
+
pushToolFact(facts, "状态", `退出码 ${data.exit_code ?? "未知"}`, false, "danger");
|
|
2788
2989
|
}
|
|
2789
|
-
else if (toolName === "
|
|
2990
|
+
else if (toolName === "file_search") {
|
|
2790
2991
|
subject = stringValue(data.query) || stringValue(data.grepPath) || stringValue(data.path);
|
|
2791
2992
|
pushToolPreview(previews, undefined, "list", grepPreview(data));
|
|
2792
2993
|
}
|
|
2793
|
-
else if (toolName === "
|
|
2994
|
+
else if (toolName === "web_search") {
|
|
2794
2995
|
subject = stringValue(data.query);
|
|
2795
2996
|
pushToolPreview(previews, undefined, "list", searchPreview(data));
|
|
2796
2997
|
}
|
|
2797
|
-
else if (toolName === "
|
|
2998
|
+
else if (toolName === "file_read") {
|
|
2798
2999
|
subject = stringValue(data.path);
|
|
2799
3000
|
if (numberValue(data.startLine) !== undefined && numberValue(data.endLine) !== undefined)
|
|
2800
3001
|
pushToolFact(facts, "范围", `${data.startLine}–${data.endLine} 行`);
|
|
2801
3002
|
pushToolPreview(previews, undefined, "code", data.content);
|
|
2802
3003
|
}
|
|
2803
|
-
else if (toolName === "
|
|
3004
|
+
else if (toolName === "file_list") {
|
|
2804
3005
|
subject = stringValue(data.path);
|
|
2805
3006
|
pushToolPreview(previews, undefined, "list", listPreview(data));
|
|
2806
3007
|
}
|
|
2807
|
-
else if (toolName === "
|
|
3008
|
+
else if (toolName === "image_create") {
|
|
2808
3009
|
subject = stringValue(data.semanticName);
|
|
2809
3010
|
pushToolFact(facts, "图片", `${numberValue(data.returnedImages) ?? arrayLength(data.images)} 张`);
|
|
2810
3011
|
pushToolFact(facts, "尺寸", data.size);
|
|
2811
3012
|
}
|
|
2812
|
-
else if (toolName === "
|
|
3013
|
+
else if (toolName === "image_inspect") {
|
|
2813
3014
|
subject = arrayLabel(data.imageRefs);
|
|
2814
3015
|
}
|
|
2815
3016
|
else if (toolResources(output)?.length) {
|
|
2816
3017
|
subject = toolResources(output)?.map((item) => item.label || item.downloadName).filter(Boolean).join("、");
|
|
2817
3018
|
}
|
|
2818
|
-
else if (toolName.
|
|
3019
|
+
else if (toolName.startsWith("subagent_") || toolName === "subagent_run") {
|
|
2819
3020
|
subject = stringValue(data.description) || stringValue(data.task_id) || stringValue(data.agent_id);
|
|
2820
3021
|
}
|
|
2821
|
-
else if (toolName === "
|
|
3022
|
+
else if (toolName === "subagent_message") {
|
|
2822
3023
|
subject = stringValue(data.target);
|
|
2823
3024
|
}
|
|
2824
3025
|
else if (toolName.startsWith("secret_")) {
|
|
@@ -2827,7 +3028,7 @@ function buildToolResultDisplay(toolName, output, ok) {
|
|
|
2827
3028
|
if (toolName === "secret_list")
|
|
2828
3029
|
pushToolFact(facts, "数量", `${arrayLength(data.secrets)} 项`);
|
|
2829
3030
|
}
|
|
2830
|
-
else if (toolName === "
|
|
3031
|
+
else if (toolName === "subagent_report") {
|
|
2831
3032
|
}
|
|
2832
3033
|
else {
|
|
2833
3034
|
subject = subject || stringValue(data.path) || stringValue(data.id) || stringValue(data.name);
|
|
@@ -2835,17 +3036,17 @@ function buildToolResultDisplay(toolName, output, ok) {
|
|
|
2835
3036
|
return normalizeToolDisplay({ subject, purpose, facts, previews });
|
|
2836
3037
|
}
|
|
2837
3038
|
function toolDisplaySubject(toolName, data) {
|
|
2838
|
-
if (["
|
|
3039
|
+
if (["file_read", "file_write", "file_edit", "file_list"].includes(toolName))
|
|
2839
3040
|
return stringValue(data.path);
|
|
2840
|
-
if (toolName === "
|
|
3041
|
+
if (toolName === "terminal_run")
|
|
2841
3042
|
return stringValue(data.cmd) || stringValue(data.command);
|
|
2842
|
-
if (toolName === "
|
|
3043
|
+
if (toolName === "file_search" || toolName === "web_search")
|
|
2843
3044
|
return stringValue(data.query);
|
|
2844
|
-
if (toolName === "
|
|
3045
|
+
if (toolName === "image_create")
|
|
2845
3046
|
return stringValue(data.semanticName);
|
|
2846
|
-
if (toolName === "
|
|
3047
|
+
if (toolName === "subagent_message")
|
|
2847
3048
|
return stringValue(data.target);
|
|
2848
|
-
if (toolName.
|
|
3049
|
+
if (toolName.startsWith("subagent_"))
|
|
2849
3050
|
return stringValue(data.task_id);
|
|
2850
3051
|
return undefined;
|
|
2851
3052
|
}
|
|
@@ -2926,24 +3127,24 @@ function taskStatusDisplay(value, ok) {
|
|
|
2926
3127
|
return status ? labels[status] ?? status : ok ? "已完成" : "失败";
|
|
2927
3128
|
}
|
|
2928
3129
|
function formatToolResult(toolName, output, ok) {
|
|
2929
|
-
if ((toolName === "
|
|
3130
|
+
if ((toolName === "file_edit" || toolName === "file_write") && isRecord(output) && isEditToolOutput(output))
|
|
2930
3131
|
return { text: formatEditToolDiff(output, ok), format: "diff", summaryMaxLines: EDIT_TOOL_SUMMARY_MAX_LINES };
|
|
2931
3132
|
if (isExecOutput(output))
|
|
2932
3133
|
return { text: formatExecToolResult(output, ok), format: "plain", summaryMaxLines: EXPANDED_SUMMARY_MAX_LINES };
|
|
2933
|
-
if (toolName === "
|
|
3134
|
+
if (toolName === "file_list" && isRecord(output))
|
|
2934
3135
|
return { text: formatListToolResult(output, ok) };
|
|
2935
|
-
if (toolName === "
|
|
3136
|
+
if (toolName === "file_read" && isRecord(output))
|
|
2936
3137
|
return { text: formatReadToolResult(output, ok) };
|
|
2937
|
-
if (toolName === "
|
|
3138
|
+
if (toolName === "file_search" && isRecord(output))
|
|
2938
3139
|
return { text: formatGrepToolResult(output, ok) };
|
|
2939
|
-
if (toolName === "
|
|
3140
|
+
if (toolName === "web_search" && isRecord(output))
|
|
2940
3141
|
return { text: formatWebSearchToolResult(output, ok), summaryMaxLines: EXPANDED_SUMMARY_MAX_LINES };
|
|
2941
|
-
if (toolName === "
|
|
3142
|
+
if (toolName === "image_create" && isRecord(output))
|
|
2942
3143
|
return { text: formatImageGenerationToolResult(output, ok), format: "plain", summaryMaxLines: 4 };
|
|
2943
3144
|
const resources = toolResources(output);
|
|
2944
3145
|
if (resources?.length)
|
|
2945
3146
|
return { text: ok ? "资源已准备好。" : "资源准备失败。", full: true, bodyTitle: ok ? "资源已就绪" : "资源准备失败" };
|
|
2946
|
-
if (toolName === "
|
|
3147
|
+
if (toolName === "plan_update" && isWebPlanPayload(output))
|
|
2947
3148
|
return { text: serializeWebPlanPayload(output), full: true, bodyTitle: webPlanBodyTitle(output) };
|
|
2948
3149
|
if (typeof output === "string")
|
|
2949
3150
|
return { text: output, format: hasAnsi(output) ? "ansi" : undefined, summaryMaxLines: EXPANDED_SUMMARY_MAX_LINES };
|