From e6affc70533e0a605b16277843e8c24ac823bac0 Mon Sep 17 00:00:00 2001 From: HitMargin <142143104+2228293026@users.noreply.github.com> Date: Thu, 9 Apr 2026 21:53:07 +0800 Subject: [PATCH] =?UTF-8?q?1.=20=E4=BF=AE=E5=A4=8D=20src/commands/fork/ind?= =?UTF-8?q?ex.ts=20=E2=80=94=20=E5=B0=86=E7=A9=BA=20stub=20=E6=94=B9?= =?UTF-8?q?=E4=B8=BA=E6=9C=89=E6=95=88=E7=9A=84=20Command=20=E5=AE=9A?= =?UTF-8?q?=E4=B9=89=20=20=20=20=202.=20=E6=96=B0=E5=A2=9E=20src/commands/?= =?UTF-8?q?fork/fork.tsx=20=E2=80=94=20=E5=AE=8C=E6=95=B4=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0=20/fork=20=E5=91=BD=E4=BB=A4=EF=BC=8C=E5=A4=8D?= =?UTF-8?q?=E7=94=A8=E4=BA=86=20AgentTool=20=E7=9A=84=20fork=20=E5=AD=90?= =?UTF-8?q?=20agent=20=E9=80=BB=E8=BE=91=20(#221)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 1. 修复 src/commands/fork/index.ts — 将空 stub 改为有效的 Command 定义 2. 新增 src/commands/fork/fork.tsx — 完整实现 /fork 命令,复用了 AgentTool 的 fork 子 agent 逻辑 * Update src/commands/fork/fork.tsx Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * fix --------- Co-authored-by: HitMargin Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- src/commands/fork/fork.tsx | 73 ++++++++++++++++++++++++++++++++++++++ src/commands/fork/index.ts | 14 ++++++-- 2 files changed, 84 insertions(+), 3 deletions(-) create mode 100644 src/commands/fork/fork.tsx diff --git a/src/commands/fork/fork.tsx b/src/commands/fork/fork.tsx new file mode 100644 index 000000000..cf120c615 --- /dev/null +++ b/src/commands/fork/fork.tsx @@ -0,0 +1,73 @@ +import { feature } from 'bun:bundle' +import React from 'react' +import { AgentTool } from '../../tools/AgentTool/AgentTool.js' +import { isInForkChild } from '../../tools/AgentTool/forkSubagent.js' +import { logForDebugging } from '../../utils/debug.js' +import type { LocalJSXCommandOnDone, LocalJSXCommandContext } from '../../types/command.js' + +export async function call( + onDone: LocalJSXCommandOnDone, + context: LocalJSXCommandContext, + args: string, +): Promise { + // Check feature flag + if (!feature('FORK_SUBAGENT')) { + onDone('Fork subagent feature is not enabled. Set FEATURE_FORK_SUBAGENT=1 to enable.', { display: 'system' }) + return null + } + + // Recursive fork guard + if (isInForkChild(context.messages)) { + onDone('Fork is not available inside a forked worker. Complete your task directly using your tools.', { display: 'system' }) + return null + } + + const directive = args.trim() + if (!directive) { + onDone('Usage: /fork \nExample: /fork Fix the null check in validate.ts', { display: 'system' }) + return null + } + + // Find the last assistant message to fork from + const lastAssistantMessage = [...context.messages].reverse().find( + m => m.type === 'assistant' + ) as any // Type assertion to avoid complex type import + + if (!lastAssistantMessage) { + onDone('Cannot fork: no assistant response in conversation history.', { display: 'system' }) + return null + } + + try { + // Reuse AgentTool logic for fork path. + // Omitting subagent_type triggers implicit fork. + const input = { + prompt: directive, + run_in_background: true, // fork always runs async + description: `Fork: ${directive.slice(0, 30)}${directive.length > 30 ? '...' : ''}`, + } + + // Call AgentTool with proper parameters: + // - input: the agent parameters (no subagent_type => fork path) + // - toolUseContext: the current context (ToolUseContext) + // - canUseTool: permission-check function from context + // - assistantMessage: the last assistant message to fork from + AgentTool.call( + input, + context, + context.canUseTool, + lastAssistantMessage + ).catch(error => { + logForDebugging(`Fork subagent async error: ${error}`, { level: 'error' }) + }) + + // Notify user that fork has been started + onDone(`Forked subagent started with directive: "${directive}"`, { display: 'system' }) + return null + } catch (error) { + // Catches synchronous setup errors only + logForDebugging(`Fork command setup error: ${error}`, { level: 'error' }) + onDone(`Fork failed: ${error instanceof Error ? error.message : String(error)}`, { display: 'system' }) + return null + } +} diff --git a/src/commands/fork/index.ts b/src/commands/fork/index.ts index 29ae6094c..a4b701411 100644 --- a/src/commands/fork/index.ts +++ b/src/commands/fork/index.ts @@ -1,3 +1,11 @@ -// Auto-generated stub — replace with real implementation -const _default: Record = {}; -export default _default; +import type { Command } from '../../commands.js' + +const fork = { + type: 'local-jsx', + name: 'fork', + description: 'Fork the current session into a new sub-agent', + argumentHint: '', + load: () => import('./fork.js'), +} satisfies Command + +export default fork