refactor: consolidate requests and finalize agent tool states

Share project JSON transport, interaction replies and report selectors.
Settle tool progress consistently for direct streams, reconnects and history, preserving failure reasons and stopped state.
This commit is contained in:
2026-11-09 17:55:00 +08:00
parent ad1f7ca7a9
commit 692bbf609c
38 changed files with 605 additions and 280 deletions
+21 -6
View File
@@ -47,7 +47,10 @@ export function upsertProgress(progress: AgentChatProgress[] | undefined, data:
return next;
}
export function completeRunningProgress(progress: AgentChatProgress[] | undefined) {
export function completeRunningProgress(
progress: AgentChatProgress[] | undefined,
status: "completed" | "error" | "cancelled" = "completed"
) {
return progress?.map((item) => {
if (item.status !== "running") {
return item;
@@ -56,7 +59,7 @@ export function completeRunningProgress(progress: AgentChatProgress[] | undefine
const endedAt = Date.now();
return {
...item,
status: "completed" as const,
status,
endedAt,
elapsedMs: undefined,
elapsedSnapshotAt: undefined,
@@ -154,9 +157,9 @@ export function applyPermissionResponse(
permission.requestId === requestId
? {
...permission,
status: toPermissionStatus(readString(payload.reply)),
status: payload.status === "error" ? "error" as const : toPermissionStatus(readString(payload.reply)),
repliedAt: Date.now(),
error: undefined
error: payload.status === "error" ? readString(payload.error) : undefined
}
: permission
);
@@ -235,7 +238,7 @@ export function applyQuestionResponse(questions: AgentQuestionRequest[] | undefi
}
export function finalizeAssistantMessageAfterAbort(message: AgentChatMessage): AgentChatMessage {
const progress = completeRunningProgress(message.progress);
const progress = completeRunningProgress(message.progress, "cancelled");
const todos = cancelRunningTodos(message.todos);
return {
@@ -266,6 +269,18 @@ export function finalizeAssistantMessageAfterAbort(message: AgentChatMessage): A
};
}
export function finalizeAssistantMessageAfterError(message: AgentChatMessage, reason: string): AgentChatMessage {
const settled = finalizeAssistantMessageAfterAbort(message);
return {
...settled,
content: message.content || `错误:${reason}`,
runError: reason,
progress: settled.progress?.map((item, index) => message.progress?.[index].status === "running"
? { ...item, status: "error", detail: item.detail ? `${item.detail}\n${reason}` : reason }
: item)
};
}
function toPermissionStatus(reply: string | undefined): AgentPermissionStatus {
if (reply === "always") {
return "approved_always";
@@ -340,7 +355,7 @@ function toToolRef(value: unknown): AgentInteractionToolRef | undefined {
}
function readProgressStatus(value: unknown): AgentChatProgress["status"] {
return value === "completed" || value === "error" ? value : "running";
return value === "completed" || value === "error" || value === "cancelled" ? value : "running";
}
function readTodoStatus(value: unknown): AgentTodoItem["status"] | undefined {