feat(agent): align investigation reports and selected context

This commit is contained in:
2026-10-10 16:02:47 +08:00
parent d58bd19039
commit a31b76a793
18 changed files with 1172 additions and 44 deletions
+32 -3
View File
@@ -90,6 +90,11 @@ const payloadSchema = z.object({
approval_mode: z.enum(["request", "always"]).optional().default("request"),
capabilities: z.array(z.string().max(64)).max(20).optional().default([]),
trigger_context: agentTriggerContextSchema.optional(),
task_context: z.object({
report_revision: z.number().int().positive().optional(),
evidence_id: z.string().min(1).max(128).optional(),
gap_id: z.string().min(1).max(128).optional(),
}).strict().optional(),
});
const toSessionUiStateContext = (sessionRecord: SessionRecord) => ({
@@ -147,7 +152,8 @@ export const toCollaborationMessages = (messages: UIMessage[]) =>
messages.flatMap((message) => {
if (message.role !== "user" && message.role !== "assistant") return [];
const content = readUiMessageText(message);
return content ? [{ ...message, parts: [{ type: "text" as const, text: content }] } as UIMessage] : [];
const reference = message.parts.filter((part) => part.type === "data-task_context");
return content ? [{ ...message, parts: [{ type: "text" as const, text: content }, ...reference] } as UIMessage] : [];
});
const toLegacyMessages = (messages: UIMessage[]) =>
@@ -384,11 +390,18 @@ export const registerChatStreamRoute = (
boundOperationalSessionId = binding.sessionId;
const resolvedTaskContext = activeSessionRecord.taskId
&& (sessionPurpose === "task_collaboration" || sessionPurpose === "task_execution")
? await operationalTaskClient.getAgentContext(binding.sessionId, activeSessionRecord.taskId)
? await operationalTaskClient.getAgentContext(binding.sessionId, activeSessionRecord.taskId,
sessionPurpose === "task_collaboration" ? parsed.data.task_context?.report_revision : undefined)
: null;
const taskContext = sessionPurpose === "task_collaboration"
? resolvedTaskContext
: null;
if (taskContext) {
const report = taskContext.selected_report ?? taskContext.task.latest_report;
const reference = z.object({ revision: z.number().int().positive() }).passthrough().safeParse(report);
setRuntimeSessionContext({ ...getRuntimeSessionContext(binding.sessionId)!,
reportRevision: reference.success ? reference.data.revision : undefined });
}
const hasRuntimeConversation = hadExistingRuntimeSession
? await runtimeHasConversation(runtime, binding.sessionId)
: false;
@@ -882,10 +895,26 @@ export const registerChatStreamRoute = (
taskHeartbeat?.unref();
try {
if (taskContext) {
const raw = taskContext.selected_report ?? taskContext.task.latest_report;
const reportRef = z.object({ revision: z.number().int().positive(), execution_generation: z.number().int().positive().nullish() }).passthrough().safeParse(raw);
const generation = taskContext.task.execution_generation;
const reference = {
task_id: activeSessionRecord.taskId!,
execution_generation: reportRef.success ? reportRef.data.execution_generation ?? null
: typeof generation === "number" && generation > 0 ? generation : null,
report_revision: reportRef.success ? reportRef.data.revision : null,
};
const part = { type: "data-task_context" as const, data: reference };
assistantParts.push(part);
writeUiChunk(part);
syncLatestUiMessages();
}
const preparedMessage = taskContext
? [
"你正在与用户协作理解一个工况任务。只根据下面由后端授权返回的任务、计划、报告和证据快照解释判断;不要展示后台执行会话、工具轨迹或内部推理。若资料不足,明确说明缺口。用户要求变更任务时使用结构化工具写回。",
"你正在与用户协作理解一个工况任务。只根据下面由后端授权返回的任务、报告和证据解释判断;selected_report 存在时用户正在阅读该轮次与修订号,优先据此回答并明确引用。不要展示后台执行会话、工具轨迹或内部推理。普通提问不改变任务,只有用户明确补充的事实可用结构化工具记录并重新分析;假设和查询要求不能当作现场事实。queued 表示等待领取,不能声称已经开始分析。",
`任务快照:${JSON.stringify(taskContext)}`,
`当前讨论对象:${JSON.stringify(parsed.data.task_context ?? {})}`,
`用户问题:${promptText}`,
].join("\n\n")
: await buildPromptWithLearningContext(