Skip to content

Commit e400008

Browse files
committed
fix: show tool calls
1 parent 80c4fa7 commit e400008

File tree

4 files changed

+79
-26
lines changed

4 files changed

+79
-26
lines changed

cli/src/chat.tsx

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import {
2626
getToolDisplayInfo,
2727
formatToolOutput,
2828
} from './codebuff-client'
29+
import type { ToolName } from '@codebuff/sdk'
2930
import { logger } from './logger'
3031
import { ShimmerText } from './shimmer-text'
3132

@@ -854,7 +855,7 @@ export const App = ({ initialPrompt }: { initialPrompt?: string } = {}) => {
854855
setCanProcessQueue(false)
855856
isChainInProgressRef.current = true
856857

857-
const activeTools = new Map<string, string>()
858+
const activeTools = new Map<string, { agentId: string; toolName: ToolName }>()
858859
let hasReceivedContent = false
859860
let actualCredits: number | undefined = undefined
860861

@@ -928,15 +929,20 @@ export const App = ({ initialPrompt }: { initialPrompt?: string } = {}) => {
928929
if (event.type === 'tool_call' && event.toolCallId) {
929930
const { toolCallId, toolName, input } = event
930931

932+
const hiddenTools: ToolName[] = ['spawn_agent_inline', 'end_turn']
933+
if (hiddenTools.includes(toolName)) {
934+
return
935+
}
936+
931937
const displayInfo = getToolDisplayInfo(toolName)
932938
const agentId = `agent-${toolCallId}`
933939

934-
activeTools.set(toolCallId, agentId)
940+
activeTools.set(toolCallId, { agentId, toolName })
935941

936942
const agentMessage: ChatMessage = {
937943
id: agentId,
938944
variant: 'agent',
939-
content: `Executing ${toolName}...\n\n\`\`\`json\n${JSON.stringify(input, null, 2)}\n\`\`\``,
945+
content: `\`\`\`json\n${JSON.stringify(input, null, 2)}\n\`\`\``,
940946
timestamp: formatTimestamp(),
941947
parentId: aiMessageId,
942948
agent: {
@@ -950,19 +956,33 @@ export const App = ({ initialPrompt }: { initialPrompt?: string } = {}) => {
950956
setStreamingAgents((prev) => new Set(prev).add(agentId))
951957
setCollapsedAgents((prev) => new Set(prev).add(agentId))
952958
} else if (event.type === 'tool_result' && event.toolCallId) {
953-
const agentId = activeTools.get(event.toolCallId)
954-
if (!agentId) return
959+
const toolInfo = activeTools.get(event.toolCallId)
960+
if (!toolInfo) return
961+
962+
const { agentId, toolName } = toolInfo
963+
964+
let output: string
965+
if (event.error) {
966+
output = `**Error:** ${typeof event.error === 'string' ? event.error : JSON.stringify(event.error)}`
967+
} else if (toolName === 'run_terminal_command') {
968+
const parsed = event.output?.[0]?.value
969+
if (parsed?.stdout || parsed?.stderr) {
970+
output = (parsed.stdout || '') + (parsed.stderr || '')
971+
} else {
972+
output = formatToolOutput(event.output)
973+
}
974+
} else {
975+
output = formatToolOutput(event.output)
976+
}
955977

956-
const output = event.error
957-
? `**Error:** ${typeof event.error === 'string' ? event.error : JSON.stringify(event.error)}`
958-
: formatToolOutput(event.output)
978+
const codeBlockLang = toolName === 'run_terminal_command' ? '' : 'yaml'
959979

960980
setMessages((prev) =>
961981
prev.map((msg) =>
962982
msg.id === agentId
963983
? {
964984
...msg,
965-
content: `${msg.content}\n\n**Result:**\n\`\`\`\n${output}\n\`\`\``,
985+
content: `${msg.content}\n\n**Result:**\n\`\`\`${codeBlockLang}\n${output}\n\`\`\``,
966986
}
967987
: msg,
968988
),

cli/src/codebuff-client.ts

Lines changed: 48 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -33,35 +33,67 @@ export function getToolDisplayInfo(toolName: string): {
3333
name: string
3434
type: string
3535
} {
36-
const toolNameMap: Record<string, string> = {
37-
write_file: 'File Writer',
38-
str_replace: 'File Editor',
39-
read_files: 'File Reader',
40-
code_search: 'Code Search',
41-
run_terminal_command: 'Terminal',
42-
browser_logs: 'Browser',
43-
run_file_change_hooks: 'File Hooks',
44-
web_search: 'Web Search',
45-
read_docs: 'Doc Reader',
46-
spawn_agents: 'Agent Spawner',
36+
const capitalizeWords = (str: string) => {
37+
return str.replace(/_/g, ' ').replace(/\b\w/g, (l) => l.toUpperCase())
4738
}
4839

4940
return {
50-
name:
51-
toolNameMap[toolName] ||
52-
toolName.replace(/_/g, ' ').replace(/\b\w/g, (l) => l.toUpperCase()),
41+
name: capitalizeWords(toolName),
5342
type: 'tool',
5443
}
5544
}
5645

46+
function toYaml(obj: any, indent = 0): string {
47+
const spaces = ' '.repeat(indent)
48+
49+
if (obj === null || obj === undefined) {
50+
return 'null'
51+
}
52+
53+
if (typeof obj === 'string') {
54+
if (obj.includes('\n')) {
55+
const lines = obj.split('\n')
56+
return '|\n' + lines.map(line => ' '.repeat(indent + 1) + line).join('\n')
57+
}
58+
return obj.includes(':') || obj.includes('#') ? `"${obj}"` : obj
59+
}
60+
61+
if (typeof obj === 'number' || typeof obj === 'boolean') {
62+
return String(obj)
63+
}
64+
65+
if (Array.isArray(obj)) {
66+
if (obj.length === 0) return '[]'
67+
return '\n' + obj.map(item => spaces + '- ' + toYaml(item, indent + 1).trimStart()).join('\n')
68+
}
69+
70+
if (typeof obj === 'object') {
71+
const entries = Object.entries(obj)
72+
if (entries.length === 0) return '{}'
73+
74+
return entries.map(([key, value]) => {
75+
const yamlValue = toYaml(value, indent + 1)
76+
if (typeof value === 'object' && value !== null && !Array.isArray(value) && Object.keys(value).length > 0) {
77+
return `${spaces}${key}:\n${yamlValue}`
78+
}
79+
if (typeof value === 'string' && value.includes('\n')) {
80+
return `${spaces}${key}: ${yamlValue}`
81+
}
82+
return `${spaces}${key}: ${yamlValue}`
83+
}).join('\n')
84+
}
85+
86+
return String(obj)
87+
}
88+
5789
export function formatToolOutput(output: unknown): string {
5890
if (!output) return ''
5991

6092
if (Array.isArray(output)) {
6193
return output
6294
.map((item) => {
6395
if (item.type === 'json') {
64-
return JSON.stringify(item.value, null, 2)
96+
return toYaml(item.value)
6597
}
6698
if (item.type === 'text') {
6799
return item.text || ''
@@ -75,5 +107,5 @@ export function formatToolOutput(output: unknown): string {
75107
return output
76108
}
77109

78-
return JSON.stringify(output, null, 2)
110+
return toYaml(output)
79111
}

sdk/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ export type * from './run'
22
export type * from '../../common/src/types/json'
33
export type * from '../../common/src/types/messages/codebuff-message'
44
export type * from '../../common/src/types/messages/data-content'
5+
export { type ToolName } from '../../common/src/tools/constants'
56
// Agent type exports
67
export type { AgentDefinition } from '../../common/src/templates/initial-agents-dir/types/agent-definition'
78
// Re-export code analysis functionality

sdk/src/run.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ export async function run({
174174
if (insideToolCall && buffer.length > BUFFER_SIZE * 10) {
175175
buffer = buffer.slice(-BUFFER_SIZE * 10)
176176
}
177-
} else if (chunk.type !== 'tool_call') {
177+
} else {
178178
await handleEvent?.(chunk)
179179
}
180180
},

0 commit comments

Comments
 (0)