feat(agent): 完善分析编排与结果传输
This commit is contained in:
+119
-9
@@ -1,5 +1,7 @@
|
||||
import { type PermissionReply } from "../runtime/opencode.js";
|
||||
import {
|
||||
type ActivityPayload,
|
||||
initialActivity,
|
||||
type PermissionRequestPayload,
|
||||
type QuestionRequestPayload,
|
||||
type TodoUpdatePayload,
|
||||
@@ -28,6 +30,7 @@ type ToolCallPayload = {
|
||||
session_id?: string;
|
||||
tool?: string;
|
||||
params?: unknown;
|
||||
/** Legacy payload field. New tool calls inherit purpose from their Activity. */
|
||||
reason?: string;
|
||||
};
|
||||
|
||||
@@ -56,13 +59,13 @@ export const createInitialStreamingMessages = (
|
||||
id: createFrontendMessageId(),
|
||||
role: "assistant",
|
||||
content: "",
|
||||
progress: [
|
||||
activities: [
|
||||
{
|
||||
id: "request-received",
|
||||
phase: "start",
|
||||
id: initialActivity.id,
|
||||
status: "running",
|
||||
title: "已收到请求,正在启动 Agent 分析",
|
||||
detail: "已接收用户消息,正在建立会话并准备进入分析、规划和工具调用阶段。",
|
||||
title: initialActivity.title,
|
||||
reason: initialActivity.reason,
|
||||
actions: [],
|
||||
startedAt: Date.now(),
|
||||
elapsedMs: 0,
|
||||
elapsedSnapshotAt: Date.now(),
|
||||
@@ -72,6 +75,90 @@ export const createInitialStreamingMessages = (
|
||||
];
|
||||
};
|
||||
|
||||
const toFrontendActivityAction = (
|
||||
action: ActivityPayload["actions"][number],
|
||||
) => ({
|
||||
id: action.id,
|
||||
tool: action.tool,
|
||||
title: action.title,
|
||||
status: action.status,
|
||||
target: action.target,
|
||||
error: action.error,
|
||||
startedAt: action.started_at,
|
||||
endedAt: action.ended_at,
|
||||
elapsedMs: action.elapsed_ms,
|
||||
elapsedSnapshotAt: action.elapsed_ms === undefined ? undefined : Date.now(),
|
||||
durationMs: action.duration_ms,
|
||||
});
|
||||
|
||||
const toFrontendActivity = (activity: ActivityPayload) => ({
|
||||
id: activity.id,
|
||||
title: activity.title,
|
||||
reason: activity.reason,
|
||||
status: activity.status,
|
||||
actions: activity.actions.map(toFrontendActivityAction),
|
||||
startedAt: activity.started_at,
|
||||
endedAt: activity.ended_at,
|
||||
elapsedMs: activity.elapsed_ms,
|
||||
elapsedSnapshotAt: activity.elapsed_ms === undefined ? undefined : Date.now(),
|
||||
durationMs: activity.duration_ms,
|
||||
});
|
||||
|
||||
export const upsertBackendActivity = (
|
||||
activities: unknown,
|
||||
activity: ActivityPayload,
|
||||
) => {
|
||||
const next = Array.isArray(activities) ? [...activities] : [];
|
||||
const index = next.findIndex(
|
||||
(item) => isObjectRecord(item) && item.id === activity.id,
|
||||
);
|
||||
const nextItem = toFrontendActivity(activity);
|
||||
if (index >= 0) next[index] = nextItem;
|
||||
else next.push(nextItem);
|
||||
return next;
|
||||
};
|
||||
|
||||
export const completeBackendActivities = (
|
||||
activities: unknown,
|
||||
status: "completed" | "error" | "cancelled" = "completed",
|
||||
) => Array.isArray(activities)
|
||||
? activities.map((activity) => {
|
||||
if (!isObjectRecord(activity) || activity.status !== "running") return activity;
|
||||
const endedAt = Date.now();
|
||||
const startedAt = typeof activity.startedAt === "number"
|
||||
? activity.startedAt
|
||||
: endedAt;
|
||||
const actions = Array.isArray(activity.actions)
|
||||
? activity.actions.map((action) => {
|
||||
if (!isObjectRecord(action) || action.status !== "running") return action;
|
||||
const actionStartedAt = typeof action.startedAt === "number"
|
||||
? action.startedAt
|
||||
: endedAt;
|
||||
return {
|
||||
...action,
|
||||
status: status === "error" ? "error" : "completed",
|
||||
endedAt,
|
||||
elapsedMs: undefined,
|
||||
elapsedSnapshotAt: undefined,
|
||||
durationMs: Math.max(0, endedAt - actionStartedAt),
|
||||
...(status === "error"
|
||||
? { error: action.error ?? "活动执行失败" }
|
||||
: {}),
|
||||
};
|
||||
})
|
||||
: activity.actions;
|
||||
return {
|
||||
...activity,
|
||||
status,
|
||||
actions,
|
||||
endedAt,
|
||||
elapsedMs: undefined,
|
||||
elapsedSnapshotAt: undefined,
|
||||
durationMs: Math.max(0, endedAt - startedAt),
|
||||
};
|
||||
})
|
||||
: activities;
|
||||
|
||||
export const upsertBackendProgress = (
|
||||
progress: unknown,
|
||||
payload: Record<string, unknown>,
|
||||
@@ -152,6 +239,31 @@ export const cancelBackendTodos = (todos: unknown) =>
|
||||
})
|
||||
: todos;
|
||||
|
||||
export const completeBackendTodos = (todos: unknown) =>
|
||||
Array.isArray(todos)
|
||||
? todos.map((todoUpdate) => {
|
||||
if (!isObjectRecord(todoUpdate) || !Array.isArray(todoUpdate.todos)) {
|
||||
return todoUpdate;
|
||||
}
|
||||
return {
|
||||
...todoUpdate,
|
||||
todos: todoUpdate.todos.map((todo) => {
|
||||
if (!isObjectRecord(todo)) {
|
||||
return todo;
|
||||
}
|
||||
if (todo.status !== "pending" && todo.status !== "in_progress") {
|
||||
return todo;
|
||||
}
|
||||
return {
|
||||
...todo,
|
||||
status: "completed",
|
||||
updatedAt: Date.now(),
|
||||
};
|
||||
}),
|
||||
};
|
||||
})
|
||||
: todos;
|
||||
|
||||
export const updateLastAssistantMessage = (
|
||||
messages: unknown[],
|
||||
updater: (message: Record<string, unknown>) => Record<string, unknown>,
|
||||
@@ -249,10 +361,6 @@ export const appendBackendToolArtifact = (
|
||||
tool,
|
||||
kind: getToolArtifactKind(tool),
|
||||
title: getToolArtifactTitle(tool, params),
|
||||
description:
|
||||
typeof payload.reason === "string" && payload.reason.trim()
|
||||
? payload.reason.trim()
|
||||
: undefined,
|
||||
params,
|
||||
});
|
||||
return next;
|
||||
@@ -267,6 +375,8 @@ export const toFrontendPermission = (
|
||||
permission: payload.permission,
|
||||
patterns: payload.patterns,
|
||||
target: payload.target,
|
||||
activityId: payload.activity_id,
|
||||
reason: payload.reason,
|
||||
always: payload.always,
|
||||
tool: payload.tool,
|
||||
createdAt: payload.created_at,
|
||||
|
||||
Reference in New Issue
Block a user