feat(agents): add isMainThread flag to agent definition for full tool access

This commit is contained in:
xixingde 2026-04-10 15:54:42 +08:00
parent 47b2db23df
commit 557b873a79
3 changed files with 16 additions and 5 deletions

View File

@ -235,5 +235,8 @@ export const STRICT_PLAN_AGENT: BuiltInAgentDefinition = {
baseDir: 'built-in', baseDir: 'built-in',
model: 'inherit', model: 'inherit',
omitClaudeMd: false, omitClaudeMd: false,
// 通过斜杠命令从主线程启动时,使 resolveAgentTools 跳过 filterToolsForAgent
// 从而保留主线程完整工具集(包括 Agent 工具)。
isMainThread: true,
getSystemPrompt: () => getStrictPlanSystemPrompt(), getSystemPrompt: () => getStrictPlanSystemPrompt(),
} }

View File

@ -122,7 +122,7 @@ export function filterToolsForAgent({
export function resolveAgentTools( export function resolveAgentTools(
agentDefinition: Pick< agentDefinition: Pick<
AgentDefinition, AgentDefinition,
'tools' | 'disallowedTools' | 'source' | 'permissionMode' 'tools' | 'disallowedTools' | 'source' | 'permissionMode' | 'isMainThread'
>, >,
availableTools: Tools, availableTools: Tools,
isAsync = false, isAsync = false,
@ -133,11 +133,15 @@ export function resolveAgentTools(
disallowedTools, disallowedTools,
source, source,
permissionMode, permissionMode,
isMainThread: agentIsMainThread,
} = agentDefinition } = agentDefinition
// When isMainThread is true, skip filterToolsForAgent entirely — the main // Allow the agent definition itself to declare isMainThread=true,
// thread's tool pool is already properly assembled by useMergedTools(), so // which takes precedence over the isMainThread parameter.
const effectiveIsMainThread = agentIsMainThread ?? isMainThread
// When effectiveIsMainThread is true, skip filterToolsForAgent entirely — the
// main thread's tool pool is already properly assembled by useMergedTools(), so
// the sub-agent disallow lists shouldn't apply. // the sub-agent disallow lists shouldn't apply.
const filteredAvailableTools = isMainThread const filteredAvailableTools = effectiveIsMainThread
? availableTools ? availableTools
: filterToolsForAgent({ : filterToolsForAgent({
tools: availableTools, tools: availableTools,
@ -195,7 +199,7 @@ export function resolveAgentTools(
} }
// For sub-agents, Agent is excluded by filterToolsForAgent — mark the spec // For sub-agents, Agent is excluded by filterToolsForAgent — mark the spec
// valid for allowedAgentTypes tracking but skip tool resolution. // valid for allowedAgentTypes tracking but skip tool resolution.
if (!isMainThread) { if (!effectiveIsMainThread) {
validTools.push(toolSpec) validTools.push(toolSpec)
continue continue
} }

View File

@ -130,6 +130,10 @@ export type BaseAgentDefinition = {
* full CLAUDE.md and interprets their output. Saves ~5-15 Gtok/week across * full CLAUDE.md and interprets their output. Saves ~5-15 Gtok/week across
* 34M+ Explore spawns. Kill-switch: tengu_slim_subagent_claudemd. */ * 34M+ Explore spawns. Kill-switch: tengu_slim_subagent_claudemd. */
omitClaudeMd?: boolean omitClaudeMd?: boolean
/** When true, resolveAgentTools skips filterToolsForAgent so the agent
* receives the full main-thread tool pool (including Agent tool).
* Use for agents launched directly via slash command from the main thread. */
isMainThread?: boolean
} }
// Built-in agents - dynamic prompts only, no static systemPrompt field // Built-in agents - dynamic prompts only, no static systemPrompt field