diff --git a/app/(chat)/api/chat/route.ts b/app/(chat)/api/chat/route.ts index 0791684c2..2131655fe 100644 --- a/app/(chat)/api/chat/route.ts +++ b/app/(chat)/api/chat/route.ts @@ -3014,6 +3014,7 @@ export async function POST(request: Request) { projectId, operationId, mutationOperation: operation, + sourceNodeIds: plan.sourceNodeIds, createdNodeIds: result.createdNodeIds, updatedNodeIds: result.updatedNodeIds, anchorNodeId: result.createdNodeIds[0] || result.updatedNodeIds[0] || null, diff --git a/lib/canvas/agent-result-view.ts b/lib/canvas/agent-result-view.ts index 2e060a3be..0a0581f39 100644 --- a/lib/canvas/agent-result-view.ts +++ b/lib/canvas/agent-result-view.ts @@ -17,6 +17,7 @@ export function buildCanvasAgentResultViewOperation(params: { projectId?: string | null; operationId: string; mutationOperation?: CanvasOperationKind; + sourceNodeIds?: string[]; createdNodeIds?: string[]; updatedNodeIds?: string[]; anchorNodeId?: string | null; @@ -29,17 +30,34 @@ export function buildCanvasAgentResultViewOperation(params: { if (!projectId || !operationId) return null; const createdNodeIds = normalizeNodeIds(params.createdNodeIds); - const updatedNodeIds = normalizeNodeIds(params.updatedNodeIds).filter( + const sourceNodeIds = normalizeNodeIds(params.sourceNodeIds).filter( (nodeId) => !createdNodeIds.includes(nodeId) ); - const nodeIds = createdNodeIds.length > 0 ? createdNodeIds : updatedNodeIds; + const updatedNodeIds = normalizeNodeIds(params.updatedNodeIds).filter( + (nodeId) => !createdNodeIds.includes(nodeId) && !sourceNodeIds.includes(nodeId) + ); + const hasCreatedResult = createdNodeIds.length > 0; + const comparisonNodeIds = + hasCreatedResult && sourceNodeIds.length > 0 + ? [...sourceNodeIds, ...createdNodeIds] + : []; + const nodeIds = + comparisonNodeIds.length > 0 + ? comparisonNodeIds + : createdNodeIds.length > 0 + ? createdNodeIds + : updatedNodeIds; if (nodeIds.length === 0) return null; const requestedAnchorNodeId = String(params.anchorNodeId || "").trim(); - const anchorNodeId = nodeIds.includes(requestedAnchorNodeId) - ? requestedAnchorNodeId - : nodeIds[0]; - const hasCreatedResult = createdNodeIds.length > 0; + const anchorNodeId = + comparisonNodeIds.length > 0 + ? sourceNodeIds.includes(requestedAnchorNodeId) + ? requestedAnchorNodeId + : sourceNodeIds[0] + : nodeIds.includes(requestedAnchorNodeId) + ? requestedAnchorNodeId + : nodeIds[0]; const operation = nodeIds.length > 1 ? "focus_nodes" @@ -61,6 +79,8 @@ export function buildCanvasAgentResultViewOperation(params: { params.reason || (params.mutationOperation === "replace_node_media" ? "focus_canvas_agent_replaced_nodes" + : comparisonNodeIds.length > 0 + ? "focus_canvas_agent_writeback_comparison" : hasCreatedResult ? "focus_canvas_agent_writeback_result" : "focus_canvas_agent_updated_nodes"), diff --git a/tests/routes/canvas-chat-helpers.test.ts b/tests/routes/canvas-chat-helpers.test.ts index 5bf78b524..d3f5beb7a 100644 --- a/tests/routes/canvas-chat-helpers.test.ts +++ b/tests/routes/canvas-chat-helpers.test.ts @@ -2113,6 +2113,22 @@ test.describe("canvas chat pure helpers", () => { anchorNodeId: "new-image-1", }); + expect( + buildCanvasAgentResultViewOperation({ + projectId: plannerContext.projectId, + operationId: "operation-compare", + mutationOperation: "append_revision", + sourceNodeIds: ["image-1", " image-1 "], + createdNodeIds: ["new-image-1"], + anchorNodeId: "new-image-1", + }) + ).toMatchObject({ + operation: "focus_nodes", + nodeIds: ["image-1", "new-image-1"], + anchorNodeId: "image-1", + reason: "focus_canvas_agent_writeback_comparison", + }); + expect( buildCanvasAgentResultViewOperation({ projectId: plannerContext.projectId,