Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
774f39cbbe |
@@ -772,6 +772,9 @@ export const streamPromptResponse = async ({
|
|||||||
detail: buildToolProgressDetail(
|
detail: buildToolProgressDetail(
|
||||||
part.tool,
|
part.tool,
|
||||||
part.state.status,
|
part.state.status,
|
||||||
|
toolParams,
|
||||||
|
reason,
|
||||||
|
part.state.status === "error" ? part.state.error : undefined,
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
if (
|
if (
|
||||||
|
|||||||
@@ -356,6 +356,37 @@ export const normalizeToolStatus = (status: string) => {
|
|||||||
return "running";
|
return "running";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const formatProgressValue = (value: unknown): string => {
|
||||||
|
if (typeof value === "string") {
|
||||||
|
return value.length > 120 ? `${value.slice(0, 117)}...` : value;
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
typeof value === "number" ||
|
||||||
|
typeof value === "boolean" ||
|
||||||
|
value === null ||
|
||||||
|
value === undefined
|
||||||
|
) {
|
||||||
|
return String(value);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const serialized = JSON.stringify(value);
|
||||||
|
return serialized.length > 120 ? `${serialized.slice(0, 117)}...` : serialized;
|
||||||
|
} catch {
|
||||||
|
return "[unserializable]";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const summarizeToolParams = (params: Record<string, unknown>) => {
|
||||||
|
const ignoredKeys = new Set(["reason", "request_reason", "why", "purpose", "rationale"]);
|
||||||
|
const summary = Object.entries(params)
|
||||||
|
.filter(([key]) => !ignoredKeys.has(key))
|
||||||
|
.slice(0, 4)
|
||||||
|
.map(([key, value]) => `${key}=${formatProgressValue(value)}`)
|
||||||
|
.join(", ");
|
||||||
|
|
||||||
|
return summary || "无附加参数";
|
||||||
|
};
|
||||||
|
|
||||||
export const buildSessionStatusDetail = (status: { type: string; message?: string }) => {
|
export const buildSessionStatusDetail = (status: { type: string; message?: string }) => {
|
||||||
if (status.type === "retry") {
|
if (status.type === "retry") {
|
||||||
return status.message
|
return status.message
|
||||||
@@ -382,19 +413,25 @@ export const buildReasoningProgressDetail = (
|
|||||||
export const buildToolProgressDetail = (
|
export const buildToolProgressDetail = (
|
||||||
tool: string,
|
tool: string,
|
||||||
status: string,
|
status: string,
|
||||||
|
params: Record<string, unknown>,
|
||||||
|
reason: string,
|
||||||
|
error?: string,
|
||||||
) => {
|
) => {
|
||||||
const toolName = toolLabels[tool] ?? tool;
|
const toolName = toolLabels[tool] ?? tool;
|
||||||
|
const reasonText = reason ? `;调用原因:${reason}` : "";
|
||||||
|
const paramsText = `;关键参数:${summarizeToolParams(params)}`;
|
||||||
|
|
||||||
if (status === "error") {
|
if (status === "error") {
|
||||||
return `${toolName} 调用失败。`;
|
const errorText = error ? `;错误:${error}` : "";
|
||||||
|
return `${toolName} 调用失败${reasonText}${paramsText}${errorText}`;
|
||||||
}
|
}
|
||||||
if (status === "completed") {
|
if (status === "completed") {
|
||||||
return `${toolName} 已执行完成。`;
|
return `${toolName} 已执行完成${reasonText}${paramsText}`;
|
||||||
}
|
}
|
||||||
if (status === "pending") {
|
if (status === "pending") {
|
||||||
return `${toolName} 等待执行。`;
|
return `${toolName} 已进入待执行状态${reasonText}${paramsText}`;
|
||||||
}
|
}
|
||||||
return `${toolName} 正在执行。`;
|
return `${toolName} 正在执行${reasonText}${paramsText}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getToolProgressTitle = (tool: string, status: string) => {
|
export const getToolProgressTitle = (tool: string, status: string) => {
|
||||||
|
|||||||
@@ -168,7 +168,7 @@ describe("streamPromptResponse", () => {
|
|||||||
).toBe("最终分析结果。");
|
).toBe("最终分析结果。");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("keeps reasoning, tool parameters, and raw errors out of progress details", async () => {
|
it("keeps reasoning generic while preserving tool execution details", async () => {
|
||||||
const runtime = {
|
const runtime = {
|
||||||
subscribeEvents: async () =>
|
subscribeEvents: async () =>
|
||||||
createEventStream([
|
createEventStream([
|
||||||
@@ -246,7 +246,9 @@ describe("streamPromptResponse", () => {
|
|||||||
(item) => item.event === "progress" && item.data.id === "tool-part-1",
|
(item) => item.event === "progress" && item.data.id === "tool-part-1",
|
||||||
);
|
);
|
||||||
expect(reasoningProgress?.data.detail).toBe("分析步骤已整理完成。");
|
expect(reasoningProgress?.data.detail).toBe("分析步骤已整理完成。");
|
||||||
expect(toolProgress?.data.detail).toBe("tjwater_cli 调用失败。");
|
expect(toolProgress?.data.detail).toBe(
|
||||||
|
"tjwater_cli 调用失败;调用原因:尝试突破分页限制;关键参数:command=network get-all-pipes-properties --limit 5000;错误:HTTP_422 raw backend payload with trace_id=secret-trace",
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("forwards opencode permission requests as SSE payloads", async () => {
|
it("forwards opencode permission requests as SSE payloads", async () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user