* Get the tool name, input, and search/read info from a message if it's a collapsible tool use. * Returns null if the message is not a collapsible tool use.
( msg: RenderableMessage, tools: Tools, )
| 308 | * Returns null if the message is not a collapsible tool use. |
| 309 | */ |
| 310 | function getCollapsibleToolInfo( |
| 311 | msg: RenderableMessage, |
| 312 | tools: Tools, |
| 313 | ): { |
| 314 | name: string |
| 315 | input: unknown |
| 316 | isSearch: boolean |
| 317 | isRead: boolean |
| 318 | isList: boolean |
| 319 | isREPL: boolean |
| 320 | isMemoryWrite: boolean |
| 321 | isAbsorbedSilently: boolean |
| 322 | mcpServerName?: string |
| 323 | isBash?: boolean |
| 324 | } | null { |
| 325 | if (msg.type === 'assistant') { |
| 326 | const content = getFirstContentItem(msg.message?.content) |
| 327 | if (!content) return null |
| 328 | const info = getSearchOrReadFromContent(content as { type: string; name?: string; input?: unknown }, tools) |
| 329 | if (info && content.type === 'tool_use') { |
| 330 | const toolUse = content as { type: 'tool_use'; name: string; input: unknown } |
| 331 | return { name: toolUse.name, input: toolUse.input, ...info } |
| 332 | } |
| 333 | } |
| 334 | if (msg.type === 'grouped_tool_use') { |
| 335 | // For grouped tool uses, check the first message's input |
| 336 | const firstContent = getFirstContentItem(msg.messages[0]?.message?.content) |
| 337 | const firstToolUse = firstContent as { type: string; input?: unknown } | undefined |
| 338 | const info = getSearchOrReadFromContent( |
| 339 | firstToolUse |
| 340 | ? { type: 'tool_use', name: msg.toolName, input: firstToolUse.input } |
| 341 | : undefined, |
| 342 | tools, |
| 343 | ) |
| 344 | if (info && firstContent && firstContent.type === 'tool_use') { |
| 345 | return { name: msg.toolName, input: firstToolUse?.input, ...info } |
| 346 | } |
| 347 | } |
| 348 | return null |
| 349 | } |
| 350 | |
| 351 | /** |
| 352 | * Check if a message is assistant text that should break a group. |
no test coverage detected