better result display

This commit is contained in:
Andrew Pareles 2025-05-22 17:22:07 -07:00
parent 31aa31a18b
commit 09f5f1fad1
4 changed files with 31 additions and 27 deletions

View file

@ -713,18 +713,7 @@ class ChatThreadService extends Disposable implements IChatThreadService {
}
// For MCP tools, handle the result based on its type
else {
const toolResult_ = toolResult as RawMCPToolCall
if (toolResult_.event === 'text') {
toolResultStr = toolResult_.text
} else if (toolResult_.event === 'image') {
toolResultStr = `[Image: ${toolResult_.image.mimeType}]`
} else if (toolResult_.event === 'audio') {
toolResultStr = `[Audio content]`
} else if (toolResult_.event === 'resource') {
toolResultStr = `[Resource content]`
} else {
toolResultStr = JSON.stringify(toolResult)
}
toolResultStr = this._mcpService.stringifyResult(toolResult as RawMCPToolCall)
}
} catch (error) {
const errorMessage = this.toolErrMsgs.errWhenStringifying(error)

View file

@ -1428,7 +1428,9 @@ const getTitle = (toolMessage: Pick<ChatMessage & { role: 'tool' }, 'name' | 'ty
: t.type === 'invalid_params' ? 'Call'
: t.type === 'tool_error' ? 'Call'
: 'Call'
const title = `${descriptor} MCP`
const title = `${descriptor} ${toolMessage.mcpServerName || 'MCP'}`
if (t.type === 'running_now' || t.type === 'tool_request')
return loadingTitleWrapper(title)
return title
@ -1852,7 +1854,7 @@ const CommandTool = ({ toolMessage, type, threadId }: { threadId: string } & ({
type WrapperProps<T extends ToolName> = { toolMessage: Exclude<ToolMessage<T>, { type: 'invalid_params' }>, messageIdx: number, threadId: string }
const MCPToolWrapper = ({ toolMessage }: WrapperProps<string>) => {
const accessor = useAccessor()
const commandService = accessor.get('ICommandService')
const mcpService = accessor.get('IMCPService')
const title = getTitle(toolMessage)
const desc1 = toolMessage.name
@ -1870,14 +1872,11 @@ const MCPToolWrapper = ({ toolMessage }: WrapperProps<string>) => {
if (toolMessage.type === 'success' || toolMessage.type === 'tool_request') {
const { result } = toolMessage
const resultStr = result ? mcpService.stringifyResult(result) : 'null'
componentParams.children = <ToolChildrenWrapper>
<SmallProseWrapper>
<ChatMarkdownRender
string={`
\`\`\`json\n${JSON.stringify(result, null, 2)}\n\`\`\`
## Inputs:
\`\`\`json\n${JSON.stringify(params, null, 2)}\n\`\`\`
`}
string={`\`\`\`json\n${resultStr}\n\`\`\``}
chatMessageLocation={undefined}
isApplyEnabled={false}
isLinkDetectionEnabled={true}

View file

@ -346,20 +346,20 @@ export class TerminalToolService extends Disposable implements ITerminalToolServ
await Promise.any([waitUntilDone, waitUntilInterrupt])
.finally(() => disposables.forEach(d => d.dispose()))
// read result if timed out, since we didn't get it (could clean this code up but it's ok)
if (resolveReason?.type === 'timeout') {
const terminalId = isPersistent ? params.persistentTerminalId : params.terminalId
result = await this.readTerminal(terminalId)
}
if (!isPersistent) {
interrupt()
}
if (!resolveReason) throw new Error('Unexpected internal error: Promise.any should have resolved with a reason.')
// read result if timed out, since we didn't get it (could clean this code up but it's ok)
if (resolveReason.type === 'timeout') {
const terminalId = isPersistent ? params.persistentTerminalId : params.terminalId
result = await this.readTerminal(terminalId)
}
if (!isPersistent) result = `$ ${command}\n${result}`
result = removeAnsiEscapeCodes(result)
// trim

View file

@ -36,6 +36,7 @@ export interface IMCPService {
getMCPTools(): InternalToolInfo[] | undefined;
callMCPTool(toolData: MCPToolCallParams): Promise<{ result: RawMCPToolCall }>;
stringifyResult(result: RawMCPToolCall): string
}
export const IMCPService = createDecorator<IMCPService>('mcpConfigService');
@ -286,6 +287,21 @@ class MCPService extends Disposable implements IMCPService {
})
}
stringifyResult(result: RawMCPToolCall): string {
let toolResultStr: string
if (result.event === 'text') {
toolResultStr = result.text
} else if (result.event === 'image') {
toolResultStr = `[Image: ${result.image.mimeType}]`
} else if (result.event === 'audio') {
toolResultStr = `[Audio content]`
} else if (result.event === 'resource') {
toolResultStr = `[Resource content]`
} else {
toolResultStr = JSON.stringify(result)
}
return toolResultStr
}
// toggle MCP server and update isOn in void settings
public async toggleServerIsOn(serverName: string, isOn: boolean): Promise<void> {