From 325913a532095bdcb48ddc379ff0ed6c1159f19f Mon Sep 17 00:00:00 2001 From: Haozhe Date: Fri, 14 Aug 2026 11:28:07 +0800 Subject: [PATCH] feat(kap-server): expose the subagent registry id in /tasks responses (#2907) --- packages/kap-server/src/protocol/task.ts | 1 + packages/kap-server/src/routes/tasks.ts | 3 +++ packages/kap-server/test/tasks.test.ts | 15 +++++++++++++++ packages/protocol/src/task.ts | 1 + 4 files changed, 20 insertions(+) diff --git a/packages/kap-server/src/protocol/task.ts b/packages/kap-server/src/protocol/task.ts index f1a84ed65..e3e646812 100644 --- a/packages/kap-server/src/protocol/task.ts +++ b/packages/kap-server/src/protocol/task.ts @@ -30,5 +30,6 @@ export const taskSchema = z.object({ model: z.string().optional(), /** Subagent tasks only: the child's effective thinking effort at spawn. */ thinking_effort: z.string().optional(), + agent_id: z.string().optional(), }); export type Task = z.infer; diff --git a/packages/kap-server/src/routes/tasks.ts b/packages/kap-server/src/routes/tasks.ts index e83bf9a0d..dd22740f0 100644 --- a/packages/kap-server/src/routes/tasks.ts +++ b/packages/kap-server/src/routes/tasks.ts @@ -375,6 +375,9 @@ function toWireTask( if (info.kind === 'agent' && info.thinkingEffort !== undefined) { base.thinking_effort = info.thinkingEffort; } + if (info.kind === 'agent' && info.agentId !== undefined) { + base.agent_id = info.agentId; + } if (output !== undefined) { base.output_preview = output.preview; base.output_bytes = output.bytes; diff --git a/packages/kap-server/test/tasks.test.ts b/packages/kap-server/test/tasks.test.ts index e70ddf50b..791b70cd0 100644 --- a/packages/kap-server/test/tasks.test.ts +++ b/packages/kap-server/test/tasks.test.ts @@ -35,6 +35,7 @@ interface TaskWire { completed_at?: string; output_preview?: string; output_bytes?: number; + agent_id?: string; } interface ListWire { @@ -214,6 +215,7 @@ describe('server-v2 /api/v1/sessions/{sid}/tasks', () => { status: 'running', model: 'provider/secondary', // subagent tasks expose the bound display model thinking_effort: 'low', // …and its effective thinking effort + agent_id: 'sub-1', }); expect(byId.get(agentId)?.command).toBeUndefined(); @@ -223,6 +225,8 @@ describe('server-v2 /api/v1/sessions/{sid}/tasks', () => { kind: 'tool', // question → tool status: 'running', }); + expect(byId.get(processId)?.agent_id).toBeUndefined(); + expect(byId.get(questionId)?.agent_id).toBeUndefined(); }); it('filters the list by wire status', async () => { @@ -245,11 +249,22 @@ describe('server-v2 /api/v1/sessions/{sid}/tasks', () => { const id = await createSession(); const tasks = await mainAgentTasks(id); const taskId = tasks.registerTask(fakeTask('process')); + const subagentId = tasks.registerTask(fakeTask('agent')); await flush(); const got = await getJson(`/api/v1/sessions/${id}/tasks/${taskId}`); expect(got.body.code).toBe(0); expect(got.body.data).toMatchObject({ id: taskId, session_id: id, kind: 'bash' }); + expect(got.body.data.agent_id).toBeUndefined(); + + const gotSubagent = await getJson(`/api/v1/sessions/${id}/tasks/${subagentId}`); + expect(gotSubagent.body.code).toBe(0); + expect(gotSubagent.body.data).toMatchObject({ + id: subagentId, + session_id: id, + kind: 'subagent', + agent_id: 'sub-1', + }); const missing = await getJson(`/api/v1/sessions/${id}/tasks/nope`); expect(missing.body.code).toBe(40406); diff --git a/packages/protocol/src/task.ts b/packages/protocol/src/task.ts index e18f69817..a96b3a8a1 100644 --- a/packages/protocol/src/task.ts +++ b/packages/protocol/src/task.ts @@ -30,6 +30,7 @@ export const taskSchema = z.object({ model: z.string().optional(), /** Subagent tasks only: the child's effective thinking effort at spawn. */ thinking_effort: z.string().optional(), + agent_id: z.string().optional(), }); export type Task = z.infer;