mirror of
https://github.com/openobserve/openobserve.git
synced 2026-11-04 08:09:27 +00:00
feat(o2ai): render CLI tool_result summary and command (#11449)
## Summary - Render `summary.return_code`, `stdout_lines`, `stderr_lines`, and `truncated` in the chat tool-call details panel so CLI tool results show parsed info like MCP tools do. - Whitelist `command` in `getToolCallDisplayData` and add a "Command" row with a copy button so the actual CLI command the agent ran is visible. ## Context The o2-ai server already emits a uniform `tool_result` shape for CLI tools (see openobserve/o2-ai#96 — wait for that to merge): ```json { "type": "tool_result", "tool": "cli_kubectl", "success": true, "message": "Exited 0 (12 lines stdout)", "summary": { "return_code": 0, "stdout_lines": 12, "stderr_lines": 0 }, "call_args": { "command": "get pods -n default" }, "call_id": "call-uuid-v7" } ``` `ContentBlock.summary` was already being captured from the event — the template just had no conditionals for the CLI fields. This PR adds them. ## What this does NOT do - Does not show raw `stdout`/`stderr` text (server currently only sends line counts). If we want inline output, that's a separate backend change. - Does not add a custom header format for CLI — the default `block.message` ("Exited 0 (12 lines stdout)") renders fine as plain text. ## Test plan - [x] `npm run type-check` — clean - [ ] Manually verify in dev chat that a CLI tool call (`kubectl get pods`) shows the Exit code / Stdout / Stderr rows and the Command row with copy button - [ ] MCP tools (SearchSQL, StreamList) still render the existing Results / Duration rows unchanged 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
abac6d95db
commit
f897aa2cb2
@@ -402,6 +402,23 @@
|
||||
<span class="detail-label">Duration</span>
|
||||
<span class="detail-value">{{ block.summary.took }}ms</span>
|
||||
</div>
|
||||
<!-- CLI tool summary (return_code / stdout_lines / stderr_lines / truncated) -->
|
||||
<div v-if="block.summary.return_code !== undefined" class="detail-item">
|
||||
<span class="detail-label">Exit code</span>
|
||||
<code class="detail-value">{{ block.summary.return_code }}</code>
|
||||
</div>
|
||||
<div v-if="block.summary.stdout_lines !== undefined" class="detail-item">
|
||||
<span class="detail-label">Stdout</span>
|
||||
<span class="detail-value">{{ block.summary.stdout_lines }} lines</span>
|
||||
</div>
|
||||
<div v-if="block.summary.stderr_lines" class="detail-item">
|
||||
<span class="detail-label">Stderr</span>
|
||||
<span class="detail-value">{{ block.summary.stderr_lines }} lines</span>
|
||||
</div>
|
||||
<div v-if="block.summary.truncated" class="detail-item">
|
||||
<span class="detail-label">Output</span>
|
||||
<span class="detail-value">truncated</span>
|
||||
</div>
|
||||
</template>
|
||||
<!-- Existing context details -->
|
||||
<div v-if="getToolCallDisplayData(block.context)?.query" class="detail-item">
|
||||
@@ -464,6 +481,22 @@
|
||||
</div>
|
||||
<code class="detail-value query-value">{{ getToolCallDisplayData(block.context)?.vrl }}</code>
|
||||
</div>
|
||||
<div v-if="getToolCallDisplayData(block.context)?.command" class="detail-item">
|
||||
<div class="detail-header">
|
||||
<span class="detail-label">Command</span>
|
||||
<q-btn
|
||||
flat
|
||||
dense
|
||||
size="xs"
|
||||
icon="content_copy"
|
||||
class="copy-btn"
|
||||
@click.stop="copyToClipboard(getToolCallDisplayData(block.context)?.command)"
|
||||
>
|
||||
<q-tooltip>Copy command</q-tooltip>
|
||||
</q-btn>
|
||||
</div>
|
||||
<code class="detail-value query-value">{{ getToolCallDisplayData(block.context)?.command }}</code>
|
||||
</div>
|
||||
<!-- Tool response: SearchSQL hits -->
|
||||
<template v-if="block.response && block.response.hits">
|
||||
<div class="detail-item">
|
||||
@@ -4532,6 +4565,9 @@ export default defineComponent({
|
||||
if (context.stream_name) data.stream = context.stream_name;
|
||||
if (context.type) data.type = context.type;
|
||||
|
||||
// CLI tools: surface the command string
|
||||
if (context.command) data.command = context.command;
|
||||
|
||||
return Object.keys(data).length > 0 ? data : null;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user