neoctl 0.2.31 → 0.2.33
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 +99 -20
- 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 +96 -8
- 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 +16 -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.d.ts +2 -0
- package/dist/tools/builtins/edit-tool.js +28 -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 +49 -26
- 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/types/messages.d.ts +8 -0
- package/dist/types/messages.js +16 -0
- package/dist/types/messages.js.map +1 -1
- package/dist/web/index.d.ts +39 -0
- package/dist/web/index.js +295 -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 +64 -2
- 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,7 +1304,21 @@ 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") {
|
|
1320
|
+
if (event.message.isMeta === true)
|
|
1321
|
+
return;
|
|
1173
1322
|
let replacedStreamingContent = false;
|
|
1174
1323
|
if (event.message.role === "assistant" && this.assistantLineId !== undefined) {
|
|
1175
1324
|
const text = assistantText(event.message);
|
|
@@ -1199,10 +1348,16 @@ export class WebRepl {
|
|
|
1199
1348
|
if (event.message.role === "tool_result") {
|
|
1200
1349
|
renderToolResultMessage(event.message, (line, toolUseId) => {
|
|
1201
1350
|
const liveLineId = this.liveToolLineIds.get(toolUseId);
|
|
1202
|
-
if (liveLineId === undefined)
|
|
1351
|
+
if (liveLineId === undefined) {
|
|
1352
|
+
const existing = this.lines.find((item) => item.toolUseId === toolUseId);
|
|
1353
|
+
if (existing) {
|
|
1354
|
+
this.replaceLine(existing.id, { ...line, toolStream: existing.toolStream, presentationLevel: mergePresentationLevel(line.presentationLevel, existing.presentationLevel), toolDisplay: mergeToolDisplays(line.toolDisplay, existing.toolDisplay) });
|
|
1355
|
+
return existing.id;
|
|
1356
|
+
}
|
|
1203
1357
|
return this.append(line);
|
|
1358
|
+
}
|
|
1204
1359
|
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) });
|
|
1360
|
+
this.replaceLine(liveLineId, { ...line, toolStream: liveLine?.toolStream, presentationLevel: mergePresentationLevel(line.presentationLevel, liveLine?.presentationLevel), toolDisplay: mergeToolDisplays(line.toolDisplay, liveLine?.toolDisplay) });
|
|
1206
1361
|
this.liveToolLineIds.delete(toolUseId);
|
|
1207
1362
|
return liveLineId;
|
|
1208
1363
|
}, runtimeToolResultPresenter(this.runtime));
|
|
@@ -1233,10 +1388,8 @@ export class WebRepl {
|
|
|
1233
1388
|
}
|
|
1234
1389
|
if (event.type === "tool.finished") {
|
|
1235
1390
|
const id = this.liveToolLineIds.get(event.toolUse.id);
|
|
1236
|
-
if (id !== undefined)
|
|
1391
|
+
if (id !== undefined)
|
|
1237
1392
|
this.finalizeLiveLine(id);
|
|
1238
|
-
this.liveToolLineIds.delete(event.toolUse.id);
|
|
1239
|
-
}
|
|
1240
1393
|
return;
|
|
1241
1394
|
}
|
|
1242
1395
|
if (event.type === "terminal") {
|
|
@@ -1500,6 +1653,7 @@ export class WebRepl {
|
|
|
1500
1653
|
return createWebRuntimeContextPayload(snapshot, {
|
|
1501
1654
|
revision,
|
|
1502
1655
|
sessionId: this.runtime.engine.snapshot().session?.sessionId,
|
|
1656
|
+
toolPresentations: Object.fromEntries((this.runtime.toolSupport?.catalog ?? []).map((tool) => [tool.name, tool.presentation])),
|
|
1503
1657
|
});
|
|
1504
1658
|
}
|
|
1505
1659
|
publishRuntimeContext(targets) {
|
|
@@ -1971,6 +2125,71 @@ function pushTextBlock(blocks, text) {
|
|
|
1971
2125
|
else
|
|
1972
2126
|
blocks.push({ type: "text", text });
|
|
1973
2127
|
}
|
|
2128
|
+
function inferToolStreamChannel(data) {
|
|
2129
|
+
if (data && typeof data === "object" && !Array.isArray(data) && data.type === "terminal.output.delta") {
|
|
2130
|
+
return data.stream === "stderr" ? "stderr" : "stdout";
|
|
2131
|
+
}
|
|
2132
|
+
return "state";
|
|
2133
|
+
}
|
|
2134
|
+
function terminalOutputDelta(data) {
|
|
2135
|
+
if (!data || typeof data !== "object" || Array.isArray(data))
|
|
2136
|
+
return undefined;
|
|
2137
|
+
const record = data;
|
|
2138
|
+
if (record.type !== "terminal.output.delta" || typeof record.text !== "string")
|
|
2139
|
+
return undefined;
|
|
2140
|
+
return { stream: record.stream === "stderr" ? "stderr" : "stdout", text: record.text };
|
|
2141
|
+
}
|
|
2142
|
+
function toolStreamTextDelta(data) {
|
|
2143
|
+
if (typeof data === "string")
|
|
2144
|
+
return data;
|
|
2145
|
+
if (!data || typeof data !== "object" || Array.isArray(data))
|
|
2146
|
+
return undefined;
|
|
2147
|
+
const record = data;
|
|
2148
|
+
for (const value of [record.text, record.delta, record.patch, record.content]) {
|
|
2149
|
+
if (typeof value === "string")
|
|
2150
|
+
return value;
|
|
2151
|
+
}
|
|
2152
|
+
return undefined;
|
|
2153
|
+
}
|
|
2154
|
+
function childToolName(data) {
|
|
2155
|
+
if (!data || typeof data !== "object" || Array.isArray(data))
|
|
2156
|
+
return undefined;
|
|
2157
|
+
const childEvent = data.child_event;
|
|
2158
|
+
if (!childEvent || typeof childEvent !== "object" || Array.isArray(childEvent))
|
|
2159
|
+
return undefined;
|
|
2160
|
+
const toolUse = childEvent.toolUse;
|
|
2161
|
+
if (!toolUse || typeof toolUse !== "object" || Array.isArray(toolUse))
|
|
2162
|
+
return undefined;
|
|
2163
|
+
return stringValue(toolUse.name);
|
|
2164
|
+
}
|
|
2165
|
+
function appendToolStreamChunk(chunks, sequence, stream, text, operation) {
|
|
2166
|
+
const next = operation === "replace" ? [] : [...(chunks ?? [])];
|
|
2167
|
+
next.push({ sequence: sequence ?? (next.at(-1)?.sequence ?? 0) + 1, stream, text });
|
|
2168
|
+
let total = 0;
|
|
2169
|
+
const retained = [];
|
|
2170
|
+
for (let index = next.length - 1; index >= 0; index -= 1) {
|
|
2171
|
+
const chunk = next[index];
|
|
2172
|
+
if (total >= 40_000)
|
|
2173
|
+
break;
|
|
2174
|
+
retained.push(chunk);
|
|
2175
|
+
total += chunk.text.length;
|
|
2176
|
+
}
|
|
2177
|
+
return retained.reverse();
|
|
2178
|
+
}
|
|
2179
|
+
function trimToolStreamText(value, maxChars) {
|
|
2180
|
+
return value.length <= maxChars ? value : value.slice(value.length - maxChars);
|
|
2181
|
+
}
|
|
2182
|
+
function appendToolStreamText(current, delta, maxChars) {
|
|
2183
|
+
return trimToolStreamText(`${current ?? ""}${delta}`, maxChars);
|
|
2184
|
+
}
|
|
2185
|
+
function toolStreamStepStatus(phase) {
|
|
2186
|
+
const normalized = phase?.toLowerCase() ?? "";
|
|
2187
|
+
if (normalized.includes("fail") || normalized.includes("error") || normalized.includes("cancel") || normalized.includes("abort"))
|
|
2188
|
+
return "failed";
|
|
2189
|
+
if (normalized.includes("complete") || normalized.includes("finish") || normalized.includes("done") || normalized.includes("success"))
|
|
2190
|
+
return "completed";
|
|
2191
|
+
return "running";
|
|
2192
|
+
}
|
|
1974
2193
|
function reduceStatus(status, event) {
|
|
1975
2194
|
if (event.type === "state")
|
|
1976
2195
|
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 +2209,10 @@ function reduceStatus(status, event) {
|
|
|
1990
2209
|
return { ...status, phase: "calling_model", detail: `retrying in ${(event.delayMs / 1000).toFixed(1)}s`, retryCooldownUntil: Date.now() + event.delayMs, activityTick: status.activityTick + 1 };
|
|
1991
2210
|
if (event.type === "tool.started")
|
|
1992
2211
|
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 ?
|
|
2212
|
+
if (event.type === "tool.progress")
|
|
2213
|
+
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 };
|
|
2214
|
+
if (event.type === "tool.result.available" || event.type === "tool.finished" || event.type === "tool.batch.completed")
|
|
2215
|
+
return { ...status, currentTool: "toolUse" in event && status.currentTool?.id === event.toolUse.id ? undefined : status.currentTool, activityTick: status.activityTick + 1 };
|
|
1995
2216
|
if (event.type === "terminal")
|
|
1996
2217
|
return { ...status, phase: "stopped", detail: event.reason, currentTool: undefined, inputTokenUpdatedAt: undefined, outputTokenUpdatedAt: undefined, retryCooldownUntil: undefined, activityTick: status.activityTick + 1 };
|
|
1997
2218
|
if (event.type === "message" || event.type === "error")
|
|
@@ -2490,13 +2711,14 @@ function thinkingLine(text, live = false) {
|
|
|
2490
2711
|
return { kind: "thinking", title: titleForKind("thinking"), text, previewStyle: "summary", summaryMaxLines: THINKING_SUMMARY_MAX_LINES, live };
|
|
2491
2712
|
}
|
|
2492
2713
|
function formatToolUse(toolUse) {
|
|
2714
|
+
const toolPresentation = toolPresentationForSource(toolUse.name);
|
|
2493
2715
|
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:
|
|
2716
|
+
if (toolUse.name === "plan_update" && isWebPlanPayload(toolUse.input))
|
|
2717
|
+
return { kind: "tool", toolName: toolUse.name, toolPresentation, title: toolPresentation.label, bodyTitle: webPlanBodyTitle(toolUse.input), text: serializeWebPlanPayload(toolUse.input), presentationLevel, collapsible: true };
|
|
2718
|
+
if (toolUse.name === "image_create")
|
|
2719
|
+
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
2720
|
const summary = summarizeToolUse(toolUse.name, toolUse.input);
|
|
2499
|
-
return { kind: "tool", toolName: toolUse.name, toolUseId: toolUse.id, title:
|
|
2721
|
+
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
2722
|
}
|
|
2501
2723
|
function formatToolResultLine(toolName, output, ok, presentToolResult) {
|
|
2502
2724
|
const presentation = normalizeToolResultPresentation(presentToolResult?.(toolName, output, ok));
|
|
@@ -2507,6 +2729,7 @@ function formatToolResultLine(toolName, output, ok, presentToolResult) {
|
|
|
2507
2729
|
return {
|
|
2508
2730
|
kind: ok ? "tool" : "error",
|
|
2509
2731
|
toolName,
|
|
2732
|
+
toolPresentation: toolPresentationForSource(toolName),
|
|
2510
2733
|
title: presentation?.title ?? toolTitle(toolName, "finished"),
|
|
2511
2734
|
bodyTitle: presentation?.bodyTitle ?? formatted.bodyTitle,
|
|
2512
2735
|
titleStatus: ok ? "success" : "failure",
|
|
@@ -2522,7 +2745,7 @@ function formatToolResultLine(toolName, output, ok, presentToolResult) {
|
|
|
2522
2745
|
};
|
|
2523
2746
|
}
|
|
2524
2747
|
function toolPresentationLevel(toolName, payload) {
|
|
2525
|
-
if (toolName === "
|
|
2748
|
+
if (toolName === "image_create")
|
|
2526
2749
|
return "primary";
|
|
2527
2750
|
if (!isRecord(payload))
|
|
2528
2751
|
return "process";
|
|
@@ -2616,40 +2839,7 @@ function safeResourceUrl(value) {
|
|
|
2616
2839
|
return /^(?:https?:\/\/|\/)/i.test(value) && !/^\/\//.test(value);
|
|
2617
2840
|
}
|
|
2618
2841
|
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;
|
|
2842
|
+
return builtinToolPresentation(toolName)?.label ?? toolName;
|
|
2653
2843
|
}
|
|
2654
2844
|
function summarizeToolUse(toolName, input) {
|
|
2655
2845
|
const purpose = toolUsePurpose(toolName, input);
|
|
@@ -2664,17 +2854,30 @@ function toolUsePurpose(toolName, input) {
|
|
|
2664
2854
|
const description = typeof input.description === "string" ? input.description.trim() : "";
|
|
2665
2855
|
if (description)
|
|
2666
2856
|
return description;
|
|
2857
|
+
const taskId = stringValue(input.task_id);
|
|
2858
|
+
if (toolName === "subagent_output")
|
|
2859
|
+
return taskId ? `读取子任务 ${taskId} 的输出` : "读取子任务输出";
|
|
2860
|
+
if (toolName === "subagent_list")
|
|
2861
|
+
return "查看子任务状态";
|
|
2862
|
+
if (toolName === "subagent_get")
|
|
2863
|
+
return taskId ? `查看子任务 ${taskId}` : "查看子任务";
|
|
2864
|
+
if (toolName === "subagent_stop")
|
|
2865
|
+
return taskId ? `停止子任务 ${taskId}` : "停止子任务";
|
|
2866
|
+
if (toolName === "subagent_resume")
|
|
2867
|
+
return taskId ? `恢复子任务 ${taskId}` : "恢复子任务";
|
|
2868
|
+
if (toolName === "subagent_message")
|
|
2869
|
+
return stringValue(input.target) ? `向 ${stringValue(input.target)} 发送消息` : "发送子任务消息";
|
|
2667
2870
|
if (toolName === "expose_downloads")
|
|
2668
2871
|
return "准备网页下载链接";
|
|
2669
|
-
if (toolName === "
|
|
2872
|
+
if (toolName === "file_read" && typeof input.path === "string")
|
|
2670
2873
|
return `读取 ${path.basename(input.path)}`;
|
|
2671
|
-
if (toolName === "
|
|
2874
|
+
if (toolName === "file_list" && typeof input.path === "string")
|
|
2672
2875
|
return `查看 ${input.path}`;
|
|
2673
|
-
if (toolName === "
|
|
2876
|
+
if (toolName === "file_search" && typeof input.query === "string")
|
|
2674
2877
|
return `搜索 ${input.query}`;
|
|
2675
|
-
if (toolName === "
|
|
2878
|
+
if (toolName === "file_write" && typeof input.path === "string")
|
|
2676
2879
|
return `写入 ${path.basename(input.path)}`;
|
|
2677
|
-
if (toolName === "
|
|
2880
|
+
if (toolName === "file_edit" && typeof input.path === "string")
|
|
2678
2881
|
return `修改 ${path.basename(input.path)}`;
|
|
2679
2882
|
return undefined;
|
|
2680
2883
|
}
|
|
@@ -2730,35 +2933,35 @@ function normalizeDisplayText(value) {
|
|
|
2730
2933
|
}
|
|
2731
2934
|
function buildToolUseDisplay(toolName, input) {
|
|
2732
2935
|
const data = isRecord(input) ? input : {};
|
|
2733
|
-
const purpose =
|
|
2734
|
-
const subject = toolName === "
|
|
2936
|
+
const purpose = toolUsePurpose(toolName, input);
|
|
2937
|
+
const subject = toolName === "terminal_run" ? undefined : toolDisplaySubject(toolName, data);
|
|
2735
2938
|
const facts = [];
|
|
2736
2939
|
const previews = [];
|
|
2737
|
-
if (toolName === "
|
|
2940
|
+
if (toolName === "terminal_run")
|
|
2738
2941
|
pushToolPreview(previews, "命令", "code", data.cmd);
|
|
2739
|
-
else if (toolName === "
|
|
2942
|
+
else if (toolName === "terminal_control") {
|
|
2740
2943
|
pushToolFact(facts, "会话", data.session_id, true);
|
|
2741
2944
|
pushToolFact(facts, "输入", data.chars, true);
|
|
2742
2945
|
}
|
|
2743
|
-
else if (toolName === "
|
|
2946
|
+
else if (toolName === "file_search")
|
|
2744
2947
|
pushToolFact(facts, "范围", data.path, true);
|
|
2745
|
-
else if (toolName === "
|
|
2948
|
+
else if (toolName === "image_inspect")
|
|
2746
2949
|
pushToolFact(facts, "图片", arrayLabel(data.imageRefs), true);
|
|
2747
|
-
else if (toolName === "
|
|
2950
|
+
else if (toolName === "image_create") {
|
|
2748
2951
|
pushToolFact(facts, "模式", data.mode === "edit" ? "编辑" : "生成");
|
|
2749
2952
|
pushToolFact(facts, "名称", data.semanticName);
|
|
2750
2953
|
}
|
|
2751
2954
|
else if (toolName === "expose_downloads")
|
|
2752
2955
|
pushToolFact(facts, "文件", arrayLabel(data.paths), true);
|
|
2753
|
-
else if (toolName === "
|
|
2956
|
+
else if (toolName === "subagent_message")
|
|
2754
2957
|
pushToolFact(facts, "接收方", data.target);
|
|
2755
|
-
else if (toolName.
|
|
2958
|
+
else if (toolName.startsWith("subagent_"))
|
|
2756
2959
|
pushToolFact(facts, "任务", data.task_id, true);
|
|
2757
2960
|
else if (toolName.startsWith("secret_")) {
|
|
2758
2961
|
pushToolFact(facts, "密钥", data.key, true);
|
|
2759
2962
|
pushToolFact(facts, "用途", data.reason);
|
|
2760
2963
|
}
|
|
2761
|
-
else if (toolName === "
|
|
2964
|
+
else if (toolName === "subagent_run") {
|
|
2762
2965
|
pushToolFact(facts, "任务", data.description ?? data.prompt);
|
|
2763
2966
|
pushToolFact(facts, "类型", data.subagent_type ?? data.mode);
|
|
2764
2967
|
}
|
|
@@ -2770,7 +2973,7 @@ function buildToolResultDisplay(toolName, output, ok) {
|
|
|
2770
2973
|
const previews = [];
|
|
2771
2974
|
let subject = toolDisplaySubject(toolName, data);
|
|
2772
2975
|
let purpose = stringValue(data.description);
|
|
2773
|
-
if ((toolName === "
|
|
2976
|
+
if ((toolName === "file_edit" || toolName === "file_write") && isEditToolOutput(data)) {
|
|
2774
2977
|
subject = data.path;
|
|
2775
2978
|
pushToolPreview(previews, undefined, "diff", compactEditDiff(data));
|
|
2776
2979
|
}
|
|
@@ -2782,43 +2985,43 @@ function buildToolResultDisplay(toolName, output, ok) {
|
|
|
2782
2985
|
if (outputText)
|
|
2783
2986
|
pushToolPreview(previews, data.stderr ? "输出 / 错误" : "输出", "code", outputText);
|
|
2784
2987
|
if (data.timed_out && !outputText)
|
|
2785
|
-
|
|
2988
|
+
pushToolFact(facts, "状态", "命令执行超时", false, "warning");
|
|
2786
2989
|
else if ((!ok || (typeof data.exit_code === "number" && data.exit_code !== 0)) && !outputText)
|
|
2787
|
-
|
|
2990
|
+
pushToolFact(facts, "状态", `退出码 ${data.exit_code ?? "未知"}`, false, "danger");
|
|
2788
2991
|
}
|
|
2789
|
-
else if (toolName === "
|
|
2992
|
+
else if (toolName === "file_search") {
|
|
2790
2993
|
subject = stringValue(data.query) || stringValue(data.grepPath) || stringValue(data.path);
|
|
2791
2994
|
pushToolPreview(previews, undefined, "list", grepPreview(data));
|
|
2792
2995
|
}
|
|
2793
|
-
else if (toolName === "
|
|
2996
|
+
else if (toolName === "web_search") {
|
|
2794
2997
|
subject = stringValue(data.query);
|
|
2795
2998
|
pushToolPreview(previews, undefined, "list", searchPreview(data));
|
|
2796
2999
|
}
|
|
2797
|
-
else if (toolName === "
|
|
3000
|
+
else if (toolName === "file_read") {
|
|
2798
3001
|
subject = stringValue(data.path);
|
|
2799
3002
|
if (numberValue(data.startLine) !== undefined && numberValue(data.endLine) !== undefined)
|
|
2800
3003
|
pushToolFact(facts, "范围", `${data.startLine}–${data.endLine} 行`);
|
|
2801
3004
|
pushToolPreview(previews, undefined, "code", data.content);
|
|
2802
3005
|
}
|
|
2803
|
-
else if (toolName === "
|
|
3006
|
+
else if (toolName === "file_list") {
|
|
2804
3007
|
subject = stringValue(data.path);
|
|
2805
3008
|
pushToolPreview(previews, undefined, "list", listPreview(data));
|
|
2806
3009
|
}
|
|
2807
|
-
else if (toolName === "
|
|
3010
|
+
else if (toolName === "image_create") {
|
|
2808
3011
|
subject = stringValue(data.semanticName);
|
|
2809
3012
|
pushToolFact(facts, "图片", `${numberValue(data.returnedImages) ?? arrayLength(data.images)} 张`);
|
|
2810
3013
|
pushToolFact(facts, "尺寸", data.size);
|
|
2811
3014
|
}
|
|
2812
|
-
else if (toolName === "
|
|
3015
|
+
else if (toolName === "image_inspect") {
|
|
2813
3016
|
subject = arrayLabel(data.imageRefs);
|
|
2814
3017
|
}
|
|
2815
3018
|
else if (toolResources(output)?.length) {
|
|
2816
3019
|
subject = toolResources(output)?.map((item) => item.label || item.downloadName).filter(Boolean).join("、");
|
|
2817
3020
|
}
|
|
2818
|
-
else if (toolName.
|
|
3021
|
+
else if (toolName.startsWith("subagent_") || toolName === "subagent_run") {
|
|
2819
3022
|
subject = stringValue(data.description) || stringValue(data.task_id) || stringValue(data.agent_id);
|
|
2820
3023
|
}
|
|
2821
|
-
else if (toolName === "
|
|
3024
|
+
else if (toolName === "subagent_message") {
|
|
2822
3025
|
subject = stringValue(data.target);
|
|
2823
3026
|
}
|
|
2824
3027
|
else if (toolName.startsWith("secret_")) {
|
|
@@ -2827,7 +3030,7 @@ function buildToolResultDisplay(toolName, output, ok) {
|
|
|
2827
3030
|
if (toolName === "secret_list")
|
|
2828
3031
|
pushToolFact(facts, "数量", `${arrayLength(data.secrets)} 项`);
|
|
2829
3032
|
}
|
|
2830
|
-
else if (toolName === "
|
|
3033
|
+
else if (toolName === "subagent_report") {
|
|
2831
3034
|
}
|
|
2832
3035
|
else {
|
|
2833
3036
|
subject = subject || stringValue(data.path) || stringValue(data.id) || stringValue(data.name);
|
|
@@ -2835,17 +3038,17 @@ function buildToolResultDisplay(toolName, output, ok) {
|
|
|
2835
3038
|
return normalizeToolDisplay({ subject, purpose, facts, previews });
|
|
2836
3039
|
}
|
|
2837
3040
|
function toolDisplaySubject(toolName, data) {
|
|
2838
|
-
if (["
|
|
3041
|
+
if (["file_read", "file_write", "file_edit", "file_list"].includes(toolName))
|
|
2839
3042
|
return stringValue(data.path);
|
|
2840
|
-
if (toolName === "
|
|
3043
|
+
if (toolName === "terminal_run")
|
|
2841
3044
|
return stringValue(data.cmd) || stringValue(data.command);
|
|
2842
|
-
if (toolName === "
|
|
3045
|
+
if (toolName === "file_search" || toolName === "web_search")
|
|
2843
3046
|
return stringValue(data.query);
|
|
2844
|
-
if (toolName === "
|
|
3047
|
+
if (toolName === "image_create")
|
|
2845
3048
|
return stringValue(data.semanticName);
|
|
2846
|
-
if (toolName === "
|
|
3049
|
+
if (toolName === "subagent_message")
|
|
2847
3050
|
return stringValue(data.target);
|
|
2848
|
-
if (toolName.
|
|
3051
|
+
if (toolName.startsWith("subagent_"))
|
|
2849
3052
|
return stringValue(data.task_id);
|
|
2850
3053
|
return undefined;
|
|
2851
3054
|
}
|
|
@@ -2926,24 +3129,24 @@ function taskStatusDisplay(value, ok) {
|
|
|
2926
3129
|
return status ? labels[status] ?? status : ok ? "已完成" : "失败";
|
|
2927
3130
|
}
|
|
2928
3131
|
function formatToolResult(toolName, output, ok) {
|
|
2929
|
-
if ((toolName === "
|
|
3132
|
+
if ((toolName === "file_edit" || toolName === "file_write") && isRecord(output) && isEditToolOutput(output))
|
|
2930
3133
|
return { text: formatEditToolDiff(output, ok), format: "diff", summaryMaxLines: EDIT_TOOL_SUMMARY_MAX_LINES };
|
|
2931
3134
|
if (isExecOutput(output))
|
|
2932
3135
|
return { text: formatExecToolResult(output, ok), format: "plain", summaryMaxLines: EXPANDED_SUMMARY_MAX_LINES };
|
|
2933
|
-
if (toolName === "
|
|
3136
|
+
if (toolName === "file_list" && isRecord(output))
|
|
2934
3137
|
return { text: formatListToolResult(output, ok) };
|
|
2935
|
-
if (toolName === "
|
|
3138
|
+
if (toolName === "file_read" && isRecord(output))
|
|
2936
3139
|
return { text: formatReadToolResult(output, ok) };
|
|
2937
|
-
if (toolName === "
|
|
3140
|
+
if (toolName === "file_search" && isRecord(output))
|
|
2938
3141
|
return { text: formatGrepToolResult(output, ok) };
|
|
2939
|
-
if (toolName === "
|
|
3142
|
+
if (toolName === "web_search" && isRecord(output))
|
|
2940
3143
|
return { text: formatWebSearchToolResult(output, ok), summaryMaxLines: EXPANDED_SUMMARY_MAX_LINES };
|
|
2941
|
-
if (toolName === "
|
|
3144
|
+
if (toolName === "image_create" && isRecord(output))
|
|
2942
3145
|
return { text: formatImageGenerationToolResult(output, ok), format: "plain", summaryMaxLines: 4 };
|
|
2943
3146
|
const resources = toolResources(output);
|
|
2944
3147
|
if (resources?.length)
|
|
2945
3148
|
return { text: ok ? "资源已准备好。" : "资源准备失败。", full: true, bodyTitle: ok ? "资源已就绪" : "资源准备失败" };
|
|
2946
|
-
if (toolName === "
|
|
3149
|
+
if (toolName === "plan_update" && isWebPlanPayload(output))
|
|
2947
3150
|
return { text: serializeWebPlanPayload(output), full: true, bodyTitle: webPlanBodyTitle(output) };
|
|
2948
3151
|
if (typeof output === "string")
|
|
2949
3152
|
return { text: output, format: hasAnsi(output) ? "ansi" : undefined, summaryMaxLines: EXPANDED_SUMMARY_MAX_LINES };
|