feat(agent-presets): enable background Codex and Claude Code subagent tasks

This commit is contained in:
pku-xht
2026-08-12 17:07:34 +08:00
parent b423ed15d7
commit 28fcda2751
35 changed files with 318 additions and 102 deletions

View File

@@ -207,7 +207,7 @@
config:
provider: codex
toolName: subagent_codex
enableRunInBackground: false
backgroundMode: one-shot
maxDepth: provider-managed
- id: tool-subagent-claude-code
@@ -216,7 +216,7 @@
config:
provider: claude-code
toolName: subagent_claude_code
enableRunInBackground: false
backgroundMode: one-shot
maxDepth: provider-managed
- id: workflow-workerthread

View File

@@ -194,7 +194,7 @@
config:
provider: codex
toolName: subagent_codex
enableRunInBackground: false
backgroundMode: one-shot
maxDepth: provider-managed
- id: tool-subagent-claude-code
@@ -203,7 +203,7 @@
config:
provider: claude-code
toolName: subagent_claude_code
enableRunInBackground: false
backgroundMode: one-shot
maxDepth: provider-managed
- id: workflow-workerthread

View File

@@ -134,7 +134,7 @@ Copy these disabled templates from a shipped full preset and remove `disabled` o
config:
provider: codex
toolName: subagent_codex
enableRunInBackground: false
backgroundMode: one-shot
maxDepth: provider-managed
- id: tool-subagent-claude-code
@@ -143,11 +143,11 @@ Copy these disabled templates from a shipped full preset and remove `disabled` o
config:
provider: claude-code
toolName: subagent_claude_code
enableRunInBackground: false
backgroundMode: one-shot
maxDepth: provider-managed
```
The two rows are independent. Leaving both disabled preserves the copied preset, enabling one exposes only that product tool, and enabling both exposes both. The host must provide `codex` or `claude` on `PATH`; the preset does not install, authenticate, select a model for, or probe either product.
The two rows are independent. Leaving both disabled preserves the copied preset, enabling one exposes only that product tool, and enabling both exposes both. `backgroundMode: one-shot` keeps omitted or `false` calls in the foreground and lets explicit `run_in_background: true` return a generic Task id. Full presets already carry `tool-tasks`, while the host carries the task registry; retain both when making a custom composition so `task_output`, `task_list`, `task_kill`, cancellation, and completion notices stay available. The host must provide `codex` or `claude` on `PATH`; the preset does not install, authenticate, select a model for, or probe either product.
## What not to move into a preset

View File

@@ -206,7 +206,7 @@
config:
provider: codex
toolName: subagent_codex
enableRunInBackground: false
backgroundMode: one-shot
maxDepth: provider-managed
- id: tool-subagent-claude-code
@@ -215,7 +215,7 @@
config:
provider: claude-code
toolName: subagent_claude_code
enableRunInBackground: false
backgroundMode: one-shot
maxDepth: provider-managed
- id: workflow-workerthread

View File

@@ -122,6 +122,16 @@ async function bootWeb(settingsFile: string, extra: PatchOptions[] = []): Promis
const toolNames = (ctx: Context, agent?: Agent): string[] =>
ctx.tools.schemas(agent).map(schema => schema.name).sort()
function toolParameterNames(ctx: Context, agent: Agent, toolName: string): string[] {
const schema = ctx.tools.schemas(agent).find(tool => tool.name === toolName)
if (schema === undefined) throw new Error(`missing tool schema ${toolName}`)
const properties = schema.parameters.properties
if (typeof properties !== 'object' || properties === null || Array.isArray(properties)) {
throw new Error(`${toolName} has invalid parameter properties`)
}
return Object.keys(properties).sort()
}
function enablePresetTool(composition: string, id: string): string {
const row = ` - id: ${id}\n`
const start = composition.indexOf(row)
@@ -475,6 +485,12 @@ describe('product subagent rows in user presets', () => {
const tools = toolNames(productCtx, handle.agent)
expect(tools.filter(name => name === 'subagent_codex' || name === 'subagent_claude_code'))
.toEqual(productTools)
expect(tools).toEqual(expect.arrayContaining(['task_kill', 'task_list', 'task_output']))
for (const productTool of productTools) {
expect(toolParameterNames(productCtx, handle.agent, productTool)).toEqual([
'description', 'prompt', 'run_in_background',
])
}
} finally {
await handle.dispose()
}