Browse Source

fix: preserve custom subagent task ids

Alvin Unreal 1 month ago
parent
commit
0ae07e3f81
2 changed files with 48 additions and 23 deletions
  1. 38 1
      src/hooks/task-session-manager/index.test.ts
  2. 10 22
      src/hooks/task-session-manager/index.ts

+ 38 - 1
src/hooks/task-session-manager/index.test.ts

@@ -1169,7 +1169,7 @@ describe('task-session-manager hook', () => {
     });
 
     const resume = {
-      args: { subagent_type: 'not-an-agent', task_id: 'exp-1' },
+      args: { subagent_type: 123, task_id: 'exp-1' },
     };
     await hook['tool.execute.before'](
       { tool: 'task', sessionID: 'parent-1', callID: 'resume' },
@@ -1179,6 +1179,43 @@ describe('task-session-manager hook', () => {
     expect(resume.args.task_id).toBeUndefined();
   });
 
+  test('custom subagent raw session task_id is preserved', async () => {
+    const { hook } = createHook();
+    const resume = {
+      args: { subagent_type: 'repro-helper', task_id: 'ses_custom123' },
+    };
+
+    await hook['tool.execute.before'](
+      { tool: 'task', sessionID: 'parent-1', callID: 'resume' },
+      resume,
+    );
+
+    expect(resume.args.task_id).toBe('ses_custom123');
+  });
+
+  test('custom subagent aliases resolve for the same custom agent', async () => {
+    const board = new BackgroundJobBoard();
+    const { hook } = createHook({ backgroundJobBoard: board });
+    board.registerLaunch({
+      taskID: 'child-1',
+      parentSessionID: 'parent-1',
+      agent: 'repro-helper',
+      description: 'ask secret letter',
+    });
+    board.updateStatus({ taskID: 'child-1', state: 'completed' });
+    board.markReconciled('child-1');
+
+    const resume = {
+      args: { subagent_type: 'repro-helper', task_id: 'rep-1' },
+    };
+    await hook['tool.execute.before'](
+      { tool: 'task', sessionID: 'parent-1', callID: 'resume' },
+      resume,
+    );
+
+    expect(resume.args.task_id).toBe('child-1');
+  });
+
   test('wrong parent or wrong agent alias does not resolve', async () => {
     const board = new BackgroundJobBoard();
     const { hook } = createHook({ backgroundJobBoard: board });

+ 10 - 22
src/hooks/task-session-manager/index.ts

@@ -1,6 +1,5 @@
 import path from 'node:path';
 import type { PluginInput } from '@opencode-ai/plugin';
-import type { AgentName } from '../../config';
 import {
   BackgroundJobBoard,
   type BackgroundJobRecord,
@@ -25,23 +24,11 @@ interface TaskArgs {
 interface PendingTaskCall {
   callId: string;
   parentSessionId: string;
-  agentType: AgentName;
+  agentType: string;
   label: string;
   resumedTaskId?: string;
 }
 
-const AGENT_NAME_SET = new Set<AgentName>([
-  'orchestrator',
-  'oracle',
-  'designer',
-  'explorer',
-  'librarian',
-  'fixer',
-  'observer',
-  'council',
-  'councillor',
-]);
-
 const MAX_PENDING_TASK_CALLS = 100;
 
 interface PendingContextFile {
@@ -108,10 +95,6 @@ function createOccurrenceId(
   return `anon:${hash}`;
 }
 
-function isAgentName(value: unknown): value is AgentName {
-  return typeof value === 'string' && AGENT_NAME_SET.has(value as AgentName);
-}
-
 function extractPath(output: string): string | undefined {
   return /<path>([^<]+)<\/path>/.exec(output)?.[1];
 }
@@ -492,18 +475,23 @@ export function createTaskSessionManagerHook(
       if (!isObjectRecord(output.args)) return;
 
       const args = output.args as TaskArgs;
-      if (!isAgentName(args.subagent_type)) {
+      if (
+        typeof args.subagent_type !== 'string' ||
+        args.subagent_type.trim() === ''
+      ) {
         if (typeof args.task_id === 'string' && args.task_id.trim() !== '') {
           delete args.task_id;
         }
         return;
       }
 
+      const agentType = args.subagent_type.trim();
+
       const label = deriveTaskSessionLabel({
         description:
           typeof args.description === 'string' ? args.description : undefined,
         prompt: typeof args.prompt === 'string' ? args.prompt : undefined,
-        agentType: args.subagent_type,
+        agentType,
       });
 
       const pendingCall: PendingTaskCall = {
@@ -512,7 +500,7 @@ export function createTaskSessionManagerHook(
           sessionID: input.sessionID,
         }),
         parentSessionId: input.sessionID,
-        agentType: args.subagent_type,
+        agentType,
         label,
       };
       rememberPendingCall(pendingCall);
@@ -525,7 +513,7 @@ export function createTaskSessionManagerHook(
       const remembered = backgroundJobBoard.resolveReusable(
         input.sessionID,
         requested,
-        args.subagent_type,
+        agentType,
       );
 
       if (!remembered) {