diff --git a/plugin/dashboard/app/sessions/[sessionId]/page.tsx b/plugin/dashboard/app/sessions/[sessionId]/page.tsx index 84ee3c8..c1be6d9 100644 --- a/plugin/dashboard/app/sessions/[sessionId]/page.tsx +++ b/plugin/dashboard/app/sessions/[sessionId]/page.tsx @@ -144,9 +144,12 @@ export default function InteractionDetailPage({
{turn.tools_used.map((t, ti) => { const input = t.tool_data?.input; + const output = t.tool_data?.output; const hasInput = input && Object.keys(input).length > 0; - if (!hasInput) { + const hasOutput = + typeof output === "string" && output.length > 0; + if (!hasInput && !hasOutput) { return ( -
-                                  {JSON.stringify(input, null, 2)}
-                                
+
+ {hasInput && ( +
+
+ input +
+
+                                        {JSON.stringify(input, null, 2)}
+                                      
+
+ )} + {hasOutput && ( +
+
+ output +
+
+                                        {output}
+                                      
+
+ )} +
); })} diff --git a/plugin/dashboard/lib/session-reader.ts b/plugin/dashboard/lib/session-reader.ts index 76f9e94..a6b31f3 100644 --- a/plugin/dashboard/lib/session-reader.ts +++ b/plugin/dashboard/lib/session-reader.ts @@ -17,6 +17,18 @@ import type { UserActionType, } from "./types"; +// Mirrors _TOOL_DATA_FIELD_MAX_LEN in plugin/src/claude_smart/state.py — we +// truncate to the same length the publisher ships to reflexio so the +// dashboard renders the exact bytes the extractor sees. +const TOOL_DATA_FIELD_MAX_LEN = 256; + +function truncateToolField(value: T): T { + if (typeof value === "string" && value.length > TOOL_DATA_FIELD_MAX_LEN) { + return value.slice(0, TOOL_DATA_FIELD_MAX_LEN) as T; + } + return value; +} + export function stateDir(): string { const override = process.env.CLAUDE_SMART_STATE_DIR; if (override) return override; @@ -30,6 +42,7 @@ type RawRecord = { user_id?: string; tool_name?: string; tool_input?: Record; + tool_output?: string; status?: string; user_action?: UserActionType; user_action_description?: string; @@ -81,8 +94,19 @@ function foldTurns(records: RawRecord[]): { tool_name: rec.tool_name ?? "", status: rec.status ?? "success", }; + const toolData: { input?: Record; output?: string } = {}; if (rec.tool_input && Object.keys(rec.tool_input).length > 0) { - entry.tool_data = { input: rec.tool_input }; + const input: Record = {}; + for (const [k, v] of Object.entries(rec.tool_input)) { + input[k] = truncateToolField(v); + } + toolData.input = input; + } + if (typeof rec.tool_output === "string" && rec.tool_output.length > 0) { + toolData.output = truncateToolField(rec.tool_output); + } + if (toolData.input || toolData.output) { + entry.tool_data = toolData; } pendingTools.push(entry); continue; diff --git a/plugin/dashboard/lib/types.ts b/plugin/dashboard/lib/types.ts index 16f31a4..f478180 100644 --- a/plugin/dashboard/lib/types.ts +++ b/plugin/dashboard/lib/types.ts @@ -12,7 +12,7 @@ export type ProfileStatus = "CURRENT" | "ARCHIVED" | "PENDING"; export interface ToolUsed { tool_name: string; status: string; - tool_data?: { input?: Record }; + tool_data?: { input?: Record; output?: string }; } export interface CitedItem {