@flanksource/clicky-ui 0.3.30 → 0.3.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/comments/CommentCard.cjs +110 -262
- package/dist/comments/CommentCard.cjs.map +1 -1
- package/dist/comments/CommentCard.d.ts +3 -1
- package/dist/comments/CommentCard.d.ts.map +1 -1
- package/dist/comments/CommentCard.js +105 -257
- package/dist/comments/CommentCard.js.map +1 -1
- package/dist/comments/CommentCardParts.cjs +95 -0
- package/dist/comments/CommentCardParts.cjs.map +1 -0
- package/dist/comments/CommentCardParts.d.ts +17 -0
- package/dist/comments/CommentCardParts.d.ts.map +1 -0
- package/dist/comments/CommentCardParts.js +95 -0
- package/dist/comments/CommentCardParts.js.map +1 -0
- package/dist/comments/CommentSidePanel.cjs +14 -7
- package/dist/comments/CommentSidePanel.cjs.map +1 -1
- package/dist/comments/CommentSidePanel.d.ts +3 -1
- package/dist/comments/CommentSidePanel.d.ts.map +1 -1
- package/dist/comments/CommentSidePanel.js +14 -7
- package/dist/comments/CommentSidePanel.js.map +1 -1
- package/dist/comments/CommentThread.cjs +2 -0
- package/dist/comments/CommentThread.cjs.map +1 -1
- package/dist/comments/CommentThread.d.ts +2 -1
- package/dist/comments/CommentThread.d.ts.map +1 -1
- package/dist/comments/CommentThread.js +2 -0
- package/dist/comments/CommentThread.js.map +1 -1
- package/dist/comments/CommentThreadList.cjs +50 -34
- package/dist/comments/CommentThreadList.cjs.map +1 -1
- package/dist/comments/CommentThreadList.d.ts +3 -1
- package/dist/comments/CommentThreadList.d.ts.map +1 -1
- package/dist/comments/CommentThreadList.js +50 -34
- package/dist/comments/CommentThreadList.js.map +1 -1
- package/dist/components/ComboboxMenu.cjs +4 -1
- package/dist/components/ComboboxMenu.cjs.map +1 -1
- package/dist/components/ComboboxMenu.d.ts.map +1 -1
- package/dist/components/ComboboxMenu.js +5 -2
- package/dist/components/ComboboxMenu.js.map +1 -1
- package/dist/components/ComboboxTags.cjs +5 -1
- package/dist/components/ComboboxTags.cjs.map +1 -1
- package/dist/components/ComboboxTags.d.ts.map +1 -1
- package/dist/components/ComboboxTags.js +6 -2
- package/dist/components/ComboboxTags.js.map +1 -1
- package/dist/components/ConnectionLoggingPolicy.cjs +24 -35
- package/dist/components/ConnectionLoggingPolicy.cjs.map +1 -1
- package/dist/components/ConnectionLoggingPolicy.d.ts.map +1 -1
- package/dist/components/ConnectionLoggingPolicy.js +24 -35
- package/dist/components/ConnectionLoggingPolicy.js.map +1 -1
- package/dist/components/MultiSelect.cjs.map +1 -1
- package/dist/components/MultiSelect.d.ts +7 -0
- package/dist/components/MultiSelect.d.ts.map +1 -1
- package/dist/components/MultiSelect.js.map +1 -1
- package/dist/components/filter-bar-multi.cjs +10 -1
- package/dist/components/filter-bar-multi.cjs.map +1 -1
- package/dist/components/filter-bar-multi.d.ts.map +1 -1
- package/dist/components/filter-bar-multi.js +11 -2
- package/dist/components/filter-bar-multi.js.map +1 -1
- package/dist/data/ai/SessionViewer.model.cjs +23 -8
- package/dist/data/ai/SessionViewer.model.cjs.map +1 -1
- package/dist/data/ai/SessionViewer.model.d.ts +8 -0
- package/dist/data/ai/SessionViewer.model.d.ts.map +1 -1
- package/dist/data/ai/SessionViewer.model.js +23 -8
- package/dist/data/ai/SessionViewer.model.js.map +1 -1
- package/dist/data/ai/SessionViewer.rows.cjs +9 -1
- package/dist/data/ai/SessionViewer.rows.cjs.map +1 -1
- package/dist/data/ai/SessionViewer.rows.js +9 -1
- package/dist/data/ai/SessionViewer.rows.js.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/VerifySection.cjs +24 -2
- package/dist/data/ai/SpecRuntimeEditor/VerifySection.cjs.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/VerifySection.d.ts.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/VerifySection.js +25 -3
- package/dist/data/ai/SpecRuntimeEditor/VerifySection.js.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/summaries.cjs.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/summaries.d.ts.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/summaries.js.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor.model.cjs +4 -0
- package/dist/data/ai/SpecRuntimeEditor.model.cjs.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor.model.d.ts +4 -0
- package/dist/data/ai/SpecRuntimeEditor.model.d.ts.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor.model.js +4 -0
- package/dist/data/ai/SpecRuntimeEditor.model.js.map +1 -1
- package/dist/data/test-runner/TestRunner.cjs +6 -4
- package/dist/data/test-runner/TestRunner.cjs.map +1 -1
- package/dist/data/test-runner/TestRunner.d.ts +10 -1
- package/dist/data/test-runner/TestRunner.d.ts.map +1 -1
- package/dist/data/test-runner/TestRunner.js +6 -4
- package/dist/data/test-runner/TestRunner.js.map +1 -1
- package/dist/data/verification/VerificationResults.cjs +99 -0
- package/dist/data/verification/VerificationResults.cjs.map +1 -0
- package/dist/data/verification/VerificationResults.d.ts +27 -0
- package/dist/data/verification/VerificationResults.d.ts.map +1 -0
- package/dist/data/verification/VerificationResults.js +99 -0
- package/dist/data/verification/VerificationResults.js.map +1 -0
- package/dist/data/verification/adapterViews.cjs +116 -0
- package/dist/data/verification/adapterViews.cjs.map +1 -0
- package/dist/data/verification/adapterViews.d.ts +13 -0
- package/dist/data/verification/adapterViews.d.ts.map +1 -0
- package/dist/data/verification/adapterViews.js +116 -0
- package/dist/data/verification/adapterViews.js.map +1 -0
- package/dist/data/verification/adapters.cjs +26 -0
- package/dist/data/verification/adapters.cjs.map +1 -0
- package/dist/data/verification/adapters.d.ts +6 -0
- package/dist/data/verification/adapters.d.ts.map +1 -0
- package/dist/data/verification/adapters.js +26 -0
- package/dist/data/verification/adapters.js.map +1 -0
- package/dist/data/verification/index.d.ts +5 -0
- package/dist/data/verification/index.d.ts.map +1 -0
- package/dist/data/verification/verify-report.cjs +58 -0
- package/dist/data/verification/verify-report.cjs.map +1 -0
- package/dist/data/verification/verify-report.d.ts +96 -0
- package/dist/data/verification/verify-report.d.ts.map +1 -0
- package/dist/data/verification/verify-report.js +58 -0
- package/dist/data/verification/verify-report.js.map +1 -0
- package/dist/data/verification/verifyReportTests.cjs +83 -0
- package/dist/data/verification/verifyReportTests.cjs.map +1 -0
- package/dist/data/verification/verifyReportTests.d.ts +13 -0
- package/dist/data/verification/verifyReportTests.d.ts.map +1 -0
- package/dist/data/verification/verifyReportTests.js +83 -0
- package/dist/data/verification/verifyReportTests.js.map +1 -0
- package/dist/data/version-info.cjs +3 -3
- package/dist/data/version-info.js +3 -3
- package/dist/data.cjs +10 -0
- package/dist/data.cjs.map +1 -1
- package/dist/data.d.ts +1 -0
- package/dist/data.d.ts.map +1 -1
- package/dist/data.js +10 -0
- package/dist/data.js.map +1 -1
- package/dist/index.cjs +10 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SessionViewer.model.cjs","sources":["../../../src/data/ai/SessionViewer.model.ts"],"sourcesContent":["import type { StaticIconComponent } from \"../Icon\";\nimport type {\n SessionBudget,\n SessionCapabilities,\n SessionContext,\n SessionCost,\n SessionMetadataEvent,\n SessionTurn,\n SessionUIMessage,\n SessionUIPart,\n SessionUsage,\n UnifiedSessionInput,\n} from \"./SessionViewer.unified\";\nimport {\n UiAsterisk,\n UiCamera,\n UiClose,\n UiCloudDownload,\n UiCode2,\n UiCommand,\n UiCompass,\n UiCursorClick,\n UiCursorText,\n UiDiff,\n UiEye,\n UiGlobe,\n UiHourglass,\n UiKanban,\n UiKeyboard,\n UiListChecks,\n UiMagicWand,\n UiPalette,\n UiPencilSimpleLine,\n UiProhibit,\n UiPuzzle,\n UiQuestion,\n UiRobotAi,\n UiScan,\n UiScroll,\n UiSearch,\n UiShare,\n UiSparkles,\n UiStack,\n UiStrategy,\n UiTerminal,\n UiWrench,\n} from \"../../icons\";\n\n// ── Captain session schema ──────────────────────────────────────────────────\n// Mirrors github.com/flanksource/captain pkg/ai/history types. A session is a\n// list of SessionEntry records (the rows of a Claude Code / Codex JSONL log).\n\nexport interface SessionToolUse {\n tool?: string;\n input?: Record<string, unknown>;\n timestamp?: string;\n cwd?: string;\n session_id?: string;\n tool_use_id?: string;\n /** \"claude\" or \"codex\". */\n source?: string;\n model?: string;\n reasoning_effort?: string;\n response?: string;\n}\n\nexport interface SessionContent {\n /** Block kind: \"text\", \"thinking\", \"tool_use\", \"tool_result\", … */\n type?: string;\n text?: string;\n thinking?: string;\n name?: string;\n input?: Record<string, unknown>;\n id?: string;\n}\n\nexport interface SessionMessage {\n role?: string;\n stop_reason?: string;\n content?: SessionContent[];\n}\n\nexport interface SessionEntry {\n /** Top-level entry kind: assistant, user, system, … */\n type?: string;\n tool_use?: SessionToolUse;\n message?: SessionMessage;\n timestamp?: string;\n cwd?: string;\n sessionId?: string;\n uuid?: string;\n /** Synthetic assistant entry Claude Code writes when an API request fails. */\n isApiErrorMessage?: boolean;\n apiErrorStatus?: number;\n /** Claude Code's error classification (e.g. \"rate_limit\"). */\n error?: string;\n}\n\n/**\n * A session to render: the unified `SessionUIMessage[]` (preferred — what\n * `GET /api/captain/sessions/{id}` serves), a legacy `SessionEntry[]` log, or\n * raw log text (JSON array or JSONL).\n */\nexport type SessionInput =\n | string\n | SessionEntry[]\n | SessionUIMessage[]\n | UnifiedSessionInput;\n\nexport interface SessionMetadataSummary {\n /** Session identifier exposed by the context meter's copy action. */\n sessionId?: string;\n /** Runtime mechanism used to execute the session. */\n executionMode?: string;\n turns?: SessionTurn[];\n capabilities?: SessionCapabilities;\n budget?: SessionBudget;\n context?: SessionContext;\n events?: SessionMetadataEvent[];\n /** Dominant model id, for the context meter's hover popover. */\n model?: string;\n /** Provider id, used to resolve the model's brand glyph. */\n provider?: string;\n /** Session reasoning effort, for the context meter's hover popover. */\n reasoningEffort?: string;\n /** Aggregate token usage, for the context meter's hover popover. */\n usage?: SessionUsage;\n /** Aggregate cost breakdown, for the context meter's hover popover. */\n cost?: SessionCost;\n}\n\n// ── Normalized events ───────────────────────────────────────────────────────\n// The raw schema interleaves consolidated `tool_use` rows with `message`\n// content blocks. normalizeSession flattens both shapes into a single ordered\n// list the viewer can render row-by-row.\n\nexport type SessionEventKind =\n | \"system\"\n | \"user\"\n | \"assistant\"\n | \"thinking\"\n | \"tool\"\n | \"error\";\n\nexport interface SessionEvent {\n id: string;\n kind: SessionEventKind;\n /** Tool name (kind === \"tool\"). */\n tool?: string;\n toolInput?: Record<string, unknown>;\n toolResponse?: string;\n /** Prose for user/assistant/thinking, or the error message for errors. */\n text?: string;\n /** Working directory the tool ran in — used to relativize file paths. */\n cwd?: string;\n timestamp?: string;\n model?: string;\n reasoningEffort?: string;\n source?: string;\n turnId?: string;\n agentId?: string;\n toolState?: string;\n approval?: SessionUIPart[\"approval\"];\n pending?: boolean;\n toolCallId?: string;\n approvalId?: string;\n sessionId?: string;\n raw?: unknown;\n errorType?: string;\n errorStatus?: number;\n}\n\nexport function truncate(text: string, max: number): string {\n return text.length <= max ? text : `${text.slice(0, max)}…`;\n}\n\n// parseEntries accepts a parsed array as-is, or parses a string as a whole-\n// document JSON (array or single object, possibly pretty-printed) first, then\n// falls back to JSONL (one object per line). The whole-document parse error is\n// caught only to attempt the JSONL fallback — a genuinely malformed JSONL line\n// throws loudly rather than being silently dropped.\nfunction parseEntries(input: string | SessionEntry[]): SessionEntry[] {\n if (Array.isArray(input)) return input;\n const text = input.trim();\n if (!text) return [];\n try {\n const parsed: unknown = JSON.parse(text);\n return Array.isArray(parsed)\n ? (parsed as SessionEntry[])\n : [parsed as SessionEntry];\n } catch {\n // not a single JSON document — treat as JSONL below\n }\n return text\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter(Boolean)\n .map((line) => {\n try {\n return JSON.parse(line) as SessionEntry;\n } catch {\n throw new Error(\n `SessionViewer: invalid session JSON line: ${truncate(line, 80)}`,\n );\n }\n });\n}\n\nfunction roleFromType(type: string | undefined): string {\n return type === \"system\" || type === \"user\" || type === \"assistant\"\n ? type\n : \"assistant\";\n}\n\nfunction toolEvent(\n id: string,\n tool: string,\n input: Record<string, unknown> | undefined,\n response: string | undefined,\n timestamp: string | undefined,\n meta: {\n model?: string;\n reasoningEffort?: string;\n source?: string;\n cwd?: string;\n turnId?: string;\n agentId?: string;\n toolState?: string;\n approval?: SessionUIPart[\"approval\"];\n pending?: boolean;\n toolCallId?: string;\n approvalId?: string;\n sessionId?: string;\n raw?: unknown;\n } = {},\n): SessionEvent {\n return {\n id,\n kind: \"tool\",\n tool,\n ...(input ? { toolInput: input } : {}),\n ...(response ? { toolResponse: response } : {}),\n ...(timestamp ? { timestamp } : {}),\n ...(meta.model ? { model: meta.model } : {}),\n ...(meta.reasoningEffort ? { reasoningEffort: meta.reasoningEffort } : {}),\n ...(meta.source ? { source: meta.source } : {}),\n ...(meta.cwd ? { cwd: meta.cwd } : {}),\n ...(meta.turnId ? { turnId: meta.turnId } : {}),\n ...(meta.agentId ? { agentId: meta.agentId } : {}),\n ...(meta.toolState ? { toolState: meta.toolState } : {}),\n ...(meta.approval ? { approval: meta.approval } : {}),\n pending: meta.pending ?? false,\n ...(meta.toolCallId ? { toolCallId: meta.toolCallId } : {}),\n ...(meta.approvalId ? { approvalId: meta.approvalId } : {}),\n ...(meta.sessionId ? { sessionId: meta.sessionId } : {}),\n ...(meta.raw !== undefined ? { raw: meta.raw } : {}),\n };\n}\n\nfunction blockEvent(\n block: SessionContent,\n role: string,\n id: string,\n timestamp: string | undefined,\n cwd: string | undefined,\n): SessionEvent | null {\n if (block.type === \"tool_use\" || (block.name && block.input)) {\n if (!block.name) return null;\n return toolEvent(id, block.name, block.input, undefined, timestamp, {\n ...(cwd ? { cwd } : {}),\n ...(block.id ? { toolCallId: block.id } : {}),\n });\n }\n if (block.type === \"thinking\" || block.thinking) {\n const text = block.thinking ?? block.text;\n return text\n ? { id, kind: \"thinking\", text, ...(timestamp ? { timestamp } : {}) }\n : null;\n }\n if (block.text) {\n return {\n id,\n kind:\n role === \"system\" ? \"system\" : role === \"user\" ? \"user\" : \"assistant\",\n text: block.text,\n ...(timestamp ? { timestamp } : {}),\n };\n }\n return null;\n}\n\n/** Flatten a captain session (unified messages, entries, or raw log text) into\n * ordered events. Unified `SessionUIMessage[]` is detected by its `parts`. */\nexport function normalizeSession(input: SessionInput): SessionEvent[] {\n if (looksLikeUnifiedSession(input)) {\n return normalizeMessages(input.messages ?? []);\n }\n if (Array.isArray(input) && looksLikeUnifiedMessages(input)) {\n return normalizeMessages(input);\n }\n const entries = parseEntries(input as string | SessionEntry[]);\n const events: SessionEvent[] = [];\n entries.forEach((entry, seq) => {\n const baseId = entry.uuid ?? `e${seq}`;\n\n if (entry.isApiErrorMessage) {\n events.push({\n id: `${baseId}-err`,\n kind: \"error\",\n text: errorMessage(entry),\n ...(entry.error ? { errorType: entry.error } : {}),\n ...(entry.apiErrorStatus ? { errorStatus: entry.apiErrorStatus } : {}),\n ...(entry.timestamp ? { timestamp: entry.timestamp } : {}),\n raw: entry,\n });\n return;\n }\n\n const tu = entry.tool_use;\n if (tu?.tool) {\n const cwd = tu.cwd ?? entry.cwd;\n events.push(\n toolEvent(\n `${baseId}-tool`,\n tu.tool,\n tu.input,\n tu.response,\n tu.timestamp ?? entry.timestamp,\n {\n ...(tu.model ? { model: tu.model } : {}),\n ...(tu.reasoning_effort\n ? { reasoningEffort: tu.reasoning_effort }\n : {}),\n ...(tu.source ? { source: tu.source } : {}),\n ...(cwd ? { cwd } : {}),\n ...(tu.tool_use_id ? { toolCallId: tu.tool_use_id } : {}),\n ...(tu.session_id ? { sessionId: tu.session_id } : {}),\n raw: entry,\n },\n ),\n );\n return;\n }\n\n const role = roleFromType(entry.message?.role ?? entry.type);\n for (const [i, block] of (entry.message?.content ?? []).entries()) {\n const ev = blockEvent(\n block,\n role,\n `${baseId}-${i}`,\n entry.timestamp,\n entry.cwd,\n );\n if (ev) events.push(ev);\n }\n });\n return events;\n}\n\nexport function getSessionMetadata(\n input: SessionInput,\n): SessionMetadataSummary | undefined {\n if (!looksLikeUnifiedSession(input)) return undefined;\n const metadata: SessionMetadataSummary = {\n ...(input.id ? { sessionId: input.id } : {}),\n ...(input.executionMode ? { executionMode: input.executionMode } : {}),\n ...(input.turns ? { turns: input.turns } : {}),\n ...(input.capabilities ? { capabilities: input.capabilities } : {}),\n ...(input.budget ? { budget: input.budget } : {}),\n ...(input.context ? { context: input.context } : {}),\n ...(input.events ? { events: input.events } : {}),\n ...(input.model ? { model: input.model } : {}),\n ...(input.provider ? { provider: input.provider } : {}),\n ...(input.reasoningEffort\n ? { reasoningEffort: input.reasoningEffort }\n : {}),\n ...(input.usage ? { usage: input.usage } : {}),\n ...(input.cost ? { cost: input.cost } : {}),\n };\n return Object.keys(metadata).length > 0 ? metadata : undefined;\n}\n\nfunction errorMessage(entry: SessionEntry): string {\n const status = entry.apiErrorStatus ? ` (HTTP ${entry.apiErrorStatus})` : \"\";\n return `${entry.error ?? \"API error\"}${status}`;\n}\n\n// ── Unified message normalization ───────────────────────────────────────────\n// Projects the canonical SessionUIMessage[] (captain pkg/session) into the same\n// SessionEvent rows, so the viewer renders the unified model and the legacy\n// SessionEntry log identically.\n\n/** A unified message array is told apart from a SessionEntry log by its\n * per-message `parts` array (a SessionEntry carries `message`/`tool_use`). */\nfunction looksLikeUnifiedMessages(\n arr: SessionEntry[] | SessionUIMessage[],\n): arr is SessionUIMessage[] {\n const first: unknown = arr[0];\n return (\n typeof first === \"object\" &&\n first !== null &&\n Array.isArray((first as SessionUIMessage).parts)\n );\n}\n\nfunction looksLikeUnifiedSession(\n input: SessionInput,\n): input is UnifiedSessionInput {\n return (\n typeof input === \"object\" &&\n input !== null &&\n !Array.isArray(input) &&\n (\"messages\" in input ||\n \"turns\" in input ||\n \"capabilities\" in input ||\n \"budget\" in input ||\n \"context\" in input)\n );\n}\n\nfunction isUnifiedToolPart(part: SessionUIPart): boolean {\n return (\n Boolean(part.toolName) &&\n (part.type === \"dynamic-tool\" || part.type.startsWith(\"tool-\"))\n );\n}\n\n/** Render a tool part's already-parsed JSON output as text. */\nfunction outputToText(output: unknown): string | undefined {\n if (output == null) return undefined;\n return typeof output === \"string\" ? output : JSON.stringify(output);\n}\n\nfunction asRecord(input: unknown): Record<string, unknown> | undefined {\n return typeof input === \"object\" && input !== null && !Array.isArray(input)\n ? (input as Record<string, unknown>)\n : undefined;\n}\n\nfunction partEvent(\n part: SessionUIPart,\n role: \"system\" | \"user\" | \"assistant\",\n id: string,\n meta: {\n timestamp?: string;\n cwd?: string;\n model?: string;\n reasoningEffort?: string;\n source?: string;\n turnId?: string;\n agentId?: string;\n sessionId?: string;\n raw?: unknown;\n },\n): SessionEvent | null {\n if (isUnifiedToolPart(part)) {\n const pending = pendingFromPart(part);\n return toolEvent(\n id,\n part.toolName as string,\n asRecord(part.input),\n outputToText(part.output),\n meta.timestamp,\n {\n ...(meta.model ? { model: meta.model } : {}),\n ...(meta.reasoningEffort\n ? { reasoningEffort: meta.reasoningEffort }\n : {}),\n ...(meta.source ? { source: meta.source } : {}),\n ...(meta.cwd ? { cwd: meta.cwd } : {}),\n ...(meta.turnId ? { turnId: meta.turnId } : {}),\n ...(meta.agentId ? { agentId: meta.agentId } : {}),\n ...(meta.sessionId ? { sessionId: meta.sessionId } : {}),\n ...(part.state ? { toolState: part.state } : {}),\n ...(part.approval ? { approval: part.approval } : {}),\n pending,\n ...(part.toolCallId ? { toolCallId: part.toolCallId } : {}),\n ...(part.approval?.id ? { approvalId: part.approval.id } : {}),\n ...(meta.raw !== undefined ? { raw: meta.raw } : {}),\n },\n );\n }\n if (part.type === \"reasoning\") {\n return part.text\n ? {\n id,\n kind: \"thinking\",\n text: part.text,\n ...(meta.timestamp ? { timestamp: meta.timestamp } : {}),\n ...(meta.turnId ? { turnId: meta.turnId } : {}),\n ...(meta.agentId ? { agentId: meta.agentId } : {}),\n ...(meta.raw !== undefined ? { raw: meta.raw } : {}),\n }\n : null;\n }\n if (part.type === \"text\") {\n return part.text\n ? {\n id,\n kind: role,\n text: part.text,\n ...(meta.timestamp ? { timestamp: meta.timestamp } : {}),\n ...(meta.turnId ? { turnId: meta.turnId } : {}),\n ...(meta.agentId ? { agentId: meta.agentId } : {}),\n ...(meta.raw !== undefined ? { raw: meta.raw } : {}),\n }\n : null;\n }\n return null; // file / unknown parts have no row representation\n}\n\nfunction pendingFromPart(part: SessionUIPart): boolean {\n if (part.approval?.approved !== undefined) return false;\n if (\n [\"approval-responded\", \"output-available\", \"output-denied\"].includes(\n part.state ?? \"\",\n )\n )\n return false;\n return (\n part.pending === true ||\n part.approval?.pending === true ||\n part.state === \"approval-requested\"\n );\n}\n\n/** Flatten unified session messages into ordered SessionEvent rows. */\nexport function normalizeMessages(\n messages: SessionUIMessage[],\n): SessionEvent[] {\n const events: SessionEvent[] = [];\n messages.forEach((msg, seq) => {\n const prov = msg.provenance;\n const baseId = msg.id ?? prov?.uuid ?? `m${seq}`;\n if (prov?.apiErrorStatus) {\n events.push({\n id: `${baseId}-err`,\n kind: \"error\",\n text: `API error (HTTP ${prov.apiErrorStatus})`,\n errorStatus: prov.apiErrorStatus,\n ...(prov.timestamp ? { timestamp: prov.timestamp } : {}),\n ...(msg.turnId ? { turnId: msg.turnId } : {}),\n ...(prov.agentId ? { agentId: prov.agentId } : {}),\n ...(msg.raw !== undefined ? { raw: msg.raw } : {}),\n });\n return;\n }\n const role: \"system\" | \"user\" | \"assistant\" =\n msg.role === \"system\"\n ? \"system\"\n : msg.role === \"user\"\n ? \"user\"\n : \"assistant\";\n const meta = {\n ...(prov?.timestamp ? { timestamp: prov.timestamp } : {}),\n ...(prov?.cwd ? { cwd: prov.cwd } : {}),\n ...(prov?.model ? { model: prov.model } : {}),\n ...(prov?.reasoningEffort\n ? { reasoningEffort: prov.reasoningEffort }\n : {}),\n ...(prov?.source ? { source: prov.source } : {}),\n ...(msg.turnId ? { turnId: msg.turnId } : {}),\n ...(prov?.agentId ? { agentId: prov.agentId } : {}),\n ...(prov?.sessionId ? { sessionId: prov.sessionId } : {}),\n ...(msg.raw !== undefined ? { raw: msg.raw } : {}),\n };\n msg.parts.forEach((part, i) => {\n const ev = partEvent(part, role, `${baseId}-${i}`, meta);\n if (ev) events.push(ev);\n });\n });\n return events;\n}\n\n// ── Action icon registry ────────────────────────────────────────────────────\n// Implements the Flanksource \"Coding agent action icons\" design: every agent\n// tool maps to a Phosphor-derived generated icon (Ui*) and a semantic tone so a\n// scan of the log reads at a glance. Tones group by surface — file reads (sky),\n// writes (amber), edits (violet), execution (emerald), agents (indigo),\n// destructive (rose), assets (pink/fuchsia).\n\nexport type SessionTone =\n | \"sky\"\n | \"amber\"\n | \"violet\"\n | \"emerald\"\n | \"teal\"\n | \"orange\"\n | \"rose\"\n | \"indigo\"\n | \"fuchsia\"\n | \"pink\"\n | \"slate\";\n\nexport interface SessionActionMeta {\n icon: StaticIconComponent;\n tone: SessionTone;\n /** Human-readable verb shown as the row heading (and in the filter menu). */\n label: string;\n /** The row heading is the input summary alone (file path, command) — the\n * icon and tone carry the verb, so the label only appears in the menu. */\n summaryOnly?: boolean;\n}\n\nconst ACTIONS: Record<string, SessionActionMeta> = {\n // File operations. Read (eye) and Write (diff) are deliberately kept off the\n // design's file-text / file-plus glyphs — they read better in a scrolling log\n // and write-type rows also carry a +/- diff stat.\n Read: { icon: UiEye, tone: \"sky\", label: \"Read file\", summaryOnly: true },\n Write: {\n icon: UiDiff,\n tone: \"amber\",\n label: \"Write file\",\n summaryOnly: true,\n },\n Edit: {\n icon: UiPencilSimpleLine,\n tone: \"violet\",\n label: \"Edit file\",\n summaryOnly: true,\n },\n MultiEdit: {\n icon: UiStack,\n tone: \"violet\",\n label: \"Multi-edit\",\n summaryOnly: true,\n },\n NotebookEdit: {\n icon: UiPencilSimpleLine,\n tone: \"violet\",\n label: \"Edit notebook\",\n summaryOnly: true,\n },\n // Search & navigation\n Grep: { icon: UiSearch, tone: \"amber\", label: \"Grep\" },\n Glob: { icon: UiAsterisk, tone: \"sky\", label: \"Glob\" },\n // Execution & shell\n Bash: { icon: UiTerminal, tone: \"emerald\", label: \"Run command\" },\n BashOutput: { icon: UiCode2, tone: \"emerald\", label: \"Shell output\" },\n KillShell: { icon: UiProhibit, tone: \"rose\", label: \"Kill shell\" },\n KillBash: { icon: UiProhibit, tone: \"rose\", label: \"Kill shell\" },\n // Agents & planning\n Task: { icon: UiRobotAi, tone: \"indigo\", label: \"Sub-agent task\" },\n Agent: { icon: UiRobotAi, tone: \"indigo\", label: \"Sub-agent task\" },\n Skill: { icon: UiMagicWand, tone: \"fuchsia\", label: \"Invoke skill\" },\n TodoWrite: { icon: UiListChecks, tone: \"sky\", label: \"Update todos\" },\n Plan: { icon: UiStrategy, tone: \"sky\", label: \"Plan\" },\n TaskCreate: { icon: UiKanban, tone: \"sky\", label: \"Create task\" },\n TaskUpdate: { icon: UiKanban, tone: \"sky\", label: \"Update task\" },\n TaskList: { icon: UiKanban, tone: \"sky\", label: \"List tasks\" },\n TaskGet: { icon: UiKanban, tone: \"sky\", label: \"Get task\" },\n TaskOutput: { icon: UiKanban, tone: \"sky\", label: \"Task output\" },\n TaskStop: { icon: UiProhibit, tone: \"rose\", label: \"Stop task\" },\n ToolSearch: { icon: UiSearch, tone: \"amber\", label: \"Search tools\" },\n AskUserQuestion: { icon: UiQuestion, tone: \"sky\", label: \"Ask user\" },\n EnterPlanMode: { icon: UiStrategy, tone: \"sky\", label: \"Enter plan mode\" },\n ExitPlanMode: { icon: UiStrategy, tone: \"sky\", label: \"Exit plan mode\" },\n // Web & browser automation\n WebFetch: { icon: UiCloudDownload, tone: \"sky\", label: \"Fetch URL\" },\n WebSearch: { icon: UiGlobe, tone: \"sky\", label: \"Web search\" },\n browser_navigate: { icon: UiCompass, tone: \"sky\", label: \"Navigate\" },\n browser_navigate_back: {\n icon: UiCompass,\n tone: \"sky\",\n label: \"Navigate back\",\n },\n browser_click: { icon: UiCursorClick, tone: \"sky\", label: \"Click\" },\n browser_triple_click: {\n icon: UiCursorText,\n tone: \"sky\",\n label: \"Triple click\",\n },\n browser_type: { icon: UiKeyboard, tone: \"emerald\", label: \"Type text\" },\n browser_press_key: { icon: UiCommand, tone: \"amber\", label: \"Press key\" },\n browser_snapshot: { icon: UiScan, tone: \"violet\", label: \"Snapshot\" },\n browser_take_screenshot: {\n icon: UiCamera,\n tone: \"indigo\",\n label: \"Screenshot\",\n },\n browser_evaluate: { icon: UiCode2, tone: \"violet\", label: \"Evaluate JS\" },\n browser_console_messages: { icon: UiScroll, tone: \"slate\", label: \"Console\" },\n browser_network_requests: {\n icon: UiShare,\n tone: \"emerald\",\n label: \"Network\",\n },\n browser_wait_for: { icon: UiHourglass, tone: \"amber\", label: \"Wait\" },\n Wait: { icon: UiHourglass, tone: \"amber\", label: \"Wait\" },\n browser_close: { icon: UiClose, tone: \"rose\", label: \"Close browser\" },\n};\n\n// MCP tools surface as `mcp__<server>__<name>` or `<server>__<name>`. Icon\n// servers get a distinct accent (palette); generative servers reuse the sparkle;\n// the rest fall back to the puzzle piece.\nconst MCP_ICON_SERVERS = new Set([\n \"iconify\",\n \"icons8\",\n \"lucide\",\n \"react-icons\",\n]);\nconst MCP_GEN_SERVERS = new Set([\"gemini\", \"openai\", \"anthropic\"]);\n\ninterface McpTool {\n server: string;\n name: string;\n}\n\nexport function splitMcpTool(tool: string): McpTool | null {\n const rest = tool.startsWith(\"mcp__\") ? tool.slice(\"mcp__\".length) : tool;\n const idx = rest.indexOf(\"__\");\n if (idx < 0) return null;\n return { server: rest.slice(0, idx), name: rest.slice(idx + 2) };\n}\n\n/** Resolve the icon, tone, and label for a tool name. */\nexport function getSessionAction(tool: string): SessionActionMeta {\n const exact = ACTIONS[tool];\n if (exact) return exact;\n\n const mcp = splitMcpTool(tool);\n if (mcp) {\n const label = `${mcp.server}: ${mcp.name.replace(/_/g, \" \")}`;\n if (MCP_ICON_SERVERS.has(mcp.server))\n return { icon: UiPalette, tone: \"pink\", label };\n if (MCP_GEN_SERVERS.has(mcp.server))\n return { icon: UiSparkles, tone: \"violet\", label };\n return { icon: UiPuzzle, tone: \"violet\", label };\n }\n\n return { icon: UiWrench, tone: \"slate\", label: tool };\n}\n\n/** Count tool-call events, the dominant model, and totals for the header. */\nexport function summarizeSession(events: SessionEvent[]): {\n toolCount: number;\n messageCount: number;\n model?: string;\n} {\n let toolCount = 0;\n let messageCount = 0;\n const modelCounts = new Map<string, number>();\n for (const event of events) {\n if (event.kind === \"tool\") toolCount += 1;\n if (\n event.kind === \"system\" ||\n event.kind === \"user\" ||\n event.kind === \"assistant\"\n ) {\n messageCount += 1;\n }\n if (event.model)\n modelCounts.set(event.model, (modelCounts.get(event.model) ?? 0) + 1);\n }\n let model: string | undefined;\n let best = 0;\n for (const [name, count] of modelCounts) {\n if (count > best) {\n best = count;\n model = name;\n }\n }\n return { toolCount, messageCount, ...(model ? { model } : {}) };\n}\n"],"names":["UiEye","UiDiff","UiPencilSimpleLine","UiStack","UiSearch","UiAsterisk","UiTerminal","UiCode2","UiProhibit","UiRobotAi","UiMagicWand","UiListChecks","UiStrategy","UiKanban","UiQuestion","UiCloudDownload","UiGlobe","UiCompass","UiCursorClick","UiCursorText","UiKeyboard","UiCommand","UiScan","UiCamera","UiScroll","UiShare","UiHourglass","UiClose","UiPalette","UiSparkles","UiPuzzle","UiWrench"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SessionViewer.model.cjs","sources":["../../../src/data/ai/SessionViewer.model.ts"],"sourcesContent":["import type { StaticIconComponent } from \"../Icon\";\nimport { WORKFLOW_PHASES } from \"./agent-action-icons\";\nimport type {\n SessionBudget,\n SessionCapabilities,\n SessionContext,\n SessionCost,\n SessionMetadataEvent,\n SessionTurn,\n SessionUIMessage,\n SessionUIPart,\n SessionUsage,\n UnifiedSessionInput,\n} from \"./SessionViewer.unified\";\nimport {\n UiAsterisk,\n UiCamera,\n UiClose,\n UiCloudDownload,\n UiCode2,\n UiCommand,\n UiCompass,\n UiCursorClick,\n UiCursorText,\n UiDiff,\n UiEye,\n UiGlobe,\n UiHourglass,\n UiKanban,\n UiKeyboard,\n UiListChecks,\n UiMagicWand,\n UiPalette,\n UiPencilSimpleLine,\n UiProhibit,\n UiPuzzle,\n UiQuestion,\n UiRobotAi,\n UiScan,\n UiScroll,\n UiSearch,\n UiShare,\n UiSparkles,\n UiStack,\n UiStrategy,\n UiTerminal,\n UiWrench,\n} from \"../../icons\";\n\n// ── Captain session schema ──────────────────────────────────────────────────\n// Mirrors github.com/flanksource/captain pkg/ai/history types. A session is a\n// list of SessionEntry records (the rows of a Claude Code / Codex JSONL log).\n\nexport interface SessionToolUse {\n tool?: string;\n input?: Record<string, unknown>;\n timestamp?: string;\n cwd?: string;\n session_id?: string;\n tool_use_id?: string;\n /** \"claude\" or \"codex\". */\n source?: string;\n model?: string;\n reasoning_effort?: string;\n response?: string;\n}\n\nexport interface SessionContent {\n /** Block kind: \"text\", \"thinking\", \"tool_use\", \"tool_result\", … */\n type?: string;\n text?: string;\n thinking?: string;\n name?: string;\n input?: Record<string, unknown>;\n id?: string;\n}\n\nexport interface SessionMessage {\n role?: string;\n stop_reason?: string;\n content?: SessionContent[];\n}\n\nexport interface SessionEntry {\n /** Top-level entry kind: assistant, user, system, … */\n type?: string;\n tool_use?: SessionToolUse;\n message?: SessionMessage;\n timestamp?: string;\n cwd?: string;\n sessionId?: string;\n uuid?: string;\n /** Synthetic assistant entry Claude Code writes when an API request fails. */\n isApiErrorMessage?: boolean;\n apiErrorStatus?: number;\n /** Claude Code's error classification (e.g. \"rate_limit\"). */\n error?: string;\n}\n\n/**\n * A session to render: the unified `SessionUIMessage[]` (preferred — what\n * `GET /api/captain/sessions/{id}` serves), a legacy `SessionEntry[]` log, or\n * raw log text (JSON array or JSONL).\n */\nexport type SessionInput =\n | string\n | SessionEntry[]\n | SessionUIMessage[]\n | UnifiedSessionInput;\n\nexport interface SessionMetadataSummary {\n /** Session identifier exposed by the context meter's copy action. */\n sessionId?: string;\n /** Runtime mechanism used to execute the session. */\n executionMode?: string;\n turns?: SessionTurn[];\n capabilities?: SessionCapabilities;\n budget?: SessionBudget;\n context?: SessionContext;\n events?: SessionMetadataEvent[];\n /** Dominant model id, for the context meter's hover popover. */\n model?: string;\n /** Provider id, used to resolve the model's brand glyph. */\n provider?: string;\n /** Session reasoning effort, for the context meter's hover popover. */\n reasoningEffort?: string;\n /** Aggregate token usage, for the context meter's hover popover. */\n usage?: SessionUsage;\n /** Aggregate cost breakdown, for the context meter's hover popover. */\n cost?: SessionCost;\n}\n\n// ── Normalized events ───────────────────────────────────────────────────────\n// The raw schema interleaves consolidated `tool_use` rows with `message`\n// content blocks. normalizeSession flattens both shapes into a single ordered\n// list the viewer can render row-by-row.\n\nexport type SessionEventKind =\n | \"system\"\n | \"user\"\n | \"assistant\"\n | \"thinking\"\n | \"tool\"\n | \"error\";\n\nexport interface SessionEvent {\n id: string;\n kind: SessionEventKind;\n /** Tool name (kind === \"tool\"). */\n tool?: string;\n toolInput?: Record<string, unknown>;\n toolResponse?: string;\n /** Prose for user/assistant/thinking, or the error message for errors. */\n text?: string;\n /** Working directory the tool ran in — used to relativize file paths. */\n cwd?: string;\n timestamp?: string;\n model?: string;\n reasoningEffort?: string;\n source?: string;\n turnId?: string;\n agentId?: string;\n toolState?: string;\n approval?: SessionUIPart[\"approval\"];\n pending?: boolean;\n toolCallId?: string;\n approvalId?: string;\n sessionId?: string;\n raw?: unknown;\n errorType?: string;\n errorStatus?: number;\n /** Set for a `verified`/`verify_failed` role — the workflow verify verdict. */\n verifyPassed?: boolean;\n /** Row icon override (e.g. the verify glyph). Renderers fall back to the\n * kind's default icon when absent. */\n icon?: StaticIconComponent;\n /** Row tone override (e.g. pass/fail for a verify row). Renderers fall back\n * to the kind's default tone when absent. */\n tone?: SessionTone;\n}\n\nexport function truncate(text: string, max: number): string {\n return text.length <= max ? text : `${text.slice(0, max)}…`;\n}\n\n// parseEntries accepts a parsed array as-is, or parses a string as a whole-\n// document JSON (array or single object, possibly pretty-printed) first, then\n// falls back to JSONL (one object per line). The whole-document parse error is\n// caught only to attempt the JSONL fallback — a genuinely malformed JSONL line\n// throws loudly rather than being silently dropped.\nfunction parseEntries(input: string | SessionEntry[]): SessionEntry[] {\n if (Array.isArray(input)) return input;\n const text = input.trim();\n if (!text) return [];\n try {\n const parsed: unknown = JSON.parse(text);\n return Array.isArray(parsed)\n ? (parsed as SessionEntry[])\n : [parsed as SessionEntry];\n } catch {\n // not a single JSON document — treat as JSONL below\n }\n return text\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter(Boolean)\n .map((line) => {\n try {\n return JSON.parse(line) as SessionEntry;\n } catch {\n throw new Error(\n `SessionViewer: invalid session JSON line: ${truncate(line, 80)}`,\n );\n }\n });\n}\n\n// \"verified\"/\"verify_failed\" pass through unchanged — the legacy SessionEntry\n// path needs the raw role to route to the same verify row `normalizeMessages`\n// builds for the unified path (see the call site below), not just a\n// system/user/assistant kind.\nfunction roleFromType(type: string | undefined): string {\n return type === \"system\" ||\n type === \"user\" ||\n type === \"assistant\" ||\n type === \"verified\" ||\n type === \"verify_failed\"\n ? type\n : \"assistant\";\n}\n\nfunction toolEvent(\n id: string,\n tool: string,\n input: Record<string, unknown> | undefined,\n response: string | undefined,\n timestamp: string | undefined,\n meta: {\n model?: string;\n reasoningEffort?: string;\n source?: string;\n cwd?: string;\n turnId?: string;\n agentId?: string;\n toolState?: string;\n approval?: SessionUIPart[\"approval\"];\n pending?: boolean;\n toolCallId?: string;\n approvalId?: string;\n sessionId?: string;\n raw?: unknown;\n } = {},\n): SessionEvent {\n return {\n id,\n kind: \"tool\",\n tool,\n ...(input ? { toolInput: input } : {}),\n ...(response ? { toolResponse: response } : {}),\n ...(timestamp ? { timestamp } : {}),\n ...(meta.model ? { model: meta.model } : {}),\n ...(meta.reasoningEffort ? { reasoningEffort: meta.reasoningEffort } : {}),\n ...(meta.source ? { source: meta.source } : {}),\n ...(meta.cwd ? { cwd: meta.cwd } : {}),\n ...(meta.turnId ? { turnId: meta.turnId } : {}),\n ...(meta.agentId ? { agentId: meta.agentId } : {}),\n ...(meta.toolState ? { toolState: meta.toolState } : {}),\n ...(meta.approval ? { approval: meta.approval } : {}),\n pending: meta.pending ?? false,\n ...(meta.toolCallId ? { toolCallId: meta.toolCallId } : {}),\n ...(meta.approvalId ? { approvalId: meta.approvalId } : {}),\n ...(meta.sessionId ? { sessionId: meta.sessionId } : {}),\n ...(meta.raw !== undefined ? { raw: meta.raw } : {}),\n };\n}\n\nfunction blockEvent(\n block: SessionContent,\n role: string,\n id: string,\n timestamp: string | undefined,\n cwd: string | undefined,\n verifyPassed: boolean | undefined,\n): SessionEvent | null {\n if (block.type === \"tool_use\" || (block.name && block.input)) {\n if (!block.name) return null;\n return toolEvent(id, block.name, block.input, undefined, timestamp, {\n ...(cwd ? { cwd } : {}),\n ...(block.id ? { toolCallId: block.id } : {}),\n });\n }\n if (block.type === \"thinking\" || block.thinking) {\n const text = block.thinking ?? block.text;\n return text\n ? { id, kind: \"thinking\", text, ...(timestamp ? { timestamp } : {}) }\n : null;\n }\n if (block.text) {\n // A verify step reports its verdict as a `verified`/`verify_failed` role —\n // rendered as a system-style row carrying the pass/fail tone and the\n // workflow verify glyph, mirroring `normalizeMessages`'s unified-path rows.\n return {\n id,\n kind:\n role === \"system\" || verifyPassed !== undefined\n ? \"system\"\n : role === \"user\"\n ? \"user\"\n : \"assistant\",\n text: block.text,\n ...(timestamp ? { timestamp } : {}),\n ...(verifyPassed !== undefined\n ? {\n verifyPassed,\n tone: verifyPassed ? \"emerald\" : \"rose\",\n icon: WORKFLOW_PHASES.verify.icon,\n }\n : {}),\n };\n }\n return null;\n}\n\n/** Flatten a captain session (unified messages, entries, or raw log text) into\n * ordered events. Unified `SessionUIMessage[]` is detected by its `parts`. */\nexport function normalizeSession(input: SessionInput): SessionEvent[] {\n if (looksLikeUnifiedSession(input)) {\n return normalizeMessages(input.messages ?? []);\n }\n if (Array.isArray(input) && looksLikeUnifiedMessages(input)) {\n return normalizeMessages(input);\n }\n const entries = parseEntries(input as string | SessionEntry[]);\n const events: SessionEvent[] = [];\n entries.forEach((entry, seq) => {\n const baseId = entry.uuid ?? `e${seq}`;\n\n if (entry.isApiErrorMessage) {\n events.push({\n id: `${baseId}-err`,\n kind: \"error\",\n text: errorMessage(entry),\n ...(entry.error ? { errorType: entry.error } : {}),\n ...(entry.apiErrorStatus ? { errorStatus: entry.apiErrorStatus } : {}),\n ...(entry.timestamp ? { timestamp: entry.timestamp } : {}),\n raw: entry,\n });\n return;\n }\n\n const tu = entry.tool_use;\n if (tu?.tool) {\n const cwd = tu.cwd ?? entry.cwd;\n events.push(\n toolEvent(\n `${baseId}-tool`,\n tu.tool,\n tu.input,\n tu.response,\n tu.timestamp ?? entry.timestamp,\n {\n ...(tu.model ? { model: tu.model } : {}),\n ...(tu.reasoning_effort\n ? { reasoningEffort: tu.reasoning_effort }\n : {}),\n ...(tu.source ? { source: tu.source } : {}),\n ...(cwd ? { cwd } : {}),\n ...(tu.tool_use_id ? { toolCallId: tu.tool_use_id } : {}),\n ...(tu.session_id ? { sessionId: tu.session_id } : {}),\n raw: entry,\n },\n ),\n );\n return;\n }\n\n const role = roleFromType(entry.message?.role ?? entry.type);\n const verifyPassed =\n role === \"verified\" ? true : role === \"verify_failed\" ? false : undefined;\n for (const [i, block] of (entry.message?.content ?? []).entries()) {\n const ev = blockEvent(\n block,\n role,\n `${baseId}-${i}`,\n entry.timestamp,\n entry.cwd,\n verifyPassed,\n );\n if (ev) events.push(ev);\n }\n });\n return events;\n}\n\nexport function getSessionMetadata(\n input: SessionInput,\n): SessionMetadataSummary | undefined {\n if (!looksLikeUnifiedSession(input)) return undefined;\n const metadata: SessionMetadataSummary = {\n ...(input.id ? { sessionId: input.id } : {}),\n ...(input.executionMode ? { executionMode: input.executionMode } : {}),\n ...(input.turns ? { turns: input.turns } : {}),\n ...(input.capabilities ? { capabilities: input.capabilities } : {}),\n ...(input.budget ? { budget: input.budget } : {}),\n ...(input.context ? { context: input.context } : {}),\n ...(input.events ? { events: input.events } : {}),\n ...(input.model ? { model: input.model } : {}),\n ...(input.provider ? { provider: input.provider } : {}),\n ...(input.reasoningEffort\n ? { reasoningEffort: input.reasoningEffort }\n : {}),\n ...(input.usage ? { usage: input.usage } : {}),\n ...(input.cost ? { cost: input.cost } : {}),\n };\n return Object.keys(metadata).length > 0 ? metadata : undefined;\n}\n\nfunction errorMessage(entry: SessionEntry): string {\n const status = entry.apiErrorStatus ? ` (HTTP ${entry.apiErrorStatus})` : \"\";\n return `${entry.error ?? \"API error\"}${status}`;\n}\n\n// ── Unified message normalization ───────────────────────────────────────────\n// Projects the canonical SessionUIMessage[] (captain pkg/session) into the same\n// SessionEvent rows, so the viewer renders the unified model and the legacy\n// SessionEntry log identically.\n\n/** A unified message array is told apart from a SessionEntry log by its\n * per-message `parts` array (a SessionEntry carries `message`/`tool_use`). */\nfunction looksLikeUnifiedMessages(\n arr: SessionEntry[] | SessionUIMessage[],\n): arr is SessionUIMessage[] {\n const first: unknown = arr[0];\n return (\n typeof first === \"object\" &&\n first !== null &&\n Array.isArray((first as SessionUIMessage).parts)\n );\n}\n\nfunction looksLikeUnifiedSession(\n input: SessionInput,\n): input is UnifiedSessionInput {\n return (\n typeof input === \"object\" &&\n input !== null &&\n !Array.isArray(input) &&\n (\"messages\" in input ||\n \"turns\" in input ||\n \"capabilities\" in input ||\n \"budget\" in input ||\n \"context\" in input)\n );\n}\n\nfunction isUnifiedToolPart(part: SessionUIPart): boolean {\n return (\n Boolean(part.toolName) &&\n (part.type === \"dynamic-tool\" || part.type.startsWith(\"tool-\"))\n );\n}\n\n/** Render a tool part's already-parsed JSON output as text. */\nfunction outputToText(output: unknown): string | undefined {\n if (output == null) return undefined;\n return typeof output === \"string\" ? output : JSON.stringify(output);\n}\n\nfunction asRecord(input: unknown): Record<string, unknown> | undefined {\n return typeof input === \"object\" && input !== null && !Array.isArray(input)\n ? (input as Record<string, unknown>)\n : undefined;\n}\n\nfunction partEvent(\n part: SessionUIPart,\n role: \"system\" | \"user\" | \"assistant\",\n id: string,\n meta: {\n timestamp?: string;\n cwd?: string;\n model?: string;\n reasoningEffort?: string;\n source?: string;\n turnId?: string;\n agentId?: string;\n sessionId?: string;\n raw?: unknown;\n verifyPassed?: boolean;\n },\n): SessionEvent | null {\n if (isUnifiedToolPart(part)) {\n const pending = pendingFromPart(part);\n return toolEvent(\n id,\n part.toolName as string,\n asRecord(part.input),\n outputToText(part.output),\n meta.timestamp,\n {\n ...(meta.model ? { model: meta.model } : {}),\n ...(meta.reasoningEffort\n ? { reasoningEffort: meta.reasoningEffort }\n : {}),\n ...(meta.source ? { source: meta.source } : {}),\n ...(meta.cwd ? { cwd: meta.cwd } : {}),\n ...(meta.turnId ? { turnId: meta.turnId } : {}),\n ...(meta.agentId ? { agentId: meta.agentId } : {}),\n ...(meta.sessionId ? { sessionId: meta.sessionId } : {}),\n ...(part.state ? { toolState: part.state } : {}),\n ...(part.approval ? { approval: part.approval } : {}),\n pending,\n ...(part.toolCallId ? { toolCallId: part.toolCallId } : {}),\n ...(part.approval?.id ? { approvalId: part.approval.id } : {}),\n ...(meta.raw !== undefined ? { raw: meta.raw } : {}),\n },\n );\n }\n if (part.type === \"reasoning\") {\n return part.text\n ? {\n id,\n kind: \"thinking\",\n text: part.text,\n ...(meta.timestamp ? { timestamp: meta.timestamp } : {}),\n ...(meta.turnId ? { turnId: meta.turnId } : {}),\n ...(meta.agentId ? { agentId: meta.agentId } : {}),\n ...(meta.raw !== undefined ? { raw: meta.raw } : {}),\n }\n : null;\n }\n if (part.type === \"text\") {\n return part.text\n ? {\n id,\n kind: role,\n text: part.text,\n ...(meta.timestamp ? { timestamp: meta.timestamp } : {}),\n ...(meta.turnId ? { turnId: meta.turnId } : {}),\n ...(meta.agentId ? { agentId: meta.agentId } : {}),\n ...(meta.raw !== undefined ? { raw: meta.raw } : {}),\n ...(meta.verifyPassed !== undefined\n ? {\n verifyPassed: meta.verifyPassed,\n tone: meta.verifyPassed ? \"emerald\" : \"rose\",\n icon: WORKFLOW_PHASES.verify.icon,\n }\n : {}),\n }\n : null;\n }\n return null; // file / unknown parts have no row representation\n}\n\nfunction pendingFromPart(part: SessionUIPart): boolean {\n if (part.approval?.approved !== undefined) return false;\n if (\n [\"approval-responded\", \"output-available\", \"output-denied\"].includes(\n part.state ?? \"\",\n )\n )\n return false;\n return (\n part.pending === true ||\n part.approval?.pending === true ||\n part.state === \"approval-requested\"\n );\n}\n\n/** Flatten unified session messages into ordered SessionEvent rows. */\nexport function normalizeMessages(\n messages: SessionUIMessage[],\n): SessionEvent[] {\n const events: SessionEvent[] = [];\n messages.forEach((msg, seq) => {\n const prov = msg.provenance;\n const baseId = msg.id ?? prov?.uuid ?? `m${seq}`;\n if (prov?.apiErrorStatus) {\n events.push({\n id: `${baseId}-err`,\n kind: \"error\",\n text: `API error (HTTP ${prov.apiErrorStatus})`,\n errorStatus: prov.apiErrorStatus,\n ...(prov.timestamp ? { timestamp: prov.timestamp } : {}),\n ...(msg.turnId ? { turnId: msg.turnId } : {}),\n ...(prov.agentId ? { agentId: prov.agentId } : {}),\n ...(msg.raw !== undefined ? { raw: msg.raw } : {}),\n });\n return;\n }\n // A verify step reports its verdict as a `verified`/`verify_failed` role —\n // rendered as a system-style row (not a fourth top-level kind) carrying the\n // pass/fail tone and the workflow verify glyph as data.\n const verifyPassed =\n msg.role === \"verified\" ? true : msg.role === \"verify_failed\" ? false : undefined;\n const role: \"system\" | \"user\" | \"assistant\" =\n msg.role === \"system\" || verifyPassed !== undefined\n ? \"system\"\n : msg.role === \"user\"\n ? \"user\"\n : \"assistant\";\n const meta = {\n ...(prov?.timestamp ? { timestamp: prov.timestamp } : {}),\n ...(prov?.cwd ? { cwd: prov.cwd } : {}),\n ...(prov?.model ? { model: prov.model } : {}),\n ...(prov?.reasoningEffort\n ? { reasoningEffort: prov.reasoningEffort }\n : {}),\n ...(prov?.source ? { source: prov.source } : {}),\n ...(msg.turnId ? { turnId: msg.turnId } : {}),\n ...(prov?.agentId ? { agentId: prov.agentId } : {}),\n ...(prov?.sessionId ? { sessionId: prov.sessionId } : {}),\n ...(msg.raw !== undefined ? { raw: msg.raw } : {}),\n ...(verifyPassed !== undefined ? { verifyPassed } : {}),\n };\n msg.parts.forEach((part, i) => {\n const ev = partEvent(part, role, `${baseId}-${i}`, meta);\n if (ev) events.push(ev);\n });\n });\n return events;\n}\n\n// ── Action icon registry ────────────────────────────────────────────────────\n// Implements the Flanksource \"Coding agent action icons\" design: every agent\n// tool maps to a Phosphor-derived generated icon (Ui*) and a semantic tone so a\n// scan of the log reads at a glance. Tones group by surface — file reads (sky),\n// writes (amber), edits (violet), execution (emerald), agents (indigo),\n// destructive (rose), assets (pink/fuchsia).\n\nexport type SessionTone =\n | \"sky\"\n | \"amber\"\n | \"violet\"\n | \"emerald\"\n | \"teal\"\n | \"orange\"\n | \"rose\"\n | \"indigo\"\n | \"fuchsia\"\n | \"pink\"\n | \"slate\";\n\nexport interface SessionActionMeta {\n icon: StaticIconComponent;\n tone: SessionTone;\n /** Human-readable verb shown as the row heading (and in the filter menu). */\n label: string;\n /** The row heading is the input summary alone (file path, command) — the\n * icon and tone carry the verb, so the label only appears in the menu. */\n summaryOnly?: boolean;\n}\n\nconst ACTIONS: Record<string, SessionActionMeta> = {\n // File operations. Read (eye) and Write (diff) are deliberately kept off the\n // design's file-text / file-plus glyphs — they read better in a scrolling log\n // and write-type rows also carry a +/- diff stat.\n Read: { icon: UiEye, tone: \"sky\", label: \"Read file\", summaryOnly: true },\n Write: {\n icon: UiDiff,\n tone: \"amber\",\n label: \"Write file\",\n summaryOnly: true,\n },\n Edit: {\n icon: UiPencilSimpleLine,\n tone: \"violet\",\n label: \"Edit file\",\n summaryOnly: true,\n },\n MultiEdit: {\n icon: UiStack,\n tone: \"violet\",\n label: \"Multi-edit\",\n summaryOnly: true,\n },\n NotebookEdit: {\n icon: UiPencilSimpleLine,\n tone: \"violet\",\n label: \"Edit notebook\",\n summaryOnly: true,\n },\n // Search & navigation\n Grep: { icon: UiSearch, tone: \"amber\", label: \"Grep\" },\n Glob: { icon: UiAsterisk, tone: \"sky\", label: \"Glob\" },\n // Execution & shell\n Bash: { icon: UiTerminal, tone: \"emerald\", label: \"Run command\" },\n BashOutput: { icon: UiCode2, tone: \"emerald\", label: \"Shell output\" },\n KillShell: { icon: UiProhibit, tone: \"rose\", label: \"Kill shell\" },\n KillBash: { icon: UiProhibit, tone: \"rose\", label: \"Kill shell\" },\n // Agents & planning\n Task: { icon: UiRobotAi, tone: \"indigo\", label: \"Sub-agent task\" },\n Agent: { icon: UiRobotAi, tone: \"indigo\", label: \"Sub-agent task\" },\n Skill: { icon: UiMagicWand, tone: \"fuchsia\", label: \"Invoke skill\" },\n TodoWrite: { icon: UiListChecks, tone: \"sky\", label: \"Update todos\" },\n Plan: { icon: UiStrategy, tone: \"sky\", label: \"Plan\" },\n TaskCreate: { icon: UiKanban, tone: \"sky\", label: \"Create task\" },\n TaskUpdate: { icon: UiKanban, tone: \"sky\", label: \"Update task\" },\n TaskList: { icon: UiKanban, tone: \"sky\", label: \"List tasks\" },\n TaskGet: { icon: UiKanban, tone: \"sky\", label: \"Get task\" },\n TaskOutput: { icon: UiKanban, tone: \"sky\", label: \"Task output\" },\n TaskStop: { icon: UiProhibit, tone: \"rose\", label: \"Stop task\" },\n ToolSearch: { icon: UiSearch, tone: \"amber\", label: \"Search tools\" },\n AskUserQuestion: { icon: UiQuestion, tone: \"sky\", label: \"Ask user\" },\n EnterPlanMode: { icon: UiStrategy, tone: \"sky\", label: \"Enter plan mode\" },\n ExitPlanMode: { icon: UiStrategy, tone: \"sky\", label: \"Exit plan mode\" },\n // Web & browser automation\n WebFetch: { icon: UiCloudDownload, tone: \"sky\", label: \"Fetch URL\" },\n WebSearch: { icon: UiGlobe, tone: \"sky\", label: \"Web search\" },\n browser_navigate: { icon: UiCompass, tone: \"sky\", label: \"Navigate\" },\n browser_navigate_back: {\n icon: UiCompass,\n tone: \"sky\",\n label: \"Navigate back\",\n },\n browser_click: { icon: UiCursorClick, tone: \"sky\", label: \"Click\" },\n browser_triple_click: {\n icon: UiCursorText,\n tone: \"sky\",\n label: \"Triple click\",\n },\n browser_type: { icon: UiKeyboard, tone: \"emerald\", label: \"Type text\" },\n browser_press_key: { icon: UiCommand, tone: \"amber\", label: \"Press key\" },\n browser_snapshot: { icon: UiScan, tone: \"violet\", label: \"Snapshot\" },\n browser_take_screenshot: {\n icon: UiCamera,\n tone: \"indigo\",\n label: \"Screenshot\",\n },\n browser_evaluate: { icon: UiCode2, tone: \"violet\", label: \"Evaluate JS\" },\n browser_console_messages: { icon: UiScroll, tone: \"slate\", label: \"Console\" },\n browser_network_requests: {\n icon: UiShare,\n tone: \"emerald\",\n label: \"Network\",\n },\n browser_wait_for: { icon: UiHourglass, tone: \"amber\", label: \"Wait\" },\n Wait: { icon: UiHourglass, tone: \"amber\", label: \"Wait\" },\n browser_close: { icon: UiClose, tone: \"rose\", label: \"Close browser\" },\n};\n\n// MCP tools surface as `mcp__<server>__<name>` or `<server>__<name>`. Icon\n// servers get a distinct accent (palette); generative servers reuse the sparkle;\n// the rest fall back to the puzzle piece.\nconst MCP_ICON_SERVERS = new Set([\n \"iconify\",\n \"icons8\",\n \"lucide\",\n \"react-icons\",\n]);\nconst MCP_GEN_SERVERS = new Set([\"gemini\", \"openai\", \"anthropic\"]);\n\ninterface McpTool {\n server: string;\n name: string;\n}\n\nexport function splitMcpTool(tool: string): McpTool | null {\n const rest = tool.startsWith(\"mcp__\") ? tool.slice(\"mcp__\".length) : tool;\n const idx = rest.indexOf(\"__\");\n if (idx < 0) return null;\n return { server: rest.slice(0, idx), name: rest.slice(idx + 2) };\n}\n\n/** Resolve the icon, tone, and label for a tool name. */\nexport function getSessionAction(tool: string): SessionActionMeta {\n const exact = ACTIONS[tool];\n if (exact) return exact;\n\n const mcp = splitMcpTool(tool);\n if (mcp) {\n const label = `${mcp.server}: ${mcp.name.replace(/_/g, \" \")}`;\n if (MCP_ICON_SERVERS.has(mcp.server))\n return { icon: UiPalette, tone: \"pink\", label };\n if (MCP_GEN_SERVERS.has(mcp.server))\n return { icon: UiSparkles, tone: \"violet\", label };\n return { icon: UiPuzzle, tone: \"violet\", label };\n }\n\n return { icon: UiWrench, tone: \"slate\", label: tool };\n}\n\n/** Count tool-call events, the dominant model, and totals for the header. */\nexport function summarizeSession(events: SessionEvent[]): {\n toolCount: number;\n messageCount: number;\n model?: string;\n} {\n let toolCount = 0;\n let messageCount = 0;\n const modelCounts = new Map<string, number>();\n for (const event of events) {\n if (event.kind === \"tool\") toolCount += 1;\n if (\n event.kind === \"system\" ||\n event.kind === \"user\" ||\n event.kind === \"assistant\"\n ) {\n messageCount += 1;\n }\n if (event.model)\n modelCounts.set(event.model, (modelCounts.get(event.model) ?? 0) + 1);\n }\n let model: string | undefined;\n let best = 0;\n for (const [name, count] of modelCounts) {\n if (count > best) {\n best = count;\n model = name;\n }\n }\n return { toolCount, messageCount, ...(model ? { model } : {}) };\n}\n"],"names":["WORKFLOW_PHASES","UiEye","UiDiff","UiPencilSimpleLine","UiStack","UiSearch","UiAsterisk","UiTerminal","UiCode2","UiProhibit","UiRobotAi","UiMagicWand","UiListChecks","UiStrategy","UiKanban","UiQuestion","UiCloudDownload","UiGlobe","UiCompass","UiCursorClick","UiCursorText","UiKeyboard","UiCommand","UiScan","UiCamera","UiScroll","UiShare","UiHourglass","UiClose","UiPalette","UiSparkles","UiPuzzle","UiWrench"],"mappings":"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"}
|
|
@@ -96,6 +96,14 @@ export interface SessionEvent {
|
|
|
96
96
|
raw?: unknown;
|
|
97
97
|
errorType?: string;
|
|
98
98
|
errorStatus?: number;
|
|
99
|
+
/** Set for a `verified`/`verify_failed` role — the workflow verify verdict. */
|
|
100
|
+
verifyPassed?: boolean;
|
|
101
|
+
/** Row icon override (e.g. the verify glyph). Renderers fall back to the
|
|
102
|
+
* kind's default icon when absent. */
|
|
103
|
+
icon?: StaticIconComponent;
|
|
104
|
+
/** Row tone override (e.g. pass/fail for a verify row). Renderers fall back
|
|
105
|
+
* to the kind's default tone when absent. */
|
|
106
|
+
tone?: SessionTone;
|
|
99
107
|
}
|
|
100
108
|
export declare function truncate(text: string, max: number): string;
|
|
101
109
|
/** Flatten a captain session (unified messages, entries, or raw log text) into
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SessionViewer.model.d.ts","sourceRoot":"","sources":["../../../src/data/ai/SessionViewer.model.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"SessionViewer.model.d.ts","sourceRoot":"","sources":["../../../src/data/ai/SessionViewer.model.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { WORKFLOW_PHASES } from "./agent-action-icons.js";
|
|
1
2
|
import { UiClose } from "../../icons/components/UiClose.js";
|
|
2
3
|
import { UiHourglass } from "../../icons/components/UiHourglass.js";
|
|
3
4
|
import { UiShare } from "../../icons/components/UiShare.js";
|
|
@@ -53,7 +54,7 @@ function parseEntries(input) {
|
|
|
53
54
|
});
|
|
54
55
|
}
|
|
55
56
|
function roleFromType(type) {
|
|
56
|
-
return type === "system" || type === "user" || type === "assistant" ? type : "assistant";
|
|
57
|
+
return type === "system" || type === "user" || type === "assistant" || type === "verified" || type === "verify_failed" ? type : "assistant";
|
|
57
58
|
}
|
|
58
59
|
function toolEvent(id, tool, input, response, timestamp, meta = {}) {
|
|
59
60
|
return {
|
|
@@ -78,7 +79,7 @@ function toolEvent(id, tool, input, response, timestamp, meta = {}) {
|
|
|
78
79
|
...meta.raw !== void 0 ? { raw: meta.raw } : {}
|
|
79
80
|
};
|
|
80
81
|
}
|
|
81
|
-
function blockEvent(block, role, id, timestamp, cwd) {
|
|
82
|
+
function blockEvent(block, role, id, timestamp, cwd, verifyPassed) {
|
|
82
83
|
if (block.type === "tool_use" || block.name && block.input) {
|
|
83
84
|
if (!block.name) return null;
|
|
84
85
|
return toolEvent(id, block.name, block.input, void 0, timestamp, {
|
|
@@ -93,9 +94,14 @@ function blockEvent(block, role, id, timestamp, cwd) {
|
|
|
93
94
|
if (block.text) {
|
|
94
95
|
return {
|
|
95
96
|
id,
|
|
96
|
-
kind: role === "system" ? "system" : role === "user" ? "user" : "assistant",
|
|
97
|
+
kind: role === "system" || verifyPassed !== void 0 ? "system" : role === "user" ? "user" : "assistant",
|
|
97
98
|
text: block.text,
|
|
98
|
-
...timestamp ? { timestamp } : {}
|
|
99
|
+
...timestamp ? { timestamp } : {},
|
|
100
|
+
...verifyPassed !== void 0 ? {
|
|
101
|
+
verifyPassed,
|
|
102
|
+
tone: verifyPassed ? "emerald" : "rose",
|
|
103
|
+
icon: WORKFLOW_PHASES.verify.icon
|
|
104
|
+
} : {}
|
|
99
105
|
};
|
|
100
106
|
}
|
|
101
107
|
return null;
|
|
@@ -148,13 +154,15 @@ function normalizeSession(input) {
|
|
|
148
154
|
return;
|
|
149
155
|
}
|
|
150
156
|
const role = roleFromType(((_a = entry.message) == null ? void 0 : _a.role) ?? entry.type);
|
|
157
|
+
const verifyPassed = role === "verified" ? true : role === "verify_failed" ? false : void 0;
|
|
151
158
|
for (const [i, block] of (((_b = entry.message) == null ? void 0 : _b.content) ?? []).entries()) {
|
|
152
159
|
const ev = blockEvent(
|
|
153
160
|
block,
|
|
154
161
|
role,
|
|
155
162
|
`${baseId}-${i}`,
|
|
156
163
|
entry.timestamp,
|
|
157
|
-
entry.cwd
|
|
164
|
+
entry.cwd,
|
|
165
|
+
verifyPassed
|
|
158
166
|
);
|
|
159
167
|
if (ev) events.push(ev);
|
|
160
168
|
}
|
|
@@ -246,7 +254,12 @@ function partEvent(part, role, id, meta) {
|
|
|
246
254
|
...meta.timestamp ? { timestamp: meta.timestamp } : {},
|
|
247
255
|
...meta.turnId ? { turnId: meta.turnId } : {},
|
|
248
256
|
...meta.agentId ? { agentId: meta.agentId } : {},
|
|
249
|
-
...meta.raw !== void 0 ? { raw: meta.raw } : {}
|
|
257
|
+
...meta.raw !== void 0 ? { raw: meta.raw } : {},
|
|
258
|
+
...meta.verifyPassed !== void 0 ? {
|
|
259
|
+
verifyPassed: meta.verifyPassed,
|
|
260
|
+
tone: meta.verifyPassed ? "emerald" : "rose",
|
|
261
|
+
icon: WORKFLOW_PHASES.verify.icon
|
|
262
|
+
} : {}
|
|
250
263
|
} : null;
|
|
251
264
|
}
|
|
252
265
|
return null;
|
|
@@ -278,7 +291,8 @@ function normalizeMessages(messages) {
|
|
|
278
291
|
});
|
|
279
292
|
return;
|
|
280
293
|
}
|
|
281
|
-
const
|
|
294
|
+
const verifyPassed = msg.role === "verified" ? true : msg.role === "verify_failed" ? false : void 0;
|
|
295
|
+
const role = msg.role === "system" || verifyPassed !== void 0 ? "system" : msg.role === "user" ? "user" : "assistant";
|
|
282
296
|
const meta = {
|
|
283
297
|
...(prov == null ? void 0 : prov.timestamp) ? { timestamp: prov.timestamp } : {},
|
|
284
298
|
...(prov == null ? void 0 : prov.cwd) ? { cwd: prov.cwd } : {},
|
|
@@ -288,7 +302,8 @@ function normalizeMessages(messages) {
|
|
|
288
302
|
...msg.turnId ? { turnId: msg.turnId } : {},
|
|
289
303
|
...(prov == null ? void 0 : prov.agentId) ? { agentId: prov.agentId } : {},
|
|
290
304
|
...(prov == null ? void 0 : prov.sessionId) ? { sessionId: prov.sessionId } : {},
|
|
291
|
-
...msg.raw !== void 0 ? { raw: msg.raw } : {}
|
|
305
|
+
...msg.raw !== void 0 ? { raw: msg.raw } : {},
|
|
306
|
+
...verifyPassed !== void 0 ? { verifyPassed } : {}
|
|
292
307
|
};
|
|
293
308
|
msg.parts.forEach((part, i) => {
|
|
294
309
|
const ev = partEvent(part, role, `${baseId}-${i}`, meta);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SessionViewer.model.js","sources":["../../../src/data/ai/SessionViewer.model.ts"],"sourcesContent":["import type { StaticIconComponent } from \"../Icon\";\nimport type {\n SessionBudget,\n SessionCapabilities,\n SessionContext,\n SessionCost,\n SessionMetadataEvent,\n SessionTurn,\n SessionUIMessage,\n SessionUIPart,\n SessionUsage,\n UnifiedSessionInput,\n} from \"./SessionViewer.unified\";\nimport {\n UiAsterisk,\n UiCamera,\n UiClose,\n UiCloudDownload,\n UiCode2,\n UiCommand,\n UiCompass,\n UiCursorClick,\n UiCursorText,\n UiDiff,\n UiEye,\n UiGlobe,\n UiHourglass,\n UiKanban,\n UiKeyboard,\n UiListChecks,\n UiMagicWand,\n UiPalette,\n UiPencilSimpleLine,\n UiProhibit,\n UiPuzzle,\n UiQuestion,\n UiRobotAi,\n UiScan,\n UiScroll,\n UiSearch,\n UiShare,\n UiSparkles,\n UiStack,\n UiStrategy,\n UiTerminal,\n UiWrench,\n} from \"../../icons\";\n\n// ── Captain session schema ──────────────────────────────────────────────────\n// Mirrors github.com/flanksource/captain pkg/ai/history types. A session is a\n// list of SessionEntry records (the rows of a Claude Code / Codex JSONL log).\n\nexport interface SessionToolUse {\n tool?: string;\n input?: Record<string, unknown>;\n timestamp?: string;\n cwd?: string;\n session_id?: string;\n tool_use_id?: string;\n /** \"claude\" or \"codex\". */\n source?: string;\n model?: string;\n reasoning_effort?: string;\n response?: string;\n}\n\nexport interface SessionContent {\n /** Block kind: \"text\", \"thinking\", \"tool_use\", \"tool_result\", … */\n type?: string;\n text?: string;\n thinking?: string;\n name?: string;\n input?: Record<string, unknown>;\n id?: string;\n}\n\nexport interface SessionMessage {\n role?: string;\n stop_reason?: string;\n content?: SessionContent[];\n}\n\nexport interface SessionEntry {\n /** Top-level entry kind: assistant, user, system, … */\n type?: string;\n tool_use?: SessionToolUse;\n message?: SessionMessage;\n timestamp?: string;\n cwd?: string;\n sessionId?: string;\n uuid?: string;\n /** Synthetic assistant entry Claude Code writes when an API request fails. */\n isApiErrorMessage?: boolean;\n apiErrorStatus?: number;\n /** Claude Code's error classification (e.g. \"rate_limit\"). */\n error?: string;\n}\n\n/**\n * A session to render: the unified `SessionUIMessage[]` (preferred — what\n * `GET /api/captain/sessions/{id}` serves), a legacy `SessionEntry[]` log, or\n * raw log text (JSON array or JSONL).\n */\nexport type SessionInput =\n | string\n | SessionEntry[]\n | SessionUIMessage[]\n | UnifiedSessionInput;\n\nexport interface SessionMetadataSummary {\n /** Session identifier exposed by the context meter's copy action. */\n sessionId?: string;\n /** Runtime mechanism used to execute the session. */\n executionMode?: string;\n turns?: SessionTurn[];\n capabilities?: SessionCapabilities;\n budget?: SessionBudget;\n context?: SessionContext;\n events?: SessionMetadataEvent[];\n /** Dominant model id, for the context meter's hover popover. */\n model?: string;\n /** Provider id, used to resolve the model's brand glyph. */\n provider?: string;\n /** Session reasoning effort, for the context meter's hover popover. */\n reasoningEffort?: string;\n /** Aggregate token usage, for the context meter's hover popover. */\n usage?: SessionUsage;\n /** Aggregate cost breakdown, for the context meter's hover popover. */\n cost?: SessionCost;\n}\n\n// ── Normalized events ───────────────────────────────────────────────────────\n// The raw schema interleaves consolidated `tool_use` rows with `message`\n// content blocks. normalizeSession flattens both shapes into a single ordered\n// list the viewer can render row-by-row.\n\nexport type SessionEventKind =\n | \"system\"\n | \"user\"\n | \"assistant\"\n | \"thinking\"\n | \"tool\"\n | \"error\";\n\nexport interface SessionEvent {\n id: string;\n kind: SessionEventKind;\n /** Tool name (kind === \"tool\"). */\n tool?: string;\n toolInput?: Record<string, unknown>;\n toolResponse?: string;\n /** Prose for user/assistant/thinking, or the error message for errors. */\n text?: string;\n /** Working directory the tool ran in — used to relativize file paths. */\n cwd?: string;\n timestamp?: string;\n model?: string;\n reasoningEffort?: string;\n source?: string;\n turnId?: string;\n agentId?: string;\n toolState?: string;\n approval?: SessionUIPart[\"approval\"];\n pending?: boolean;\n toolCallId?: string;\n approvalId?: string;\n sessionId?: string;\n raw?: unknown;\n errorType?: string;\n errorStatus?: number;\n}\n\nexport function truncate(text: string, max: number): string {\n return text.length <= max ? text : `${text.slice(0, max)}…`;\n}\n\n// parseEntries accepts a parsed array as-is, or parses a string as a whole-\n// document JSON (array or single object, possibly pretty-printed) first, then\n// falls back to JSONL (one object per line). The whole-document parse error is\n// caught only to attempt the JSONL fallback — a genuinely malformed JSONL line\n// throws loudly rather than being silently dropped.\nfunction parseEntries(input: string | SessionEntry[]): SessionEntry[] {\n if (Array.isArray(input)) return input;\n const text = input.trim();\n if (!text) return [];\n try {\n const parsed: unknown = JSON.parse(text);\n return Array.isArray(parsed)\n ? (parsed as SessionEntry[])\n : [parsed as SessionEntry];\n } catch {\n // not a single JSON document — treat as JSONL below\n }\n return text\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter(Boolean)\n .map((line) => {\n try {\n return JSON.parse(line) as SessionEntry;\n } catch {\n throw new Error(\n `SessionViewer: invalid session JSON line: ${truncate(line, 80)}`,\n );\n }\n });\n}\n\nfunction roleFromType(type: string | undefined): string {\n return type === \"system\" || type === \"user\" || type === \"assistant\"\n ? type\n : \"assistant\";\n}\n\nfunction toolEvent(\n id: string,\n tool: string,\n input: Record<string, unknown> | undefined,\n response: string | undefined,\n timestamp: string | undefined,\n meta: {\n model?: string;\n reasoningEffort?: string;\n source?: string;\n cwd?: string;\n turnId?: string;\n agentId?: string;\n toolState?: string;\n approval?: SessionUIPart[\"approval\"];\n pending?: boolean;\n toolCallId?: string;\n approvalId?: string;\n sessionId?: string;\n raw?: unknown;\n } = {},\n): SessionEvent {\n return {\n id,\n kind: \"tool\",\n tool,\n ...(input ? { toolInput: input } : {}),\n ...(response ? { toolResponse: response } : {}),\n ...(timestamp ? { timestamp } : {}),\n ...(meta.model ? { model: meta.model } : {}),\n ...(meta.reasoningEffort ? { reasoningEffort: meta.reasoningEffort } : {}),\n ...(meta.source ? { source: meta.source } : {}),\n ...(meta.cwd ? { cwd: meta.cwd } : {}),\n ...(meta.turnId ? { turnId: meta.turnId } : {}),\n ...(meta.agentId ? { agentId: meta.agentId } : {}),\n ...(meta.toolState ? { toolState: meta.toolState } : {}),\n ...(meta.approval ? { approval: meta.approval } : {}),\n pending: meta.pending ?? false,\n ...(meta.toolCallId ? { toolCallId: meta.toolCallId } : {}),\n ...(meta.approvalId ? { approvalId: meta.approvalId } : {}),\n ...(meta.sessionId ? { sessionId: meta.sessionId } : {}),\n ...(meta.raw !== undefined ? { raw: meta.raw } : {}),\n };\n}\n\nfunction blockEvent(\n block: SessionContent,\n role: string,\n id: string,\n timestamp: string | undefined,\n cwd: string | undefined,\n): SessionEvent | null {\n if (block.type === \"tool_use\" || (block.name && block.input)) {\n if (!block.name) return null;\n return toolEvent(id, block.name, block.input, undefined, timestamp, {\n ...(cwd ? { cwd } : {}),\n ...(block.id ? { toolCallId: block.id } : {}),\n });\n }\n if (block.type === \"thinking\" || block.thinking) {\n const text = block.thinking ?? block.text;\n return text\n ? { id, kind: \"thinking\", text, ...(timestamp ? { timestamp } : {}) }\n : null;\n }\n if (block.text) {\n return {\n id,\n kind:\n role === \"system\" ? \"system\" : role === \"user\" ? \"user\" : \"assistant\",\n text: block.text,\n ...(timestamp ? { timestamp } : {}),\n };\n }\n return null;\n}\n\n/** Flatten a captain session (unified messages, entries, or raw log text) into\n * ordered events. Unified `SessionUIMessage[]` is detected by its `parts`. */\nexport function normalizeSession(input: SessionInput): SessionEvent[] {\n if (looksLikeUnifiedSession(input)) {\n return normalizeMessages(input.messages ?? []);\n }\n if (Array.isArray(input) && looksLikeUnifiedMessages(input)) {\n return normalizeMessages(input);\n }\n const entries = parseEntries(input as string | SessionEntry[]);\n const events: SessionEvent[] = [];\n entries.forEach((entry, seq) => {\n const baseId = entry.uuid ?? `e${seq}`;\n\n if (entry.isApiErrorMessage) {\n events.push({\n id: `${baseId}-err`,\n kind: \"error\",\n text: errorMessage(entry),\n ...(entry.error ? { errorType: entry.error } : {}),\n ...(entry.apiErrorStatus ? { errorStatus: entry.apiErrorStatus } : {}),\n ...(entry.timestamp ? { timestamp: entry.timestamp } : {}),\n raw: entry,\n });\n return;\n }\n\n const tu = entry.tool_use;\n if (tu?.tool) {\n const cwd = tu.cwd ?? entry.cwd;\n events.push(\n toolEvent(\n `${baseId}-tool`,\n tu.tool,\n tu.input,\n tu.response,\n tu.timestamp ?? entry.timestamp,\n {\n ...(tu.model ? { model: tu.model } : {}),\n ...(tu.reasoning_effort\n ? { reasoningEffort: tu.reasoning_effort }\n : {}),\n ...(tu.source ? { source: tu.source } : {}),\n ...(cwd ? { cwd } : {}),\n ...(tu.tool_use_id ? { toolCallId: tu.tool_use_id } : {}),\n ...(tu.session_id ? { sessionId: tu.session_id } : {}),\n raw: entry,\n },\n ),\n );\n return;\n }\n\n const role = roleFromType(entry.message?.role ?? entry.type);\n for (const [i, block] of (entry.message?.content ?? []).entries()) {\n const ev = blockEvent(\n block,\n role,\n `${baseId}-${i}`,\n entry.timestamp,\n entry.cwd,\n );\n if (ev) events.push(ev);\n }\n });\n return events;\n}\n\nexport function getSessionMetadata(\n input: SessionInput,\n): SessionMetadataSummary | undefined {\n if (!looksLikeUnifiedSession(input)) return undefined;\n const metadata: SessionMetadataSummary = {\n ...(input.id ? { sessionId: input.id } : {}),\n ...(input.executionMode ? { executionMode: input.executionMode } : {}),\n ...(input.turns ? { turns: input.turns } : {}),\n ...(input.capabilities ? { capabilities: input.capabilities } : {}),\n ...(input.budget ? { budget: input.budget } : {}),\n ...(input.context ? { context: input.context } : {}),\n ...(input.events ? { events: input.events } : {}),\n ...(input.model ? { model: input.model } : {}),\n ...(input.provider ? { provider: input.provider } : {}),\n ...(input.reasoningEffort\n ? { reasoningEffort: input.reasoningEffort }\n : {}),\n ...(input.usage ? { usage: input.usage } : {}),\n ...(input.cost ? { cost: input.cost } : {}),\n };\n return Object.keys(metadata).length > 0 ? metadata : undefined;\n}\n\nfunction errorMessage(entry: SessionEntry): string {\n const status = entry.apiErrorStatus ? ` (HTTP ${entry.apiErrorStatus})` : \"\";\n return `${entry.error ?? \"API error\"}${status}`;\n}\n\n// ── Unified message normalization ───────────────────────────────────────────\n// Projects the canonical SessionUIMessage[] (captain pkg/session) into the same\n// SessionEvent rows, so the viewer renders the unified model and the legacy\n// SessionEntry log identically.\n\n/** A unified message array is told apart from a SessionEntry log by its\n * per-message `parts` array (a SessionEntry carries `message`/`tool_use`). */\nfunction looksLikeUnifiedMessages(\n arr: SessionEntry[] | SessionUIMessage[],\n): arr is SessionUIMessage[] {\n const first: unknown = arr[0];\n return (\n typeof first === \"object\" &&\n first !== null &&\n Array.isArray((first as SessionUIMessage).parts)\n );\n}\n\nfunction looksLikeUnifiedSession(\n input: SessionInput,\n): input is UnifiedSessionInput {\n return (\n typeof input === \"object\" &&\n input !== null &&\n !Array.isArray(input) &&\n (\"messages\" in input ||\n \"turns\" in input ||\n \"capabilities\" in input ||\n \"budget\" in input ||\n \"context\" in input)\n );\n}\n\nfunction isUnifiedToolPart(part: SessionUIPart): boolean {\n return (\n Boolean(part.toolName) &&\n (part.type === \"dynamic-tool\" || part.type.startsWith(\"tool-\"))\n );\n}\n\n/** Render a tool part's already-parsed JSON output as text. */\nfunction outputToText(output: unknown): string | undefined {\n if (output == null) return undefined;\n return typeof output === \"string\" ? output : JSON.stringify(output);\n}\n\nfunction asRecord(input: unknown): Record<string, unknown> | undefined {\n return typeof input === \"object\" && input !== null && !Array.isArray(input)\n ? (input as Record<string, unknown>)\n : undefined;\n}\n\nfunction partEvent(\n part: SessionUIPart,\n role: \"system\" | \"user\" | \"assistant\",\n id: string,\n meta: {\n timestamp?: string;\n cwd?: string;\n model?: string;\n reasoningEffort?: string;\n source?: string;\n turnId?: string;\n agentId?: string;\n sessionId?: string;\n raw?: unknown;\n },\n): SessionEvent | null {\n if (isUnifiedToolPart(part)) {\n const pending = pendingFromPart(part);\n return toolEvent(\n id,\n part.toolName as string,\n asRecord(part.input),\n outputToText(part.output),\n meta.timestamp,\n {\n ...(meta.model ? { model: meta.model } : {}),\n ...(meta.reasoningEffort\n ? { reasoningEffort: meta.reasoningEffort }\n : {}),\n ...(meta.source ? { source: meta.source } : {}),\n ...(meta.cwd ? { cwd: meta.cwd } : {}),\n ...(meta.turnId ? { turnId: meta.turnId } : {}),\n ...(meta.agentId ? { agentId: meta.agentId } : {}),\n ...(meta.sessionId ? { sessionId: meta.sessionId } : {}),\n ...(part.state ? { toolState: part.state } : {}),\n ...(part.approval ? { approval: part.approval } : {}),\n pending,\n ...(part.toolCallId ? { toolCallId: part.toolCallId } : {}),\n ...(part.approval?.id ? { approvalId: part.approval.id } : {}),\n ...(meta.raw !== undefined ? { raw: meta.raw } : {}),\n },\n );\n }\n if (part.type === \"reasoning\") {\n return part.text\n ? {\n id,\n kind: \"thinking\",\n text: part.text,\n ...(meta.timestamp ? { timestamp: meta.timestamp } : {}),\n ...(meta.turnId ? { turnId: meta.turnId } : {}),\n ...(meta.agentId ? { agentId: meta.agentId } : {}),\n ...(meta.raw !== undefined ? { raw: meta.raw } : {}),\n }\n : null;\n }\n if (part.type === \"text\") {\n return part.text\n ? {\n id,\n kind: role,\n text: part.text,\n ...(meta.timestamp ? { timestamp: meta.timestamp } : {}),\n ...(meta.turnId ? { turnId: meta.turnId } : {}),\n ...(meta.agentId ? { agentId: meta.agentId } : {}),\n ...(meta.raw !== undefined ? { raw: meta.raw } : {}),\n }\n : null;\n }\n return null; // file / unknown parts have no row representation\n}\n\nfunction pendingFromPart(part: SessionUIPart): boolean {\n if (part.approval?.approved !== undefined) return false;\n if (\n [\"approval-responded\", \"output-available\", \"output-denied\"].includes(\n part.state ?? \"\",\n )\n )\n return false;\n return (\n part.pending === true ||\n part.approval?.pending === true ||\n part.state === \"approval-requested\"\n );\n}\n\n/** Flatten unified session messages into ordered SessionEvent rows. */\nexport function normalizeMessages(\n messages: SessionUIMessage[],\n): SessionEvent[] {\n const events: SessionEvent[] = [];\n messages.forEach((msg, seq) => {\n const prov = msg.provenance;\n const baseId = msg.id ?? prov?.uuid ?? `m${seq}`;\n if (prov?.apiErrorStatus) {\n events.push({\n id: `${baseId}-err`,\n kind: \"error\",\n text: `API error (HTTP ${prov.apiErrorStatus})`,\n errorStatus: prov.apiErrorStatus,\n ...(prov.timestamp ? { timestamp: prov.timestamp } : {}),\n ...(msg.turnId ? { turnId: msg.turnId } : {}),\n ...(prov.agentId ? { agentId: prov.agentId } : {}),\n ...(msg.raw !== undefined ? { raw: msg.raw } : {}),\n });\n return;\n }\n const role: \"system\" | \"user\" | \"assistant\" =\n msg.role === \"system\"\n ? \"system\"\n : msg.role === \"user\"\n ? \"user\"\n : \"assistant\";\n const meta = {\n ...(prov?.timestamp ? { timestamp: prov.timestamp } : {}),\n ...(prov?.cwd ? { cwd: prov.cwd } : {}),\n ...(prov?.model ? { model: prov.model } : {}),\n ...(prov?.reasoningEffort\n ? { reasoningEffort: prov.reasoningEffort }\n : {}),\n ...(prov?.source ? { source: prov.source } : {}),\n ...(msg.turnId ? { turnId: msg.turnId } : {}),\n ...(prov?.agentId ? { agentId: prov.agentId } : {}),\n ...(prov?.sessionId ? { sessionId: prov.sessionId } : {}),\n ...(msg.raw !== undefined ? { raw: msg.raw } : {}),\n };\n msg.parts.forEach((part, i) => {\n const ev = partEvent(part, role, `${baseId}-${i}`, meta);\n if (ev) events.push(ev);\n });\n });\n return events;\n}\n\n// ── Action icon registry ────────────────────────────────────────────────────\n// Implements the Flanksource \"Coding agent action icons\" design: every agent\n// tool maps to a Phosphor-derived generated icon (Ui*) and a semantic tone so a\n// scan of the log reads at a glance. Tones group by surface — file reads (sky),\n// writes (amber), edits (violet), execution (emerald), agents (indigo),\n// destructive (rose), assets (pink/fuchsia).\n\nexport type SessionTone =\n | \"sky\"\n | \"amber\"\n | \"violet\"\n | \"emerald\"\n | \"teal\"\n | \"orange\"\n | \"rose\"\n | \"indigo\"\n | \"fuchsia\"\n | \"pink\"\n | \"slate\";\n\nexport interface SessionActionMeta {\n icon: StaticIconComponent;\n tone: SessionTone;\n /** Human-readable verb shown as the row heading (and in the filter menu). */\n label: string;\n /** The row heading is the input summary alone (file path, command) — the\n * icon and tone carry the verb, so the label only appears in the menu. */\n summaryOnly?: boolean;\n}\n\nconst ACTIONS: Record<string, SessionActionMeta> = {\n // File operations. Read (eye) and Write (diff) are deliberately kept off the\n // design's file-text / file-plus glyphs — they read better in a scrolling log\n // and write-type rows also carry a +/- diff stat.\n Read: { icon: UiEye, tone: \"sky\", label: \"Read file\", summaryOnly: true },\n Write: {\n icon: UiDiff,\n tone: \"amber\",\n label: \"Write file\",\n summaryOnly: true,\n },\n Edit: {\n icon: UiPencilSimpleLine,\n tone: \"violet\",\n label: \"Edit file\",\n summaryOnly: true,\n },\n MultiEdit: {\n icon: UiStack,\n tone: \"violet\",\n label: \"Multi-edit\",\n summaryOnly: true,\n },\n NotebookEdit: {\n icon: UiPencilSimpleLine,\n tone: \"violet\",\n label: \"Edit notebook\",\n summaryOnly: true,\n },\n // Search & navigation\n Grep: { icon: UiSearch, tone: \"amber\", label: \"Grep\" },\n Glob: { icon: UiAsterisk, tone: \"sky\", label: \"Glob\" },\n // Execution & shell\n Bash: { icon: UiTerminal, tone: \"emerald\", label: \"Run command\" },\n BashOutput: { icon: UiCode2, tone: \"emerald\", label: \"Shell output\" },\n KillShell: { icon: UiProhibit, tone: \"rose\", label: \"Kill shell\" },\n KillBash: { icon: UiProhibit, tone: \"rose\", label: \"Kill shell\" },\n // Agents & planning\n Task: { icon: UiRobotAi, tone: \"indigo\", label: \"Sub-agent task\" },\n Agent: { icon: UiRobotAi, tone: \"indigo\", label: \"Sub-agent task\" },\n Skill: { icon: UiMagicWand, tone: \"fuchsia\", label: \"Invoke skill\" },\n TodoWrite: { icon: UiListChecks, tone: \"sky\", label: \"Update todos\" },\n Plan: { icon: UiStrategy, tone: \"sky\", label: \"Plan\" },\n TaskCreate: { icon: UiKanban, tone: \"sky\", label: \"Create task\" },\n TaskUpdate: { icon: UiKanban, tone: \"sky\", label: \"Update task\" },\n TaskList: { icon: UiKanban, tone: \"sky\", label: \"List tasks\" },\n TaskGet: { icon: UiKanban, tone: \"sky\", label: \"Get task\" },\n TaskOutput: { icon: UiKanban, tone: \"sky\", label: \"Task output\" },\n TaskStop: { icon: UiProhibit, tone: \"rose\", label: \"Stop task\" },\n ToolSearch: { icon: UiSearch, tone: \"amber\", label: \"Search tools\" },\n AskUserQuestion: { icon: UiQuestion, tone: \"sky\", label: \"Ask user\" },\n EnterPlanMode: { icon: UiStrategy, tone: \"sky\", label: \"Enter plan mode\" },\n ExitPlanMode: { icon: UiStrategy, tone: \"sky\", label: \"Exit plan mode\" },\n // Web & browser automation\n WebFetch: { icon: UiCloudDownload, tone: \"sky\", label: \"Fetch URL\" },\n WebSearch: { icon: UiGlobe, tone: \"sky\", label: \"Web search\" },\n browser_navigate: { icon: UiCompass, tone: \"sky\", label: \"Navigate\" },\n browser_navigate_back: {\n icon: UiCompass,\n tone: \"sky\",\n label: \"Navigate back\",\n },\n browser_click: { icon: UiCursorClick, tone: \"sky\", label: \"Click\" },\n browser_triple_click: {\n icon: UiCursorText,\n tone: \"sky\",\n label: \"Triple click\",\n },\n browser_type: { icon: UiKeyboard, tone: \"emerald\", label: \"Type text\" },\n browser_press_key: { icon: UiCommand, tone: \"amber\", label: \"Press key\" },\n browser_snapshot: { icon: UiScan, tone: \"violet\", label: \"Snapshot\" },\n browser_take_screenshot: {\n icon: UiCamera,\n tone: \"indigo\",\n label: \"Screenshot\",\n },\n browser_evaluate: { icon: UiCode2, tone: \"violet\", label: \"Evaluate JS\" },\n browser_console_messages: { icon: UiScroll, tone: \"slate\", label: \"Console\" },\n browser_network_requests: {\n icon: UiShare,\n tone: \"emerald\",\n label: \"Network\",\n },\n browser_wait_for: { icon: UiHourglass, tone: \"amber\", label: \"Wait\" },\n Wait: { icon: UiHourglass, tone: \"amber\", label: \"Wait\" },\n browser_close: { icon: UiClose, tone: \"rose\", label: \"Close browser\" },\n};\n\n// MCP tools surface as `mcp__<server>__<name>` or `<server>__<name>`. Icon\n// servers get a distinct accent (palette); generative servers reuse the sparkle;\n// the rest fall back to the puzzle piece.\nconst MCP_ICON_SERVERS = new Set([\n \"iconify\",\n \"icons8\",\n \"lucide\",\n \"react-icons\",\n]);\nconst MCP_GEN_SERVERS = new Set([\"gemini\", \"openai\", \"anthropic\"]);\n\ninterface McpTool {\n server: string;\n name: string;\n}\n\nexport function splitMcpTool(tool: string): McpTool | null {\n const rest = tool.startsWith(\"mcp__\") ? tool.slice(\"mcp__\".length) : tool;\n const idx = rest.indexOf(\"__\");\n if (idx < 0) return null;\n return { server: rest.slice(0, idx), name: rest.slice(idx + 2) };\n}\n\n/** Resolve the icon, tone, and label for a tool name. */\nexport function getSessionAction(tool: string): SessionActionMeta {\n const exact = ACTIONS[tool];\n if (exact) return exact;\n\n const mcp = splitMcpTool(tool);\n if (mcp) {\n const label = `${mcp.server}: ${mcp.name.replace(/_/g, \" \")}`;\n if (MCP_ICON_SERVERS.has(mcp.server))\n return { icon: UiPalette, tone: \"pink\", label };\n if (MCP_GEN_SERVERS.has(mcp.server))\n return { icon: UiSparkles, tone: \"violet\", label };\n return { icon: UiPuzzle, tone: \"violet\", label };\n }\n\n return { icon: UiWrench, tone: \"slate\", label: tool };\n}\n\n/** Count tool-call events, the dominant model, and totals for the header. */\nexport function summarizeSession(events: SessionEvent[]): {\n toolCount: number;\n messageCount: number;\n model?: string;\n} {\n let toolCount = 0;\n let messageCount = 0;\n const modelCounts = new Map<string, number>();\n for (const event of events) {\n if (event.kind === \"tool\") toolCount += 1;\n if (\n event.kind === \"system\" ||\n event.kind === \"user\" ||\n event.kind === \"assistant\"\n ) {\n messageCount += 1;\n }\n if (event.model)\n modelCounts.set(event.model, (modelCounts.get(event.model) ?? 0) + 1);\n }\n let model: string | undefined;\n let best = 0;\n for (const [name, count] of modelCounts) {\n if (count > best) {\n best = count;\n model = name;\n }\n }\n return { toolCount, messageCount, ...(model ? { model } : {}) };\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SessionViewer.model.js","sources":["../../../src/data/ai/SessionViewer.model.ts"],"sourcesContent":["import type { StaticIconComponent } from \"../Icon\";\nimport { WORKFLOW_PHASES } from \"./agent-action-icons\";\nimport type {\n SessionBudget,\n SessionCapabilities,\n SessionContext,\n SessionCost,\n SessionMetadataEvent,\n SessionTurn,\n SessionUIMessage,\n SessionUIPart,\n SessionUsage,\n UnifiedSessionInput,\n} from \"./SessionViewer.unified\";\nimport {\n UiAsterisk,\n UiCamera,\n UiClose,\n UiCloudDownload,\n UiCode2,\n UiCommand,\n UiCompass,\n UiCursorClick,\n UiCursorText,\n UiDiff,\n UiEye,\n UiGlobe,\n UiHourglass,\n UiKanban,\n UiKeyboard,\n UiListChecks,\n UiMagicWand,\n UiPalette,\n UiPencilSimpleLine,\n UiProhibit,\n UiPuzzle,\n UiQuestion,\n UiRobotAi,\n UiScan,\n UiScroll,\n UiSearch,\n UiShare,\n UiSparkles,\n UiStack,\n UiStrategy,\n UiTerminal,\n UiWrench,\n} from \"../../icons\";\n\n// ── Captain session schema ──────────────────────────────────────────────────\n// Mirrors github.com/flanksource/captain pkg/ai/history types. A session is a\n// list of SessionEntry records (the rows of a Claude Code / Codex JSONL log).\n\nexport interface SessionToolUse {\n tool?: string;\n input?: Record<string, unknown>;\n timestamp?: string;\n cwd?: string;\n session_id?: string;\n tool_use_id?: string;\n /** \"claude\" or \"codex\". */\n source?: string;\n model?: string;\n reasoning_effort?: string;\n response?: string;\n}\n\nexport interface SessionContent {\n /** Block kind: \"text\", \"thinking\", \"tool_use\", \"tool_result\", … */\n type?: string;\n text?: string;\n thinking?: string;\n name?: string;\n input?: Record<string, unknown>;\n id?: string;\n}\n\nexport interface SessionMessage {\n role?: string;\n stop_reason?: string;\n content?: SessionContent[];\n}\n\nexport interface SessionEntry {\n /** Top-level entry kind: assistant, user, system, … */\n type?: string;\n tool_use?: SessionToolUse;\n message?: SessionMessage;\n timestamp?: string;\n cwd?: string;\n sessionId?: string;\n uuid?: string;\n /** Synthetic assistant entry Claude Code writes when an API request fails. */\n isApiErrorMessage?: boolean;\n apiErrorStatus?: number;\n /** Claude Code's error classification (e.g. \"rate_limit\"). */\n error?: string;\n}\n\n/**\n * A session to render: the unified `SessionUIMessage[]` (preferred — what\n * `GET /api/captain/sessions/{id}` serves), a legacy `SessionEntry[]` log, or\n * raw log text (JSON array or JSONL).\n */\nexport type SessionInput =\n | string\n | SessionEntry[]\n | SessionUIMessage[]\n | UnifiedSessionInput;\n\nexport interface SessionMetadataSummary {\n /** Session identifier exposed by the context meter's copy action. */\n sessionId?: string;\n /** Runtime mechanism used to execute the session. */\n executionMode?: string;\n turns?: SessionTurn[];\n capabilities?: SessionCapabilities;\n budget?: SessionBudget;\n context?: SessionContext;\n events?: SessionMetadataEvent[];\n /** Dominant model id, for the context meter's hover popover. */\n model?: string;\n /** Provider id, used to resolve the model's brand glyph. */\n provider?: string;\n /** Session reasoning effort, for the context meter's hover popover. */\n reasoningEffort?: string;\n /** Aggregate token usage, for the context meter's hover popover. */\n usage?: SessionUsage;\n /** Aggregate cost breakdown, for the context meter's hover popover. */\n cost?: SessionCost;\n}\n\n// ── Normalized events ───────────────────────────────────────────────────────\n// The raw schema interleaves consolidated `tool_use` rows with `message`\n// content blocks. normalizeSession flattens both shapes into a single ordered\n// list the viewer can render row-by-row.\n\nexport type SessionEventKind =\n | \"system\"\n | \"user\"\n | \"assistant\"\n | \"thinking\"\n | \"tool\"\n | \"error\";\n\nexport interface SessionEvent {\n id: string;\n kind: SessionEventKind;\n /** Tool name (kind === \"tool\"). */\n tool?: string;\n toolInput?: Record<string, unknown>;\n toolResponse?: string;\n /** Prose for user/assistant/thinking, or the error message for errors. */\n text?: string;\n /** Working directory the tool ran in — used to relativize file paths. */\n cwd?: string;\n timestamp?: string;\n model?: string;\n reasoningEffort?: string;\n source?: string;\n turnId?: string;\n agentId?: string;\n toolState?: string;\n approval?: SessionUIPart[\"approval\"];\n pending?: boolean;\n toolCallId?: string;\n approvalId?: string;\n sessionId?: string;\n raw?: unknown;\n errorType?: string;\n errorStatus?: number;\n /** Set for a `verified`/`verify_failed` role — the workflow verify verdict. */\n verifyPassed?: boolean;\n /** Row icon override (e.g. the verify glyph). Renderers fall back to the\n * kind's default icon when absent. */\n icon?: StaticIconComponent;\n /** Row tone override (e.g. pass/fail for a verify row). Renderers fall back\n * to the kind's default tone when absent. */\n tone?: SessionTone;\n}\n\nexport function truncate(text: string, max: number): string {\n return text.length <= max ? text : `${text.slice(0, max)}…`;\n}\n\n// parseEntries accepts a parsed array as-is, or parses a string as a whole-\n// document JSON (array or single object, possibly pretty-printed) first, then\n// falls back to JSONL (one object per line). The whole-document parse error is\n// caught only to attempt the JSONL fallback — a genuinely malformed JSONL line\n// throws loudly rather than being silently dropped.\nfunction parseEntries(input: string | SessionEntry[]): SessionEntry[] {\n if (Array.isArray(input)) return input;\n const text = input.trim();\n if (!text) return [];\n try {\n const parsed: unknown = JSON.parse(text);\n return Array.isArray(parsed)\n ? (parsed as SessionEntry[])\n : [parsed as SessionEntry];\n } catch {\n // not a single JSON document — treat as JSONL below\n }\n return text\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter(Boolean)\n .map((line) => {\n try {\n return JSON.parse(line) as SessionEntry;\n } catch {\n throw new Error(\n `SessionViewer: invalid session JSON line: ${truncate(line, 80)}`,\n );\n }\n });\n}\n\n// \"verified\"/\"verify_failed\" pass through unchanged — the legacy SessionEntry\n// path needs the raw role to route to the same verify row `normalizeMessages`\n// builds for the unified path (see the call site below), not just a\n// system/user/assistant kind.\nfunction roleFromType(type: string | undefined): string {\n return type === \"system\" ||\n type === \"user\" ||\n type === \"assistant\" ||\n type === \"verified\" ||\n type === \"verify_failed\"\n ? type\n : \"assistant\";\n}\n\nfunction toolEvent(\n id: string,\n tool: string,\n input: Record<string, unknown> | undefined,\n response: string | undefined,\n timestamp: string | undefined,\n meta: {\n model?: string;\n reasoningEffort?: string;\n source?: string;\n cwd?: string;\n turnId?: string;\n agentId?: string;\n toolState?: string;\n approval?: SessionUIPart[\"approval\"];\n pending?: boolean;\n toolCallId?: string;\n approvalId?: string;\n sessionId?: string;\n raw?: unknown;\n } = {},\n): SessionEvent {\n return {\n id,\n kind: \"tool\",\n tool,\n ...(input ? { toolInput: input } : {}),\n ...(response ? { toolResponse: response } : {}),\n ...(timestamp ? { timestamp } : {}),\n ...(meta.model ? { model: meta.model } : {}),\n ...(meta.reasoningEffort ? { reasoningEffort: meta.reasoningEffort } : {}),\n ...(meta.source ? { source: meta.source } : {}),\n ...(meta.cwd ? { cwd: meta.cwd } : {}),\n ...(meta.turnId ? { turnId: meta.turnId } : {}),\n ...(meta.agentId ? { agentId: meta.agentId } : {}),\n ...(meta.toolState ? { toolState: meta.toolState } : {}),\n ...(meta.approval ? { approval: meta.approval } : {}),\n pending: meta.pending ?? false,\n ...(meta.toolCallId ? { toolCallId: meta.toolCallId } : {}),\n ...(meta.approvalId ? { approvalId: meta.approvalId } : {}),\n ...(meta.sessionId ? { sessionId: meta.sessionId } : {}),\n ...(meta.raw !== undefined ? { raw: meta.raw } : {}),\n };\n}\n\nfunction blockEvent(\n block: SessionContent,\n role: string,\n id: string,\n timestamp: string | undefined,\n cwd: string | undefined,\n verifyPassed: boolean | undefined,\n): SessionEvent | null {\n if (block.type === \"tool_use\" || (block.name && block.input)) {\n if (!block.name) return null;\n return toolEvent(id, block.name, block.input, undefined, timestamp, {\n ...(cwd ? { cwd } : {}),\n ...(block.id ? { toolCallId: block.id } : {}),\n });\n }\n if (block.type === \"thinking\" || block.thinking) {\n const text = block.thinking ?? block.text;\n return text\n ? { id, kind: \"thinking\", text, ...(timestamp ? { timestamp } : {}) }\n : null;\n }\n if (block.text) {\n // A verify step reports its verdict as a `verified`/`verify_failed` role —\n // rendered as a system-style row carrying the pass/fail tone and the\n // workflow verify glyph, mirroring `normalizeMessages`'s unified-path rows.\n return {\n id,\n kind:\n role === \"system\" || verifyPassed !== undefined\n ? \"system\"\n : role === \"user\"\n ? \"user\"\n : \"assistant\",\n text: block.text,\n ...(timestamp ? { timestamp } : {}),\n ...(verifyPassed !== undefined\n ? {\n verifyPassed,\n tone: verifyPassed ? \"emerald\" : \"rose\",\n icon: WORKFLOW_PHASES.verify.icon,\n }\n : {}),\n };\n }\n return null;\n}\n\n/** Flatten a captain session (unified messages, entries, or raw log text) into\n * ordered events. Unified `SessionUIMessage[]` is detected by its `parts`. */\nexport function normalizeSession(input: SessionInput): SessionEvent[] {\n if (looksLikeUnifiedSession(input)) {\n return normalizeMessages(input.messages ?? []);\n }\n if (Array.isArray(input) && looksLikeUnifiedMessages(input)) {\n return normalizeMessages(input);\n }\n const entries = parseEntries(input as string | SessionEntry[]);\n const events: SessionEvent[] = [];\n entries.forEach((entry, seq) => {\n const baseId = entry.uuid ?? `e${seq}`;\n\n if (entry.isApiErrorMessage) {\n events.push({\n id: `${baseId}-err`,\n kind: \"error\",\n text: errorMessage(entry),\n ...(entry.error ? { errorType: entry.error } : {}),\n ...(entry.apiErrorStatus ? { errorStatus: entry.apiErrorStatus } : {}),\n ...(entry.timestamp ? { timestamp: entry.timestamp } : {}),\n raw: entry,\n });\n return;\n }\n\n const tu = entry.tool_use;\n if (tu?.tool) {\n const cwd = tu.cwd ?? entry.cwd;\n events.push(\n toolEvent(\n `${baseId}-tool`,\n tu.tool,\n tu.input,\n tu.response,\n tu.timestamp ?? entry.timestamp,\n {\n ...(tu.model ? { model: tu.model } : {}),\n ...(tu.reasoning_effort\n ? { reasoningEffort: tu.reasoning_effort }\n : {}),\n ...(tu.source ? { source: tu.source } : {}),\n ...(cwd ? { cwd } : {}),\n ...(tu.tool_use_id ? { toolCallId: tu.tool_use_id } : {}),\n ...(tu.session_id ? { sessionId: tu.session_id } : {}),\n raw: entry,\n },\n ),\n );\n return;\n }\n\n const role = roleFromType(entry.message?.role ?? entry.type);\n const verifyPassed =\n role === \"verified\" ? true : role === \"verify_failed\" ? false : undefined;\n for (const [i, block] of (entry.message?.content ?? []).entries()) {\n const ev = blockEvent(\n block,\n role,\n `${baseId}-${i}`,\n entry.timestamp,\n entry.cwd,\n verifyPassed,\n );\n if (ev) events.push(ev);\n }\n });\n return events;\n}\n\nexport function getSessionMetadata(\n input: SessionInput,\n): SessionMetadataSummary | undefined {\n if (!looksLikeUnifiedSession(input)) return undefined;\n const metadata: SessionMetadataSummary = {\n ...(input.id ? { sessionId: input.id } : {}),\n ...(input.executionMode ? { executionMode: input.executionMode } : {}),\n ...(input.turns ? { turns: input.turns } : {}),\n ...(input.capabilities ? { capabilities: input.capabilities } : {}),\n ...(input.budget ? { budget: input.budget } : {}),\n ...(input.context ? { context: input.context } : {}),\n ...(input.events ? { events: input.events } : {}),\n ...(input.model ? { model: input.model } : {}),\n ...(input.provider ? { provider: input.provider } : {}),\n ...(input.reasoningEffort\n ? { reasoningEffort: input.reasoningEffort }\n : {}),\n ...(input.usage ? { usage: input.usage } : {}),\n ...(input.cost ? { cost: input.cost } : {}),\n };\n return Object.keys(metadata).length > 0 ? metadata : undefined;\n}\n\nfunction errorMessage(entry: SessionEntry): string {\n const status = entry.apiErrorStatus ? ` (HTTP ${entry.apiErrorStatus})` : \"\";\n return `${entry.error ?? \"API error\"}${status}`;\n}\n\n// ── Unified message normalization ───────────────────────────────────────────\n// Projects the canonical SessionUIMessage[] (captain pkg/session) into the same\n// SessionEvent rows, so the viewer renders the unified model and the legacy\n// SessionEntry log identically.\n\n/** A unified message array is told apart from a SessionEntry log by its\n * per-message `parts` array (a SessionEntry carries `message`/`tool_use`). */\nfunction looksLikeUnifiedMessages(\n arr: SessionEntry[] | SessionUIMessage[],\n): arr is SessionUIMessage[] {\n const first: unknown = arr[0];\n return (\n typeof first === \"object\" &&\n first !== null &&\n Array.isArray((first as SessionUIMessage).parts)\n );\n}\n\nfunction looksLikeUnifiedSession(\n input: SessionInput,\n): input is UnifiedSessionInput {\n return (\n typeof input === \"object\" &&\n input !== null &&\n !Array.isArray(input) &&\n (\"messages\" in input ||\n \"turns\" in input ||\n \"capabilities\" in input ||\n \"budget\" in input ||\n \"context\" in input)\n );\n}\n\nfunction isUnifiedToolPart(part: SessionUIPart): boolean {\n return (\n Boolean(part.toolName) &&\n (part.type === \"dynamic-tool\" || part.type.startsWith(\"tool-\"))\n );\n}\n\n/** Render a tool part's already-parsed JSON output as text. */\nfunction outputToText(output: unknown): string | undefined {\n if (output == null) return undefined;\n return typeof output === \"string\" ? output : JSON.stringify(output);\n}\n\nfunction asRecord(input: unknown): Record<string, unknown> | undefined {\n return typeof input === \"object\" && input !== null && !Array.isArray(input)\n ? (input as Record<string, unknown>)\n : undefined;\n}\n\nfunction partEvent(\n part: SessionUIPart,\n role: \"system\" | \"user\" | \"assistant\",\n id: string,\n meta: {\n timestamp?: string;\n cwd?: string;\n model?: string;\n reasoningEffort?: string;\n source?: string;\n turnId?: string;\n agentId?: string;\n sessionId?: string;\n raw?: unknown;\n verifyPassed?: boolean;\n },\n): SessionEvent | null {\n if (isUnifiedToolPart(part)) {\n const pending = pendingFromPart(part);\n return toolEvent(\n id,\n part.toolName as string,\n asRecord(part.input),\n outputToText(part.output),\n meta.timestamp,\n {\n ...(meta.model ? { model: meta.model } : {}),\n ...(meta.reasoningEffort\n ? { reasoningEffort: meta.reasoningEffort }\n : {}),\n ...(meta.source ? { source: meta.source } : {}),\n ...(meta.cwd ? { cwd: meta.cwd } : {}),\n ...(meta.turnId ? { turnId: meta.turnId } : {}),\n ...(meta.agentId ? { agentId: meta.agentId } : {}),\n ...(meta.sessionId ? { sessionId: meta.sessionId } : {}),\n ...(part.state ? { toolState: part.state } : {}),\n ...(part.approval ? { approval: part.approval } : {}),\n pending,\n ...(part.toolCallId ? { toolCallId: part.toolCallId } : {}),\n ...(part.approval?.id ? { approvalId: part.approval.id } : {}),\n ...(meta.raw !== undefined ? { raw: meta.raw } : {}),\n },\n );\n }\n if (part.type === \"reasoning\") {\n return part.text\n ? {\n id,\n kind: \"thinking\",\n text: part.text,\n ...(meta.timestamp ? { timestamp: meta.timestamp } : {}),\n ...(meta.turnId ? { turnId: meta.turnId } : {}),\n ...(meta.agentId ? { agentId: meta.agentId } : {}),\n ...(meta.raw !== undefined ? { raw: meta.raw } : {}),\n }\n : null;\n }\n if (part.type === \"text\") {\n return part.text\n ? {\n id,\n kind: role,\n text: part.text,\n ...(meta.timestamp ? { timestamp: meta.timestamp } : {}),\n ...(meta.turnId ? { turnId: meta.turnId } : {}),\n ...(meta.agentId ? { agentId: meta.agentId } : {}),\n ...(meta.raw !== undefined ? { raw: meta.raw } : {}),\n ...(meta.verifyPassed !== undefined\n ? {\n verifyPassed: meta.verifyPassed,\n tone: meta.verifyPassed ? \"emerald\" : \"rose\",\n icon: WORKFLOW_PHASES.verify.icon,\n }\n : {}),\n }\n : null;\n }\n return null; // file / unknown parts have no row representation\n}\n\nfunction pendingFromPart(part: SessionUIPart): boolean {\n if (part.approval?.approved !== undefined) return false;\n if (\n [\"approval-responded\", \"output-available\", \"output-denied\"].includes(\n part.state ?? \"\",\n )\n )\n return false;\n return (\n part.pending === true ||\n part.approval?.pending === true ||\n part.state === \"approval-requested\"\n );\n}\n\n/** Flatten unified session messages into ordered SessionEvent rows. */\nexport function normalizeMessages(\n messages: SessionUIMessage[],\n): SessionEvent[] {\n const events: SessionEvent[] = [];\n messages.forEach((msg, seq) => {\n const prov = msg.provenance;\n const baseId = msg.id ?? prov?.uuid ?? `m${seq}`;\n if (prov?.apiErrorStatus) {\n events.push({\n id: `${baseId}-err`,\n kind: \"error\",\n text: `API error (HTTP ${prov.apiErrorStatus})`,\n errorStatus: prov.apiErrorStatus,\n ...(prov.timestamp ? { timestamp: prov.timestamp } : {}),\n ...(msg.turnId ? { turnId: msg.turnId } : {}),\n ...(prov.agentId ? { agentId: prov.agentId } : {}),\n ...(msg.raw !== undefined ? { raw: msg.raw } : {}),\n });\n return;\n }\n // A verify step reports its verdict as a `verified`/`verify_failed` role —\n // rendered as a system-style row (not a fourth top-level kind) carrying the\n // pass/fail tone and the workflow verify glyph as data.\n const verifyPassed =\n msg.role === \"verified\" ? true : msg.role === \"verify_failed\" ? false : undefined;\n const role: \"system\" | \"user\" | \"assistant\" =\n msg.role === \"system\" || verifyPassed !== undefined\n ? \"system\"\n : msg.role === \"user\"\n ? \"user\"\n : \"assistant\";\n const meta = {\n ...(prov?.timestamp ? { timestamp: prov.timestamp } : {}),\n ...(prov?.cwd ? { cwd: prov.cwd } : {}),\n ...(prov?.model ? { model: prov.model } : {}),\n ...(prov?.reasoningEffort\n ? { reasoningEffort: prov.reasoningEffort }\n : {}),\n ...(prov?.source ? { source: prov.source } : {}),\n ...(msg.turnId ? { turnId: msg.turnId } : {}),\n ...(prov?.agentId ? { agentId: prov.agentId } : {}),\n ...(prov?.sessionId ? { sessionId: prov.sessionId } : {}),\n ...(msg.raw !== undefined ? { raw: msg.raw } : {}),\n ...(verifyPassed !== undefined ? { verifyPassed } : {}),\n };\n msg.parts.forEach((part, i) => {\n const ev = partEvent(part, role, `${baseId}-${i}`, meta);\n if (ev) events.push(ev);\n });\n });\n return events;\n}\n\n// ── Action icon registry ────────────────────────────────────────────────────\n// Implements the Flanksource \"Coding agent action icons\" design: every agent\n// tool maps to a Phosphor-derived generated icon (Ui*) and a semantic tone so a\n// scan of the log reads at a glance. Tones group by surface — file reads (sky),\n// writes (amber), edits (violet), execution (emerald), agents (indigo),\n// destructive (rose), assets (pink/fuchsia).\n\nexport type SessionTone =\n | \"sky\"\n | \"amber\"\n | \"violet\"\n | \"emerald\"\n | \"teal\"\n | \"orange\"\n | \"rose\"\n | \"indigo\"\n | \"fuchsia\"\n | \"pink\"\n | \"slate\";\n\nexport interface SessionActionMeta {\n icon: StaticIconComponent;\n tone: SessionTone;\n /** Human-readable verb shown as the row heading (and in the filter menu). */\n label: string;\n /** The row heading is the input summary alone (file path, command) — the\n * icon and tone carry the verb, so the label only appears in the menu. */\n summaryOnly?: boolean;\n}\n\nconst ACTIONS: Record<string, SessionActionMeta> = {\n // File operations. Read (eye) and Write (diff) are deliberately kept off the\n // design's file-text / file-plus glyphs — they read better in a scrolling log\n // and write-type rows also carry a +/- diff stat.\n Read: { icon: UiEye, tone: \"sky\", label: \"Read file\", summaryOnly: true },\n Write: {\n icon: UiDiff,\n tone: \"amber\",\n label: \"Write file\",\n summaryOnly: true,\n },\n Edit: {\n icon: UiPencilSimpleLine,\n tone: \"violet\",\n label: \"Edit file\",\n summaryOnly: true,\n },\n MultiEdit: {\n icon: UiStack,\n tone: \"violet\",\n label: \"Multi-edit\",\n summaryOnly: true,\n },\n NotebookEdit: {\n icon: UiPencilSimpleLine,\n tone: \"violet\",\n label: \"Edit notebook\",\n summaryOnly: true,\n },\n // Search & navigation\n Grep: { icon: UiSearch, tone: \"amber\", label: \"Grep\" },\n Glob: { icon: UiAsterisk, tone: \"sky\", label: \"Glob\" },\n // Execution & shell\n Bash: { icon: UiTerminal, tone: \"emerald\", label: \"Run command\" },\n BashOutput: { icon: UiCode2, tone: \"emerald\", label: \"Shell output\" },\n KillShell: { icon: UiProhibit, tone: \"rose\", label: \"Kill shell\" },\n KillBash: { icon: UiProhibit, tone: \"rose\", label: \"Kill shell\" },\n // Agents & planning\n Task: { icon: UiRobotAi, tone: \"indigo\", label: \"Sub-agent task\" },\n Agent: { icon: UiRobotAi, tone: \"indigo\", label: \"Sub-agent task\" },\n Skill: { icon: UiMagicWand, tone: \"fuchsia\", label: \"Invoke skill\" },\n TodoWrite: { icon: UiListChecks, tone: \"sky\", label: \"Update todos\" },\n Plan: { icon: UiStrategy, tone: \"sky\", label: \"Plan\" },\n TaskCreate: { icon: UiKanban, tone: \"sky\", label: \"Create task\" },\n TaskUpdate: { icon: UiKanban, tone: \"sky\", label: \"Update task\" },\n TaskList: { icon: UiKanban, tone: \"sky\", label: \"List tasks\" },\n TaskGet: { icon: UiKanban, tone: \"sky\", label: \"Get task\" },\n TaskOutput: { icon: UiKanban, tone: \"sky\", label: \"Task output\" },\n TaskStop: { icon: UiProhibit, tone: \"rose\", label: \"Stop task\" },\n ToolSearch: { icon: UiSearch, tone: \"amber\", label: \"Search tools\" },\n AskUserQuestion: { icon: UiQuestion, tone: \"sky\", label: \"Ask user\" },\n EnterPlanMode: { icon: UiStrategy, tone: \"sky\", label: \"Enter plan mode\" },\n ExitPlanMode: { icon: UiStrategy, tone: \"sky\", label: \"Exit plan mode\" },\n // Web & browser automation\n WebFetch: { icon: UiCloudDownload, tone: \"sky\", label: \"Fetch URL\" },\n WebSearch: { icon: UiGlobe, tone: \"sky\", label: \"Web search\" },\n browser_navigate: { icon: UiCompass, tone: \"sky\", label: \"Navigate\" },\n browser_navigate_back: {\n icon: UiCompass,\n tone: \"sky\",\n label: \"Navigate back\",\n },\n browser_click: { icon: UiCursorClick, tone: \"sky\", label: \"Click\" },\n browser_triple_click: {\n icon: UiCursorText,\n tone: \"sky\",\n label: \"Triple click\",\n },\n browser_type: { icon: UiKeyboard, tone: \"emerald\", label: \"Type text\" },\n browser_press_key: { icon: UiCommand, tone: \"amber\", label: \"Press key\" },\n browser_snapshot: { icon: UiScan, tone: \"violet\", label: \"Snapshot\" },\n browser_take_screenshot: {\n icon: UiCamera,\n tone: \"indigo\",\n label: \"Screenshot\",\n },\n browser_evaluate: { icon: UiCode2, tone: \"violet\", label: \"Evaluate JS\" },\n browser_console_messages: { icon: UiScroll, tone: \"slate\", label: \"Console\" },\n browser_network_requests: {\n icon: UiShare,\n tone: \"emerald\",\n label: \"Network\",\n },\n browser_wait_for: { icon: UiHourglass, tone: \"amber\", label: \"Wait\" },\n Wait: { icon: UiHourglass, tone: \"amber\", label: \"Wait\" },\n browser_close: { icon: UiClose, tone: \"rose\", label: \"Close browser\" },\n};\n\n// MCP tools surface as `mcp__<server>__<name>` or `<server>__<name>`. Icon\n// servers get a distinct accent (palette); generative servers reuse the sparkle;\n// the rest fall back to the puzzle piece.\nconst MCP_ICON_SERVERS = new Set([\n \"iconify\",\n \"icons8\",\n \"lucide\",\n \"react-icons\",\n]);\nconst MCP_GEN_SERVERS = new Set([\"gemini\", \"openai\", \"anthropic\"]);\n\ninterface McpTool {\n server: string;\n name: string;\n}\n\nexport function splitMcpTool(tool: string): McpTool | null {\n const rest = tool.startsWith(\"mcp__\") ? tool.slice(\"mcp__\".length) : tool;\n const idx = rest.indexOf(\"__\");\n if (idx < 0) return null;\n return { server: rest.slice(0, idx), name: rest.slice(idx + 2) };\n}\n\n/** Resolve the icon, tone, and label for a tool name. */\nexport function getSessionAction(tool: string): SessionActionMeta {\n const exact = ACTIONS[tool];\n if (exact) return exact;\n\n const mcp = splitMcpTool(tool);\n if (mcp) {\n const label = `${mcp.server}: ${mcp.name.replace(/_/g, \" \")}`;\n if (MCP_ICON_SERVERS.has(mcp.server))\n return { icon: UiPalette, tone: \"pink\", label };\n if (MCP_GEN_SERVERS.has(mcp.server))\n return { icon: UiSparkles, tone: \"violet\", label };\n return { icon: UiPuzzle, tone: \"violet\", label };\n }\n\n return { icon: UiWrench, tone: \"slate\", label: tool };\n}\n\n/** Count tool-call events, the dominant model, and totals for the header. */\nexport function summarizeSession(events: SessionEvent[]): {\n toolCount: number;\n messageCount: number;\n model?: string;\n} {\n let toolCount = 0;\n let messageCount = 0;\n const modelCounts = new Map<string, number>();\n for (const event of events) {\n if (event.kind === \"tool\") toolCount += 1;\n if (\n event.kind === \"system\" ||\n event.kind === \"user\" ||\n event.kind === \"assistant\"\n ) {\n messageCount += 1;\n }\n if (event.model)\n modelCounts.set(event.model, (modelCounts.get(event.model) ?? 0) + 1);\n }\n let model: string | undefined;\n let best = 0;\n for (const [name, count] of modelCounts) {\n if (count > best) {\n best = count;\n model = name;\n }\n }\n return { toolCount, messageCount, ...(model ? { model } : {}) };\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -200,7 +200,7 @@ function UserRow({
|
|
|
200
200
|
}
|
|
201
201
|
);
|
|
202
202
|
}
|
|
203
|
-
function
|
|
203
|
+
function baseEventVisual(event) {
|
|
204
204
|
switch (event.kind) {
|
|
205
205
|
case "tool": {
|
|
206
206
|
const action = SessionViewer_model.getSessionAction(event.tool ?? "");
|
|
@@ -248,6 +248,14 @@ function eventVisual(event) {
|
|
|
248
248
|
};
|
|
249
249
|
}
|
|
250
250
|
}
|
|
251
|
+
function eventVisual(event) {
|
|
252
|
+
const base = baseEventVisual(event);
|
|
253
|
+
return {
|
|
254
|
+
...base,
|
|
255
|
+
icon: event.icon ?? base.icon,
|
|
256
|
+
tone: event.tone ?? base.tone
|
|
257
|
+
};
|
|
258
|
+
}
|
|
251
259
|
function EventBody({
|
|
252
260
|
event,
|
|
253
261
|
visual,
|