diff --git a/frontend-web/src/core/auth/task-deeplink.ts b/frontend-web/src/core/auth/task-deeplink.ts index 673073d5..6b51a73a 100644 --- a/frontend-web/src/core/auth/task-deeplink.ts +++ b/frontend-web/src/core/auth/task-deeplink.ts @@ -234,7 +234,7 @@ export interface TaskDeeplinkTarget { } /** xdfx(行动分析)开场信息里要追加的行动信息:行动标题 + 行动内容 + 行动id。 */ -interface ActionOpeningInfo { +export interface ActionOpeningInfo { /** 行动id(action_id)。 */ actionId?: string; /** 行动标题(行动名称 actionName)。 */ @@ -264,8 +264,12 @@ function buildOpeningText(detail: CopTaskDetail, taskId: string, action?: Action * 3qfx/rwfx 这类“按任务id 直接问答”的任务工作区,在 ``TaskContext`` 丢失但 * ``login.copTaskDetail`` 仍存在时,可用它重新拼出开场词做前端自恢复。 */ -export function buildTaskOpeningText(detail: CopTaskDetail, taskId: string): string { - return buildOpeningText(detail, taskId); +export function buildTaskOpeningText( + detail: CopTaskDetail, + taskId: string, + action?: ActionOpeningInfo, +): string { + return buildOpeningText(detail, taskId, action); } /** diff --git a/frontend-web/src/pages/AgentChatPage.tsx b/frontend-web/src/pages/AgentChatPage.tsx index 9bbb23cb..ddb3deaa 100644 --- a/frontend-web/src/pages/AgentChatPage.tsx +++ b/frontend-web/src/pages/AgentChatPage.tsx @@ -50,10 +50,18 @@ import { type TemplateRenderResult, } from "@/core/scheduled-tasks"; import { env } from "@/env"; -import { readTaskContext, taskThreadMetadata } from "@/core/auth/task-purpose"; +import { + readTaskContext, + taskThreadMetadata, + type TaskContext, +} from "@/core/auth/task-purpose"; import { TaskPurposePanel } from "@/strategy-components/components/task-components/TaskPurposePanel"; import { desensitize } from "@/lib/desensitize"; -import { buildTaskOpeningText, readCopTaskDetail } from "@/core/auth/task-deeplink"; +import { + buildTaskOpeningText, + readActionDetail, + readCopTaskDetail, +} from "@/core/auth/task-deeplink"; /** 内置「模板数据转换器」agent 的稳定 id。仅此 agent 的对话页显示「页面模板 + 渲染预览」调试入口。 */ const TEMPLATE_BUILDER_AGENT_ID = "template-json-builder"; @@ -104,7 +112,8 @@ export default function AgentChatPage({ // 任务深链上下文(taskId + 开场信息):闸门(rwfx)与纯绑定(3qfx/xdfx)都要读取。 const taskCtxOn = !!(taskGate || taskBind); - const taskContext = useMemo(() => { + const isXdfxTaskBind = !!chatBasePath?.includes("/plan-task-action/"); + const taskContext = useMemo(() => { if (!taskCtxOn) return null; const stored = readTaskContext(); if (stored && stored.agentId === agent_id) return stored; @@ -114,15 +123,28 @@ export default function AgentChatPage({ const detail = readCopTaskDetail(); const fallbackTaskId = detail?.id == null ? "" : String(detail.id).trim(); if (detail && fallbackTaskId && agent_id) { + const actionDetail = isXdfxTaskBind ? readActionDetail() : null; + const actionId = actionDetail?.id ? String(actionDetail.id).trim() : ""; + const actionTaskId = actionDetail?.taskId ? String(actionDetail.taskId).trim() : ""; + const hasMatchingAction = + !!actionId && !!actionTaskId && actionTaskId === fallbackTaskId; + const actionInfo = hasMatchingAction + ? { + actionId, + actionName: actionDetail?.actionName, + narration: actionDetail?.narration, + } + : undefined; return { taskId: fallbackTaskId, agentId: agent_id, - openingText: buildTaskOpeningText(detail, fallbackTaskId), + openingText: buildTaskOpeningText(detail, fallbackTaskId, actionInfo), + ...(hasMatchingAction ? { actionId, partitionByAction: true } : {}), }; } } return stored; - }, [agent_id, taskBind, taskCtxOn, taskGate]); + }, [agent_id, isXdfxTaskBind, taskBind, taskCtxOn, taskGate]); const taskId = taskCtxOn && taskContext && taskContext.agentId === agent_id ? taskContext.taskId diff --git a/frontend-web/src/strategy-components/components/task-components/TaskFxWorkspace.tsx b/frontend-web/src/strategy-components/components/task-components/TaskFxWorkspace.tsx index dfa1b7c2..650828f1 100644 --- a/frontend-web/src/strategy-components/components/task-components/TaskFxWorkspace.tsx +++ b/frontend-web/src/strategy-components/components/task-components/TaskFxWorkspace.tsx @@ -37,6 +37,7 @@ import { } from "@/core/auth/task-purpose"; import { fetchActionDetail, + readActionDetail, readCopTaskDetail, type ActionDetail, } from "@/core/auth/task-deeplink"; @@ -61,12 +62,22 @@ function useChatsBase(taskBase: string): { const agentId = agent_id ?? ""; const ctx = readTaskContext(); const detail = readCopTaskDetail(); + const isXdfx = taskBase.includes("/plan-task-action"); + const cachedAction = isXdfx ? readActionDetail() : null; const fallbackTaskId = detail?.id == null ? "" : String(detail.id).trim(); + const fallbackActionId = cachedAction?.id ? String(cachedAction.id).trim() : ""; + const fallbackActionTaskId = cachedAction?.taskId ? String(cachedAction.taskId).trim() : ""; + const hasMatchingAction = + !!fallbackActionId && !!fallbackActionTaskId && fallbackActionTaskId === fallbackTaskId; // 3qfx 偶发会出现 task context 丢失,但任务详情仍在 sessionStorage 的情况。 // 这里回退到任务详情里的 taskId,避免左侧对话列表直接失效成“空任务态”。 - const taskId = ctx?.taskId ?? fallbackTaskId; - const actionId = ctx?.partitionByAction ? (ctx.actionId ?? "") : ""; + const taskId = ctx?.taskId ?? (hasMatchingAction ? fallbackActionTaskId : fallbackTaskId); + const actionId = ctx?.partitionByAction + ? (ctx.actionId ?? "") + : hasMatchingAction + ? fallbackActionId + : ""; return { taskId, agentId, actionId, chatsBase: `${taskBase}/agent/${agentId}/chats` }; }