Skip to content

Commit ff77d85

Browse files
committed
Add explicit case to fallback to commander-lite if commander doesn't work
1 parent 92a5663 commit ff77d85

File tree

2 files changed

+81
-2
lines changed

2 files changed

+81
-2
lines changed

packages/agent-runtime/src/tools/handlers/tool/spawn-agent-utils.ts

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,70 @@ export function getMatchingSpawn(
159159
return null
160160
}
161161

162+
/**
163+
* Synchronously transforms spawn_agents input to use 'commander-lite' instead of 'commander'
164+
* when the parent agent doesn't have access to 'commander' but does have access to 'commander-lite'.
165+
* This should be called BEFORE the tool call is streamed to the UI.
166+
*/
167+
export function transformSpawnAgentsInput(
168+
input: Record<string, unknown>,
169+
spawnableAgents: AgentTemplateType[],
170+
): Record<string, unknown> {
171+
const agents = input.agents
172+
if (!Array.isArray(agents)) {
173+
return input
174+
}
175+
176+
let hasTransformation = false
177+
const transformedAgents = agents.map((agent) => {
178+
if (typeof agent !== 'object' || agent === null) {
179+
return agent
180+
}
181+
182+
const agentEntry = agent as Record<string, unknown>
183+
const agentTypeStr = agentEntry.agent_type
184+
if (typeof agentTypeStr !== 'string') {
185+
return agent
186+
}
187+
188+
// Check if this is 'commander'
189+
const { agentId } = parseAgentId(agentTypeStr)
190+
if (agentId !== 'commander') {
191+
return agent
192+
}
193+
194+
// Check if 'commander' is available in spawnableAgents
195+
const commanderType = getMatchingSpawn(spawnableAgents, agentTypeStr)
196+
if (commanderType) {
197+
// Commander is available, no transformation needed
198+
return agent
199+
}
200+
201+
// Check if 'commander-lite' is available as a fallback
202+
const commanderLiteType = getMatchingSpawn(spawnableAgents, 'commander-lite')
203+
if (!commanderLiteType) {
204+
// Neither available, let validation handle the error
205+
return agent
206+
}
207+
208+
// Transform commander -> commander-lite
209+
hasTransformation = true
210+
return {
211+
...agentEntry,
212+
agent_type: commanderLiteType,
213+
}
214+
})
215+
216+
if (!hasTransformation) {
217+
return input
218+
}
219+
220+
return {
221+
...input,
222+
agents: transformedAgents,
223+
}
224+
}
225+
162226
/**
163227
* Validates agent template and permissions
164228
*/

packages/agent-runtime/src/tools/tool-executor.ts

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { MCP_TOOL_SEPARATOR } from '../mcp-constants'
77
import { getMCPToolData } from '../mcp'
88
import { getAgentShortName } from '../templates/prompts'
99
import { codebuffToolHandlers } from './handlers/list'
10+
import { transformSpawnAgentsInput } from './handlers/tool/spawn-agent-utils'
1011
import { ensureZodSchema } from './prompts'
1112

1213
import type { AgentTemplateType } from '@codebuff/common/types/session-state'
@@ -187,12 +188,19 @@ export function executeToolCall<T extends ToolName>(
187188
return previousToolCallFinished
188189
}
189190

191+
// Transform spawn_agents input to use commander-lite fallback before streaming
192+
// This ensures the UI shows the correct agent type from the start
193+
const transformedInput =
194+
toolName === 'spawn_agents'
195+
? transformSpawnAgentsInput(input, agentTemplate.spawnableAgents)
196+
: input
197+
190198
// Only emit tool_call event after permission check passes
191199
onResponseChunk({
192200
type: 'tool_call',
193201
toolCallId,
194202
toolName,
195-
input,
203+
input: transformedInput,
196204
agentId: agentState.agentId,
197205
parentAgentId: agentState.parentId,
198206
includeToolCall: !excludeToolFromMessageHistory,
@@ -204,8 +212,16 @@ export function executeToolCall<T extends ToolName>(
204212
const handler = codebuffToolHandlers[
205213
toolName
206214
] as unknown as CodebuffToolHandlerFunction<T>
215+
216+
// Use transformed input for spawn_agents so the handler receives the correct agent types
217+
const finalToolCall =
218+
toolName === 'spawn_agents'
219+
? { ...toolCall, input: transformedInput }
220+
: toolCall
221+
207222
const toolResultPromise = handler({
208223
...params,
224+
toolCall: finalToolCall,
209225
previousToolCallFinished,
210226
writeToClient: onResponseChunk,
211227
requestClientToolCall: (async (
@@ -222,7 +238,6 @@ export function executeToolCall<T extends ToolName>(
222238
})
223239
return clientToolResult.output as CodebuffToolOutput<T>
224240
}) as any,
225-
toolCall,
226241
})
227242

228243
return toolResultPromise.then(async ({ output, creditsUsed }) => {

0 commit comments

Comments
 (0)