Skip to content

Commit 001614b

Browse files
authored
expose parent_tool_use_id for subagents (agentclientprotocol#341)
I'm not sure yet how a good protocol for subagents could look like, so instead of opening an RFD, I opted to expose Claude's `parent_tool_use_id` in `_meta.claudeCode.parentToolUseId`. This will allow Tidewave to render tools from subagents in a better way.
1 parent 218661f commit 001614b

1 file changed

Lines changed: 47 additions & 15 deletions

File tree

src/acp-agent.ts

Lines changed: 47 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -640,7 +640,10 @@ export class ClaudeAcpAgent implements Agent {
640640
this.toolUseCache,
641641
this.client,
642642
this.logger,
643-
{ clientCapabilities: this.clientCapabilities },
643+
{
644+
clientCapabilities: this.clientCapabilities,
645+
parentToolUseId: message.parent_tool_use_id,
646+
},
644647
)) {
645648
await this.client.sessionUpdate(notification);
646649
}
@@ -1393,23 +1396,34 @@ export function toAcpNotifications(
13931396
toolUseCache: ToolUseCache,
13941397
client: AgentSideConnection,
13951398
logger: Logger,
1396-
options?: { registerHooks?: boolean; clientCapabilities?: ClientCapabilities },
1399+
options?: {
1400+
registerHooks?: boolean;
1401+
clientCapabilities?: ClientCapabilities;
1402+
parentToolUseId?: string | null;
1403+
},
13971404
): SessionNotification[] {
13981405
const registerHooks = options?.registerHooks !== false;
13991406
const supportsTerminalOutput = options?.clientCapabilities?._meta?.["terminal_output"] === true;
14001407
if (typeof content === "string") {
1401-
return [
1402-
{
1403-
sessionId,
1404-
update: {
1405-
sessionUpdate: role === "assistant" ? "agent_message_chunk" : "user_message_chunk",
1406-
content: {
1407-
type: "text",
1408-
text: content,
1409-
},
1410-
},
1408+
const update: SessionNotification["update"] = {
1409+
sessionUpdate: role === "assistant" ? "agent_message_chunk" : "user_message_chunk",
1410+
content: {
1411+
type: "text",
1412+
text: content,
14111413
},
1412-
];
1414+
};
1415+
1416+
if (options?.parentToolUseId) {
1417+
update._meta = {
1418+
...update._meta,
1419+
claudeCode: {
1420+
...(update._meta?.claudeCode || {}),
1421+
parentToolUseId: options.parentToolUseId,
1422+
},
1423+
};
1424+
}
1425+
1426+
return [{ sessionId, update }];
14131427
}
14141428

14151429
const output = [];
@@ -1573,6 +1587,9 @@ export function toAcpNotifications(
15731587
update: {
15741588
_meta: {
15751589
terminal_output: toolMeta.terminal_output,
1590+
...(options?.parentToolUseId
1591+
? { claudeCode: { parentToolUseId: options.parentToolUseId } }
1592+
: {}),
15761593
},
15771594
toolCallId: chunk.tool_use_id,
15781595
sessionUpdate: "tool_call_update" as const,
@@ -1613,6 +1630,15 @@ export function toAcpNotifications(
16131630
break;
16141631
}
16151632
if (update) {
1633+
if (options?.parentToolUseId) {
1634+
update._meta = {
1635+
...update._meta,
1636+
claudeCode: {
1637+
...(update._meta?.claudeCode || {}),
1638+
parentToolUseId: options.parentToolUseId,
1639+
},
1640+
};
1641+
}
16161642
output.push({ sessionId, update });
16171643
}
16181644
}
@@ -1638,7 +1664,10 @@ export function streamEventToAcpNotifications(
16381664
toolUseCache,
16391665
client,
16401666
logger,
1641-
{ clientCapabilities: options?.clientCapabilities },
1667+
{
1668+
clientCapabilities: options?.clientCapabilities,
1669+
parentToolUseId: message.parent_tool_use_id,
1670+
},
16421671
);
16431672
case "content_block_delta":
16441673
return toAcpNotifications(
@@ -1648,7 +1677,10 @@ export function streamEventToAcpNotifications(
16481677
toolUseCache,
16491678
client,
16501679
logger,
1651-
{ clientCapabilities: options?.clientCapabilities },
1680+
{
1681+
clientCapabilities: options?.clientCapabilities,
1682+
parentToolUseId: message.parent_tool_use_id,
1683+
},
16521684
);
16531685
// No content
16541686
case "message_start":

0 commit comments

Comments
 (0)