diff --git a/packages/events/src/agent-runtime.test.ts b/packages/events/src/agent-runtime.test.ts index 1d152ce9..8ae570d8 100644 --- a/packages/events/src/agent-runtime.test.ts +++ b/packages/events/src/agent-runtime.test.ts @@ -144,8 +144,9 @@ describe('agent runtime contract baseline', () => { createdAt: '2026-04-04T12:00:00.000Z', statusAtCapture: 'waiting-approval', currentTaskId: 'task_cowork_1', + checkpointArtifactId: 'artifact://notelett/note-1', todoIds: ['todo_cowork_1'], - artifactRefs: [], + artifactRefs: ['artifact://notelett/note-1'], memoryRefs: [], approvalRefs: ['approval_1'], dispatchContext: { @@ -164,5 +165,6 @@ describe('agent runtime contract baseline', () => { expect(checkpoint.statusAtCapture).toBe('waiting-approval'); expect(checkpoint.resumeToken).toBe('task_cowork_1'); + expect(checkpoint.checkpointArtifactId).toBe('artifact://notelett/note-1'); }); }); diff --git a/packages/events/src/agent-runtime.ts b/packages/events/src/agent-runtime.ts index a4e38072..5ba0ec96 100644 --- a/packages/events/src/agent-runtime.ts +++ b/packages/events/src/agent-runtime.ts @@ -81,6 +81,7 @@ export const AgentCheckpointSchema = z.object({ createdAt: z.string().datetime(), statusAtCapture: AgentCheckpointStatusSchema, currentTaskId: z.string().min(1).nullable().optional(), + checkpointArtifactId: z.string().min(1).nullable().optional(), todoIds: z.array(z.string().min(1)), artifactRefs: z.array(z.string().min(1)), memoryRefs: z.array(z.string().min(1)), diff --git a/services/cowork-service/src/modules/agent-runtime/routes.test.ts b/services/cowork-service/src/modules/agent-runtime/routes.test.ts index e55a65d5..6810506a 100644 --- a/services/cowork-service/src/modules/agent-runtime/routes.test.ts +++ b/services/cowork-service/src/modules/agent-runtime/routes.test.ts @@ -89,6 +89,7 @@ describe('agent runtime routes', () => { updatedAt: '2026-04-04T08:10:00.000Z', sessionId: 'sess-1', eventId: 'evt_cowork_task_task-1', + checkpointArtifactId: 'artifact://notelett/note-1', }, ], }, @@ -102,6 +103,7 @@ describe('agent runtime routes', () => { sessionId: 'sess-1', productId: 'clawcowork', status: 'running', + checkpointArtifactId: 'artifact://notelett/note-1', correlationId: 'evt_cowork_task_task-1', }); }); @@ -232,6 +234,7 @@ describe('agent runtime routes', () => { completed: false, cancelled: false, completed_tool_calls: 2, + checkpoint_artifact_id: 'artifact://notelett/note-1', artifact_refs: ['artifact://notelett/note-1'], memory_refs: ['memory://mindlyst/memory-1'], approval_refs: ['approval://cowork/ap-1'], @@ -251,6 +254,7 @@ describe('agent runtime routes', () => { userId: 'demo-user', statusAtCapture: 'queued', resumeToken: 'task-1', + checkpointArtifactId: 'artifact://notelett/note-1', artifactRefs: ['artifact://notelett/note-1'], memoryRefs: ['memory://mindlyst/memory-1'], approvalRefs: ['approval://cowork/ap-1'], diff --git a/services/cowork-service/src/modules/agent-runtime/routes.ts b/services/cowork-service/src/modules/agent-runtime/routes.ts index d64606ff..3a935f15 100644 --- a/services/cowork-service/src/modules/agent-runtime/routes.ts +++ b/services/cowork-service/src/modules/agent-runtime/routes.ts @@ -279,6 +279,15 @@ function toAgentCheckpoint( : 'checkpoint available for resume', ].join('; '); + const artifactRefs = Array.isArray(checkpoint.artifact_refs) + ? checkpoint.artifact_refs.filter((value): value is string => typeof value === 'string') + : []; + const checkpointArtifactId = + typeof checkpoint.checkpoint_artifact_id === 'string' && + checkpoint.checkpoint_artifact_id.length > 0 + ? checkpoint.checkpoint_artifact_id + : (artifactRefs[0] ?? null); + return AgentCheckpointSchema.parse({ checkpointId: `ckpt_${taskId}`, sessionId: @@ -292,10 +301,9 @@ function toAgentCheckpoint( createdAt, statusAtCapture: mapCheckpointStatus(task, checkpoint), currentTaskId: taskId, + checkpointArtifactId, todoIds: [`todo_${taskId}`], - artifactRefs: Array.isArray(checkpoint.artifact_refs) - ? checkpoint.artifact_refs.filter((value): value is string => typeof value === 'string') - : [], + artifactRefs, memoryRefs: Array.isArray(checkpoint.memory_refs) ? checkpoint.memory_refs.filter((value): value is string => typeof value === 'string') : [],