Skip to content

Commit 3f4ceda

Browse files
committed
cli: collapse code reviewers within code-reviewer-multi-prompt
1 parent 4fc5d7e commit 3f4ceda

File tree

3 files changed

+86
-10
lines changed

3 files changed

+86
-10
lines changed

cli/src/utils/constants.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,40 @@ export const shouldCollapseByDefault = (agentType: string): boolean => {
3232
)
3333
}
3434

35+
/**
36+
* Rules for collapsing child agents when spawned by specific parent agents.
37+
* Key: parent agent type pattern, Value: array of child agent type patterns to collapse
38+
*/
39+
export const PARENT_CHILD_COLLAPSE_RULES: Record<string, string[]> = {
40+
'code-reviewer-multi-prompt': ['code-reviewer'],
41+
}
42+
43+
/**
44+
* Check if a child agent should be collapsed when spawned by a specific parent
45+
*/
46+
export const shouldCollapseForParent = (
47+
childAgentType: string,
48+
parentAgentType: string | undefined,
49+
): boolean => {
50+
if (!parentAgentType) {
51+
return false
52+
}
53+
54+
for (const [parentPattern, childPatterns] of Object.entries(
55+
PARENT_CHILD_COLLAPSE_RULES,
56+
)) {
57+
if (parentAgentType.includes(parentPattern)) {
58+
for (const childPattern of childPatterns) {
59+
if (childAgentType.includes(childPattern)) {
60+
return true
61+
}
62+
}
63+
}
64+
}
65+
66+
return false
67+
}
68+
3569
// Agent IDs that should render as simple text instead of full agent boxes
3670
export const SIMPLE_TEXT_AGENT_IDS = [
3771
'best-of-n-selector',

cli/src/utils/message-block-helpers.ts

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { isEqual } from 'lodash'
22

33
import { formatToolOutput } from './codebuff-client'
4-
import { shouldCollapseByDefault } from './constants'
4+
import { shouldCollapseByDefault, shouldCollapseForParent } from './constants'
55

66
import type {
77
ContentBlock,
@@ -250,6 +250,30 @@ export const appendInterruptionNotice = (
250250
return [...blocks, interruptionNotice]
251251
}
252252

253+
/**
254+
* Recursively finds an agent block by ID and returns its agent type.
255+
* Returns undefined if not found.
256+
*/
257+
export const findAgentTypeById = (
258+
blocks: ContentBlock[],
259+
agentId: string,
260+
): string | undefined => {
261+
for (const block of blocks) {
262+
if (block.type === 'agent') {
263+
if (block.agentId === agentId) {
264+
return block.agentType
265+
}
266+
if (block.blocks) {
267+
const found = findAgentTypeById(block.blocks, agentId)
268+
if (found) {
269+
return found
270+
}
271+
}
272+
}
273+
}
274+
return undefined
275+
}
276+
253277
/**
254278
* Options for creating an agent content block.
255279
*/
@@ -262,6 +286,8 @@ export interface CreateAgentBlockOptions {
262286
spawnToolCallId?: string
263287
/** The index within the spawn_agents call */
264288
spawnIndex?: number
289+
/** The agent type of the parent agent that spawned this one */
290+
parentAgentType?: string
265291
}
266292

267293
/**
@@ -270,7 +296,10 @@ export interface CreateAgentBlockOptions {
270296
export const createAgentBlock = (
271297
options: CreateAgentBlockOptions,
272298
): AgentContentBlock => {
273-
const { agentId, agentType, prompt, params, spawnToolCallId, spawnIndex } = options
299+
const { agentId, agentType, prompt, params, spawnToolCallId, spawnIndex, parentAgentType } = options
300+
const shouldCollapse =
301+
shouldCollapseByDefault(agentType || '') ||
302+
shouldCollapseForParent(agentType || '', parentAgentType)
274303
return {
275304
type: 'agent',
276305
agentId,
@@ -283,7 +312,7 @@ export const createAgentBlock = (
283312
...(params && { params }),
284313
...(spawnToolCallId && { spawnToolCallId }),
285314
...(spawnIndex !== undefined && { spawnIndex }),
286-
...(shouldCollapseByDefault(agentType || '') && { isCollapsed: true }),
315+
...(shouldCollapse && { isCollapsed: true }),
287316
}
288317
}
289318

cli/src/utils/sdk-event-handlers.ts

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
createAgentBlock,
1111
extractPlanFromBuffer,
1212
extractSpawnAgentResultContent,
13+
findAgentTypeById,
1314
insertPlanBlock,
1415
nestBlockUnderParent,
1516
transformAskUserBlocks,
@@ -216,14 +217,20 @@ const handleSubagentStart = (
216217
'Creating new agent block (no spawn_agents match)',
217218
)
218219

219-
const newAgentBlock = createAgentBlock({
220-
agentId: event.agentId,
221-
agentType: event.agentType || '',
222-
prompt: event.prompt,
223-
params: event.params,
224-
})
225-
226220
state.message.updater.updateAiMessageBlocks((blocks) => {
221+
// Look up the parent agent's type if there's a parent agent ID
222+
const parentAgentType = event.parentAgentId
223+
? findAgentTypeById(blocks, event.parentAgentId)
224+
: undefined
225+
226+
const newAgentBlock = createAgentBlock({
227+
agentId: event.agentId,
228+
agentType: event.agentType || '',
229+
prompt: event.prompt,
230+
params: event.params,
231+
parentAgentType,
232+
})
233+
227234
if (event.parentAgentId) {
228235
const { blocks: nestedBlocks, parentFound } = nestBlockUnderParent(
229236
blocks,
@@ -273,6 +280,11 @@ const handleSpawnAgentsToolCall = (
273280
})
274281

275282
state.message.updater.updateAiMessageBlocks((blocks) => {
283+
// Look up the parent agent's type if there's a parent agent ID
284+
const parentAgentType = event.agentId
285+
? findAgentTypeById(blocks, event.agentId)
286+
: undefined
287+
276288
const newAgentBlocks: ContentBlock[] = agents
277289
.map((agent: any, originalIndex: number) => ({ agent, originalIndex }))
278290
.filter(({ agent }) => !shouldHideAgent(agent.agent_type || ''))
@@ -283,6 +295,7 @@ const handleSpawnAgentsToolCall = (
283295
prompt: agent.prompt,
284296
spawnToolCallId: event.toolCallId,
285297
spawnIndex: originalIndex,
298+
parentAgentType,
286299
}),
287300
)
288301

0 commit comments

Comments
 (0)