@flanksource/clicky-ui 0.3.44 → 0.3.45
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/README.md +2 -0
- package/dist/ai.cjs +4 -2
- package/dist/ai.cjs.map +1 -1
- package/dist/ai.js +3 -1
- package/dist/components/MdxEditorField.cjs +40 -22
- package/dist/components/MdxEditorField.cjs.map +1 -1
- package/dist/components/MdxEditorField.d.ts.map +1 -1
- package/dist/components/MdxEditorField.js +41 -23
- package/dist/components/MdxEditorField.js.map +1 -1
- package/dist/components/json-schema-form-item-summary.cjs +6 -1
- package/dist/components/json-schema-form-item-summary.cjs.map +1 -1
- package/dist/components/json-schema-form-item-summary.d.ts.map +1 -1
- package/dist/components/json-schema-form-item-summary.js +6 -1
- package/dist/components/json-schema-form-item-summary.js.map +1 -1
- package/dist/data/CodeBlock.cjs +3 -2
- package/dist/data/CodeBlock.cjs.map +1 -1
- package/dist/data/CodeBlock.d.ts +3 -1
- package/dist/data/CodeBlock.d.ts.map +1 -1
- package/dist/data/CodeBlock.js +3 -2
- package/dist/data/CodeBlock.js.map +1 -1
- package/dist/data/GraphDiagram.cjs +18 -6
- package/dist/data/GraphDiagram.cjs.map +1 -1
- package/dist/data/GraphDiagram.d.ts +9 -1
- package/dist/data/GraphDiagram.d.ts.map +1 -1
- package/dist/data/GraphDiagram.js +18 -6
- package/dist/data/GraphDiagram.js.map +1 -1
- package/dist/data/GraphDiagramNodes.cjs +38 -29
- package/dist/data/GraphDiagramNodes.cjs.map +1 -1
- package/dist/data/GraphDiagramNodes.d.ts +8 -2
- package/dist/data/GraphDiagramNodes.d.ts.map +1 -1
- package/dist/data/GraphDiagramNodes.js +38 -29
- package/dist/data/GraphDiagramNodes.js.map +1 -1
- package/dist/data/JsonView.cjs +118 -49
- package/dist/data/JsonView.cjs.map +1 -1
- package/dist/data/JsonView.d.ts +13 -10
- package/dist/data/JsonView.d.ts.map +1 -1
- package/dist/data/JsonView.js +118 -49
- package/dist/data/JsonView.js.map +1 -1
- package/dist/data/MarkdownEditor.cjs +2 -2
- package/dist/data/MarkdownEditor.cjs.map +1 -1
- package/dist/data/MarkdownEditor.js +2 -2
- package/dist/data/MarkdownEditor.js.map +1 -1
- package/dist/data/ai/AdvancedChatConfig.cjs +90 -249
- package/dist/data/ai/AdvancedChatConfig.cjs.map +1 -1
- package/dist/data/ai/AdvancedChatConfig.d.ts +2 -5
- package/dist/data/ai/AdvancedChatConfig.d.ts.map +1 -1
- package/dist/data/ai/AdvancedChatConfig.js +91 -250
- package/dist/data/ai/AdvancedChatConfig.js.map +1 -1
- package/dist/data/ai/ChatButton.cjs +2 -0
- package/dist/data/ai/ChatButton.cjs.map +1 -1
- package/dist/data/ai/ChatButton.d.ts +1 -1
- package/dist/data/ai/ChatButton.d.ts.map +1 -1
- package/dist/data/ai/ChatButton.js +2 -0
- package/dist/data/ai/ChatButton.js.map +1 -1
- package/dist/data/ai/ChatFab.cjs +5 -1
- package/dist/data/ai/ChatFab.cjs.map +1 -1
- package/dist/data/ai/ChatFab.d.ts +5 -1
- package/dist/data/ai/ChatFab.d.ts.map +1 -1
- package/dist/data/ai/ChatFab.js +5 -1
- package/dist/data/ai/ChatFab.js.map +1 -1
- package/dist/data/ai/ChatWindow.cjs +2 -8
- package/dist/data/ai/ChatWindow.cjs.map +1 -1
- package/dist/data/ai/ChatWindow.d.ts.map +1 -1
- package/dist/data/ai/ChatWindow.js +2 -8
- package/dist/data/ai/ChatWindow.js.map +1 -1
- package/dist/data/ai/ChatWindow.runtime.cjs +0 -5
- package/dist/data/ai/ChatWindow.runtime.cjs.map +1 -1
- package/dist/data/ai/ChatWindow.runtime.d.ts +0 -2
- package/dist/data/ai/ChatWindow.runtime.d.ts.map +1 -1
- package/dist/data/ai/ChatWindow.runtime.js +0 -5
- package/dist/data/ai/ChatWindow.runtime.js.map +1 -1
- package/dist/data/ai/PromptRunEditor/runtimeActions.cjs +2 -2
- package/dist/data/ai/PromptRunEditor/runtimeActions.cjs.map +1 -1
- package/dist/data/ai/PromptRunEditor/runtimeActions.d.ts.map +1 -1
- package/dist/data/ai/PromptRunEditor/runtimeActions.js +2 -2
- package/dist/data/ai/PromptRunEditor/runtimeActions.js.map +1 -1
- package/dist/data/ai/SessionInspector.approvals.cjs +3 -6
- package/dist/data/ai/SessionInspector.approvals.cjs.map +1 -1
- package/dist/data/ai/SessionInspector.approvals.js +3 -6
- package/dist/data/ai/SessionInspector.approvals.js.map +1 -1
- package/dist/data/ai/SessionViewer.cjs +13 -4
- package/dist/data/ai/SessionViewer.cjs.map +1 -1
- package/dist/data/ai/SessionViewer.d.ts +5 -1
- package/dist/data/ai/SessionViewer.d.ts.map +1 -1
- package/dist/data/ai/SessionViewer.header.cjs +1 -1
- package/dist/data/ai/SessionViewer.header.cjs.map +1 -1
- package/dist/data/ai/SessionViewer.header.js +1 -1
- package/dist/data/ai/SessionViewer.header.js.map +1 -1
- package/dist/data/ai/SessionViewer.js +13 -4
- package/dist/data/ai/SessionViewer.js.map +1 -1
- package/dist/data/ai/SessionViewer.model.cjs +2 -0
- package/dist/data/ai/SessionViewer.model.cjs.map +1 -1
- package/dist/data/ai/SessionViewer.model.d.ts +1 -0
- package/dist/data/ai/SessionViewer.model.d.ts.map +1 -1
- package/dist/data/ai/SessionViewer.model.js +2 -0
- package/dist/data/ai/SessionViewer.model.js.map +1 -1
- package/dist/data/ai/SessionViewer.rows.cjs +41 -27
- package/dist/data/ai/SessionViewer.rows.cjs.map +1 -1
- package/dist/data/ai/SessionViewer.rows.d.ts +4 -2
- package/dist/data/ai/SessionViewer.rows.d.ts.map +1 -1
- package/dist/data/ai/SessionViewer.rows.js +41 -27
- package/dist/data/ai/SessionViewer.rows.js.map +1 -1
- package/dist/data/ai/SessionViewer.tokens.cjs +35 -0
- package/dist/data/ai/SessionViewer.tokens.cjs.map +1 -0
- package/dist/data/ai/SessionViewer.tokens.d.ts +5 -0
- package/dist/data/ai/SessionViewer.tokens.d.ts.map +1 -0
- package/dist/data/ai/SessionViewer.tokens.js +35 -0
- package/dist/data/ai/SessionViewer.tokens.js.map +1 -0
- package/dist/data/ai/SessionViewer.tool-cost.cjs +128 -0
- package/dist/data/ai/SessionViewer.tool-cost.cjs.map +1 -0
- package/dist/data/ai/SessionViewer.tool-cost.d.ts +6 -0
- package/dist/data/ai/SessionViewer.tool-cost.d.ts.map +1 -0
- package/dist/data/ai/SessionViewer.tool-cost.js +128 -0
- package/dist/data/ai/SessionViewer.tool-cost.js.map +1 -0
- package/dist/data/ai/SessionViewer.tool-details.cjs +3 -1
- package/dist/data/ai/SessionViewer.tool-details.cjs.map +1 -1
- package/dist/data/ai/SessionViewer.tool-details.d.ts.map +1 -1
- package/dist/data/ai/SessionViewer.tool-details.js +3 -1
- package/dist/data/ai/SessionViewer.tool-details.js.map +1 -1
- package/dist/data/ai/SessionViewer.tool-row.cjs +55 -35
- package/dist/data/ai/SessionViewer.tool-row.cjs.map +1 -1
- package/dist/data/ai/SessionViewer.tool-row.d.ts +2 -1
- package/dist/data/ai/SessionViewer.tool-row.d.ts.map +1 -1
- package/dist/data/ai/SessionViewer.tool-row.js +55 -35
- package/dist/data/ai/SessionViewer.tool-row.js.map +1 -1
- package/dist/data/ai/SessionViewer.unified.d.ts +4 -0
- package/dist/data/ai/SessionViewer.unified.d.ts.map +1 -1
- package/dist/data/ai/SessionViewerMenu.cjs +18 -1
- package/dist/data/ai/SessionViewerMenu.cjs.map +1 -1
- package/dist/data/ai/SessionViewerMenu.d.ts +6 -1
- package/dist/data/ai/SessionViewerMenu.d.ts.map +1 -1
- package/dist/data/ai/SessionViewerMenu.js +18 -1
- package/dist/data/ai/SessionViewerMenu.js.map +1 -1
- package/dist/data/ai/ToolPreferences.cjs +149 -143
- package/dist/data/ai/ToolPreferences.cjs.map +1 -1
- package/dist/data/ai/ToolPreferences.d.ts +20 -6
- package/dist/data/ai/ToolPreferences.d.ts.map +1 -1
- package/dist/data/ai/ToolPreferences.js +151 -146
- package/dist/data/ai/ToolPreferences.js.map +1 -1
- package/dist/data/ai/ToolPreferences.model.cjs +14 -10
- package/dist/data/ai/ToolPreferences.model.cjs.map +1 -1
- package/dist/data/ai/ToolPreferences.model.d.ts +1 -0
- package/dist/data/ai/ToolPreferences.model.d.ts.map +1 -1
- package/dist/data/ai/ToolPreferences.model.js +15 -11
- package/dist/data/ai/ToolPreferences.model.js.map +1 -1
- package/dist/data/ai/ToolPreferencesList.cjs +1 -0
- package/dist/data/ai/ToolPreferencesList.cjs.map +1 -1
- package/dist/data/ai/ToolPreferencesList.d.ts +4 -1
- package/dist/data/ai/ToolPreferencesList.d.ts.map +1 -1
- package/dist/data/ai/ToolPreferencesList.js +2 -1
- package/dist/data/ai/ToolPreferencesList.js.map +1 -1
- package/dist/data/ai/ToolSchemaBrowser.cjs +52 -53
- package/dist/data/ai/ToolSchemaBrowser.cjs.map +1 -1
- package/dist/data/ai/ToolSchemaBrowser.d.ts +6 -3
- package/dist/data/ai/ToolSchemaBrowser.d.ts.map +1 -1
- package/dist/data/ai/ToolSchemaBrowser.directory-header.cjs +9 -13
- package/dist/data/ai/ToolSchemaBrowser.directory-header.cjs.map +1 -1
- package/dist/data/ai/ToolSchemaBrowser.directory-header.d.ts +5 -2
- package/dist/data/ai/ToolSchemaBrowser.directory-header.d.ts.map +1 -1
- package/dist/data/ai/ToolSchemaBrowser.directory-header.js +9 -13
- package/dist/data/ai/ToolSchemaBrowser.directory-header.js.map +1 -1
- package/dist/data/ai/ToolSchemaBrowser.js +53 -54
- package/dist/data/ai/ToolSchemaBrowser.js.map +1 -1
- package/dist/data/ai/ToolSchemaBrowser.model.cjs +19 -27
- package/dist/data/ai/ToolSchemaBrowser.model.cjs.map +1 -1
- package/dist/data/ai/ToolSchemaBrowser.model.d.ts +9 -6
- package/dist/data/ai/ToolSchemaBrowser.model.d.ts.map +1 -1
- package/dist/data/ai/ToolSchemaBrowser.model.js +20 -28
- package/dist/data/ai/ToolSchemaBrowser.model.js.map +1 -1
- package/dist/data/ai/ToolSchemaBrowser.sidebar.cjs +12 -213
- package/dist/data/ai/ToolSchemaBrowser.sidebar.cjs.map +1 -1
- package/dist/data/ai/ToolSchemaBrowser.sidebar.d.ts +1 -3
- package/dist/data/ai/ToolSchemaBrowser.sidebar.d.ts.map +1 -1
- package/dist/data/ai/ToolSchemaBrowser.sidebar.js +13 -214
- package/dist/data/ai/ToolSchemaBrowser.sidebar.js.map +1 -1
- package/dist/data/ai/ToolSchemaBrowser.strategies.cjs +54 -0
- package/dist/data/ai/ToolSchemaBrowser.strategies.cjs.map +1 -0
- package/dist/data/ai/ToolSchemaBrowser.strategies.d.ts +9 -0
- package/dist/data/ai/ToolSchemaBrowser.strategies.d.ts.map +1 -0
- package/dist/data/ai/ToolSchemaBrowser.strategies.js +54 -0
- package/dist/data/ai/ToolSchemaBrowser.strategies.js.map +1 -0
- package/dist/data/ai/ToolSchemaBrowser.tree.cjs +179 -0
- package/dist/data/ai/ToolSchemaBrowser.tree.cjs.map +1 -0
- package/dist/data/ai/ToolSchemaBrowser.tree.d.ts +20 -0
- package/dist/data/ai/ToolSchemaBrowser.tree.d.ts.map +1 -0
- package/dist/data/ai/ToolSchemaBrowser.tree.js +179 -0
- package/dist/data/ai/ToolSchemaBrowser.tree.js.map +1 -0
- package/dist/data/ai/index.d.ts +2 -2
- package/dist/data/ai/index.d.ts.map +1 -1
- package/dist/data/ai/runtime-profiles/PermissionStrategiesEditor.cjs +8 -28
- package/dist/data/ai/runtime-profiles/PermissionStrategiesEditor.cjs.map +1 -1
- package/dist/data/ai/runtime-profiles/PermissionStrategiesEditor.d.ts.map +1 -1
- package/dist/data/ai/runtime-profiles/PermissionStrategiesEditor.js +9 -29
- package/dist/data/ai/runtime-profiles/PermissionStrategiesEditor.js.map +1 -1
- package/dist/data/ai/session-token-sizing.d.ts +32 -0
- package/dist/data/ai/session-token-sizing.d.ts.map +1 -0
- package/dist/data/ai/use-session-token-sizing.cjs +73 -0
- package/dist/data/ai/use-session-token-sizing.cjs.map +1 -0
- package/dist/data/ai/use-session-token-sizing.d.ts +21 -0
- package/dist/data/ai/use-session-token-sizing.d.ts.map +1 -0
- package/dist/data/ai/use-session-token-sizing.js +73 -0
- package/dist/data/ai/use-session-token-sizing.js.map +1 -0
- package/dist/data/call-graph/CallGraph.cjs +250 -0
- package/dist/data/call-graph/CallGraph.cjs.map +1 -0
- package/dist/data/call-graph/CallGraph.d.ts +69 -0
- package/dist/data/call-graph/CallGraph.d.ts.map +1 -0
- package/dist/data/call-graph/CallGraph.js +250 -0
- package/dist/data/call-graph/CallGraph.js.map +1 -0
- package/dist/data/call-graph/CallGraphGlyphs.cjs +39 -0
- package/dist/data/call-graph/CallGraphGlyphs.cjs.map +1 -0
- package/dist/data/call-graph/CallGraphGlyphs.d.ts +19 -0
- package/dist/data/call-graph/CallGraphGlyphs.d.ts.map +1 -0
- package/dist/data/call-graph/CallGraphGlyphs.js +39 -0
- package/dist/data/call-graph/CallGraphGlyphs.js.map +1 -0
- package/dist/data/call-graph/CallGraphMembers.cjs +50 -0
- package/dist/data/call-graph/CallGraphMembers.cjs.map +1 -0
- package/dist/data/call-graph/CallGraphMembers.d.ts +22 -0
- package/dist/data/call-graph/CallGraphMembers.d.ts.map +1 -0
- package/dist/data/call-graph/CallGraphMembers.js +50 -0
- package/dist/data/call-graph/CallGraphMembers.js.map +1 -0
- package/dist/data/call-graph/CallGraphParts.cjs +204 -0
- package/dist/data/call-graph/CallGraphParts.cjs.map +1 -0
- package/dist/data/call-graph/CallGraphParts.d.ts +44 -0
- package/dist/data/call-graph/CallGraphParts.d.ts.map +1 -0
- package/dist/data/call-graph/CallGraphParts.js +204 -0
- package/dist/data/call-graph/CallGraphParts.js.map +1 -0
- package/dist/data/call-graph/CallGraphToolbar.cjs +186 -0
- package/dist/data/call-graph/CallGraphToolbar.cjs.map +1 -0
- package/dist/data/call-graph/CallGraphToolbar.d.ts +45 -0
- package/dist/data/call-graph/CallGraphToolbar.d.ts.map +1 -0
- package/dist/data/call-graph/CallGraphToolbar.js +186 -0
- package/dist/data/call-graph/CallGraphToolbar.js.map +1 -0
- package/dist/data/call-graph/call-graph-exclude.cjs +75 -0
- package/dist/data/call-graph/call-graph-exclude.cjs.map +1 -0
- package/dist/data/call-graph/call-graph-exclude.d.ts +31 -0
- package/dist/data/call-graph/call-graph-exclude.d.ts.map +1 -0
- package/dist/data/call-graph/call-graph-exclude.js +75 -0
- package/dist/data/call-graph/call-graph-exclude.js.map +1 -0
- package/dist/data/call-graph/call-graph-labels.cjs +96 -0
- package/dist/data/call-graph/call-graph-labels.cjs.map +1 -0
- package/dist/data/call-graph/call-graph-labels.d.ts +53 -0
- package/dist/data/call-graph/call-graph-labels.d.ts.map +1 -0
- package/dist/data/call-graph/call-graph-labels.js +96 -0
- package/dist/data/call-graph/call-graph-labels.js.map +1 -0
- package/dist/data/call-graph/call-graph-model.cjs +161 -0
- package/dist/data/call-graph/call-graph-model.cjs.map +1 -0
- package/dist/data/call-graph/call-graph-model.d.ts +102 -0
- package/dist/data/call-graph/call-graph-model.d.ts.map +1 -0
- package/dist/data/call-graph/call-graph-model.js +161 -0
- package/dist/data/call-graph/call-graph-model.js.map +1 -0
- package/dist/data/call-graph/call-graph-vocabulary.cjs +177 -0
- package/dist/data/call-graph/call-graph-vocabulary.cjs.map +1 -0
- package/dist/data/call-graph/call-graph-vocabulary.d.ts +72 -0
- package/dist/data/call-graph/call-graph-vocabulary.d.ts.map +1 -0
- package/dist/data/call-graph/call-graph-vocabulary.js +177 -0
- package/dist/data/call-graph/call-graph-vocabulary.js.map +1 -0
- package/dist/data/call-graph/call-graph.fixtures.d.ts +63 -0
- package/dist/data/call-graph/call-graph.fixtures.d.ts.map +1 -0
- package/dist/data/call-graph/index.d.ts +7 -0
- package/dist/data/call-graph/index.d.ts.map +1 -0
- package/dist/data/call-graph/types.cjs +5 -0
- package/dist/data/call-graph/types.cjs.map +1 -0
- package/dist/data/call-graph/types.d.ts +135 -0
- package/dist/data/call-graph/types.d.ts.map +1 -0
- package/dist/data/call-graph/types.js +5 -0
- package/dist/data/call-graph/types.js.map +1 -0
- package/dist/data/call-graph/use-call-graph.cjs +93 -0
- package/dist/data/call-graph/use-call-graph.cjs.map +1 -0
- package/dist/data/call-graph/use-call-graph.d.ts +24 -0
- package/dist/data/call-graph/use-call-graph.d.ts.map +1 -0
- package/dist/data/call-graph/use-call-graph.js +93 -0
- package/dist/data/call-graph/use-call-graph.js.map +1 -0
- package/dist/data/chat/Chat.cjs +39 -15
- package/dist/data/chat/Chat.cjs.map +1 -1
- package/dist/data/chat/Chat.d.ts.map +1 -1
- package/dist/data/chat/Chat.fixtures.cjs +2 -2
- package/dist/data/chat/Chat.fixtures.cjs.map +1 -1
- package/dist/data/chat/Chat.fixtures.js +2 -2
- package/dist/data/chat/Chat.fixtures.js.map +1 -1
- package/dist/data/chat/Chat.js +40 -16
- package/dist/data/chat/Chat.js.map +1 -1
- package/dist/data/chat/ChatRuntimeToolbar.cjs +3 -6
- package/dist/data/chat/ChatRuntimeToolbar.cjs.map +1 -1
- package/dist/data/chat/ChatRuntimeToolbar.d.ts.map +1 -1
- package/dist/data/chat/ChatRuntimeToolbar.js +3 -6
- package/dist/data/chat/ChatRuntimeToolbar.js.map +1 -1
- package/dist/data/chat/ContextMeter.bar.cjs +5 -8
- package/dist/data/chat/ContextMeter.bar.cjs.map +1 -1
- package/dist/data/chat/ContextMeter.bar.d.ts +1 -1
- package/dist/data/chat/ContextMeter.bar.d.ts.map +1 -1
- package/dist/data/chat/ContextMeter.bar.js +5 -8
- package/dist/data/chat/ContextMeter.bar.js.map +1 -1
- package/dist/data/chat/ContextMeter.cjs +18 -19
- package/dist/data/chat/ContextMeter.cjs.map +1 -1
- package/dist/data/chat/ContextMeter.d.ts +1 -1
- package/dist/data/chat/ContextMeter.d.ts.map +1 -1
- package/dist/data/chat/ContextMeter.js +18 -19
- package/dist/data/chat/ContextMeter.js.map +1 -1
- package/dist/data/chat/Conversation.cjs +2 -1
- package/dist/data/chat/Conversation.cjs.map +1 -1
- package/dist/data/chat/Conversation.d.ts +4 -1
- package/dist/data/chat/Conversation.d.ts.map +1 -1
- package/dist/data/chat/Conversation.js +2 -1
- package/dist/data/chat/Conversation.js.map +1 -1
- package/dist/data/chat/Message.cjs +39 -12
- package/dist/data/chat/Message.cjs.map +1 -1
- package/dist/data/chat/Message.d.ts +1 -1
- package/dist/data/chat/Message.d.ts.map +1 -1
- package/dist/data/chat/Message.js +40 -13
- package/dist/data/chat/Message.js.map +1 -1
- package/dist/data/chat/ToolCall.cjs +60 -5
- package/dist/data/chat/ToolCall.cjs.map +1 -1
- package/dist/data/chat/ToolCall.d.ts +7 -2
- package/dist/data/chat/ToolCall.d.ts.map +1 -1
- package/dist/data/chat/ToolCall.js +60 -5
- package/dist/data/chat/ToolCall.js.map +1 -1
- package/dist/data/chat/approval.cjs.map +1 -1
- package/dist/data/chat/approval.d.ts +2 -2
- package/dist/data/chat/approval.d.ts.map +1 -1
- package/dist/data/chat/approval.js.map +1 -1
- package/dist/data/chat/tool-policy.cjs +59 -2
- package/dist/data/chat/tool-policy.cjs.map +1 -1
- package/dist/data/chat/tool-policy.d.ts +9 -0
- package/dist/data/chat/tool-policy.d.ts.map +1 -1
- package/dist/data/chat/tool-policy.js +59 -2
- package/dist/data/chat/tool-policy.js.map +1 -1
- package/dist/data/chat/types.cjs +6 -0
- package/dist/data/chat/types.cjs.map +1 -1
- package/dist/data/chat/types.d.ts +13 -4
- package/dist/data/chat/types.d.ts.map +1 -1
- package/dist/data/chat/types.js +7 -1
- package/dist/data/chat/types.js.map +1 -1
- package/dist/data/chat/usage-snapshot.cjs +11 -6
- package/dist/data/chat/usage-snapshot.cjs.map +1 -1
- package/dist/data/chat/usage-snapshot.d.ts +0 -1
- package/dist/data/chat/usage-snapshot.d.ts.map +1 -1
- package/dist/data/chat/usage-snapshot.js +11 -6
- package/dist/data/chat/usage-snapshot.js.map +1 -1
- package/dist/data/diagnostics/StackFrameRow.cjs +3 -3
- package/dist/data/diagnostics/StackFrameRow.cjs.map +1 -1
- package/dist/data/diagnostics/StackFrameRow.js +3 -3
- package/dist/data/diagnostics/StackFrameRow.js.map +1 -1
- package/dist/data/graph-columns-layout.cjs +26 -10
- package/dist/data/graph-columns-layout.cjs.map +1 -1
- package/dist/data/graph-columns-layout.d.ts +8 -0
- package/dist/data/graph-columns-layout.d.ts.map +1 -1
- package/dist/data/graph-columns-layout.js +26 -10
- package/dist/data/graph-columns-layout.js.map +1 -1
- package/dist/data/graph-diagram-model.cjs.map +1 -1
- package/dist/data/graph-diagram-model.d.ts +5 -0
- package/dist/data/graph-diagram-model.d.ts.map +1 -1
- package/dist/data/graph-diagram-model.js.map +1 -1
- package/dist/data/graph-edge-routing.cjs +9 -3
- package/dist/data/graph-edge-routing.cjs.map +1 -1
- package/dist/data/graph-edge-routing.d.ts +2 -0
- package/dist/data/graph-edge-routing.d.ts.map +1 -1
- package/dist/data/graph-edge-routing.js +9 -3
- package/dist/data/graph-edge-routing.js.map +1 -1
- package/dist/data/json-view/JsonSource.cjs +84 -0
- package/dist/data/json-view/JsonSource.cjs.map +1 -0
- package/dist/data/json-view/JsonSource.d.ts +7 -0
- package/dist/data/json-view/JsonSource.d.ts.map +1 -0
- package/dist/data/json-view/JsonSource.js +84 -0
- package/dist/data/json-view/JsonSource.js.map +1 -0
- package/dist/data/json-view/parse-prefix.cjs +132 -0
- package/dist/data/json-view/parse-prefix.cjs.map +1 -0
- package/dist/data/json-view/parse-prefix.d.ts +11 -0
- package/dist/data/json-view/parse-prefix.d.ts.map +1 -0
- package/dist/data/json-view/parse-prefix.js +132 -0
- package/dist/data/json-view/parse-prefix.js.map +1 -0
- package/dist/data/json-view/parse-source.cjs +62 -0
- package/dist/data/json-view/parse-source.cjs.map +1 -0
- package/dist/data/json-view/parse-source.d.ts +16 -0
- package/dist/data/json-view/parse-source.d.ts.map +1 -0
- package/dist/data/json-view/parse-source.js +62 -0
- package/dist/data/json-view/parse-source.js.map +1 -0
- package/dist/data/json-view/story-fixtures.d.ts +6 -0
- package/dist/data/json-view/story-fixtures.d.ts.map +1 -0
- package/dist/data/json-view/types.d.ts +14 -0
- package/dist/data/json-view/types.d.ts.map +1 -0
- package/dist/data/runtime/RuntimeBar.cjs +2 -5
- package/dist/data/runtime/RuntimeBar.cjs.map +1 -1
- package/dist/data/runtime/RuntimeBar.d.ts +2 -4
- package/dist/data/runtime/RuntimeBar.d.ts.map +1 -1
- package/dist/data/runtime/RuntimeBar.fields.cjs +2 -2
- package/dist/data/runtime/RuntimeBar.fields.cjs.map +1 -1
- package/dist/data/runtime/RuntimeBar.fields.js +2 -2
- package/dist/data/runtime/RuntimeBar.fields.js.map +1 -1
- package/dist/data/runtime/RuntimeBar.js +2 -5
- package/dist/data/runtime/RuntimeBar.js.map +1 -1
- package/dist/data/runtime/RuntimeBar.selection.cjs +4 -1
- package/dist/data/runtime/RuntimeBar.selection.cjs.map +1 -1
- package/dist/data/runtime/RuntimeBar.selection.d.ts.map +1 -1
- package/dist/data/runtime/RuntimeBar.selection.js +5 -2
- package/dist/data/runtime/RuntimeBar.selection.js.map +1 -1
- package/dist/data/runtime/RuntimeBarActions.cjs +1 -5
- package/dist/data/runtime/RuntimeBarActions.cjs.map +1 -1
- package/dist/data/runtime/RuntimeBarActions.d.ts +1 -1
- package/dist/data/runtime/RuntimeBarActions.d.ts.map +1 -1
- package/dist/data/runtime/RuntimeBarActions.js +1 -5
- package/dist/data/runtime/RuntimeBarActions.js.map +1 -1
- package/dist/data/runtime/RuntimeBarIdentity.cjs +6 -14
- package/dist/data/runtime/RuntimeBarIdentity.cjs.map +1 -1
- package/dist/data/runtime/RuntimeBarIdentity.d.ts +0 -1
- package/dist/data/runtime/RuntimeBarIdentity.d.ts.map +1 -1
- package/dist/data/runtime/RuntimeBarIdentity.js +6 -14
- package/dist/data/runtime/RuntimeBarIdentity.js.map +1 -1
- package/dist/data/runtime/RuntimeBarLayout.cjs +8 -27
- package/dist/data/runtime/RuntimeBarLayout.cjs.map +1 -1
- package/dist/data/runtime/RuntimeBarLayout.d.ts.map +1 -1
- package/dist/data/runtime/RuntimeBarLayout.js +8 -27
- package/dist/data/runtime/RuntimeBarLayout.js.map +1 -1
- package/dist/data/runtime/RuntimeBarSegment.cjs +1 -5
- package/dist/data/runtime/RuntimeBarSegment.cjs.map +1 -1
- package/dist/data/runtime/RuntimeBarSegment.d.ts.map +1 -1
- package/dist/data/runtime/RuntimeBarSegment.js +1 -5
- package/dist/data/runtime/RuntimeBarSegment.js.map +1 -1
- package/dist/data/runtime/use-runtime-bar-overflow.cjs +4 -10
- package/dist/data/runtime/use-runtime-bar-overflow.cjs.map +1 -1
- package/dist/data/runtime/use-runtime-bar-overflow.d.ts +1 -2
- package/dist/data/runtime/use-runtime-bar-overflow.d.ts.map +1 -1
- package/dist/data/runtime/use-runtime-bar-overflow.js +4 -10
- package/dist/data/runtime/use-runtime-bar-overflow.js.map +1 -1
- package/dist/data/test-runner/TestRunner.fixtures.d.ts +0 -20
- package/dist/data/test-runner/TestRunner.fixtures.d.ts.map +1 -1
- package/dist/data/test-runner/TestRunner.large-fixtures.d.ts +22 -0
- package/dist/data/test-runner/TestRunner.large-fixtures.d.ts.map +1 -0
- package/dist/data/use-pan-zoom.cjs +23 -10
- package/dist/data/use-pan-zoom.cjs.map +1 -1
- package/dist/data/use-pan-zoom.d.ts +16 -2
- package/dist/data/use-pan-zoom.d.ts.map +1 -1
- package/dist/data/use-pan-zoom.js +23 -10
- package/dist/data/use-pan-zoom.js.map +1 -1
- package/dist/data/version-info.cjs +3 -3
- package/dist/data/version-info.js +3 -3
- package/dist/data.cjs +26 -2
- 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 +24 -0
- package/dist/data.js.map +1 -1
- package/dist/index.cjs +28 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +24 -0
- package/dist/index.js.map +1 -1
- package/dist/layout/Workspace.cjs +13 -4
- package/dist/layout/Workspace.cjs.map +1 -1
- package/dist/layout/Workspace.d.ts +7 -2
- package/dist/layout/Workspace.d.ts.map +1 -1
- package/dist/layout/Workspace.js +13 -4
- package/dist/layout/Workspace.js.map +1 -1
- package/dist/lib/permission-strategies.cjs +71 -11
- package/dist/lib/permission-strategies.cjs.map +1 -1
- package/dist/lib/permission-strategies.d.ts +3 -0
- package/dist/lib/permission-strategies.d.ts.map +1 -1
- package/dist/lib/permission-strategies.js +71 -11
- package/dist/lib/permission-strategies.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +5 -3
- package/dist/data/ai/ToolSchemaBrowser.selection-toolbar.cjs +0 -57
- package/dist/data/ai/ToolSchemaBrowser.selection-toolbar.cjs.map +0 -1
- package/dist/data/ai/ToolSchemaBrowser.selection-toolbar.d.ts +0 -7
- package/dist/data/ai/ToolSchemaBrowser.selection-toolbar.d.ts.map +0 -1
- package/dist/data/ai/ToolSchemaBrowser.selection-toolbar.js +0 -57
- package/dist/data/ai/ToolSchemaBrowser.selection-toolbar.js.map +0 -1
- package/dist/data/runtime/RuntimeBar.context.cjs +0 -8
- package/dist/data/runtime/RuntimeBar.context.cjs.map +0 -1
- package/dist/data/runtime/RuntimeBar.context.d.ts +0 -2
- package/dist/data/runtime/RuntimeBar.context.d.ts.map +0 -1
- package/dist/data/runtime/RuntimeBar.context.js +0 -8
- package/dist/data/runtime/RuntimeBar.context.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SessionViewer.cjs","sources":["../../../src/data/ai/SessionViewer.tsx"],"sourcesContent":["import { useMemo, useState, type ReactNode } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { cn } from \"../../lib/utils\";\nimport { Icon } from \"../Icon\";\nimport { Button } from \"../../components/button\";\nimport { useDensityValue, type Density } from \"../../hooks/use-density\";\nimport { DensityValueProvider } from \"../../hooks/density-provider\";\nimport { UiArrowDown, UiRobotAi } from \"../../icons\";\nimport {\n getSessionMetadata,\n normalizeSession,\n summarizeSession,\n type SessionEvent,\n type SessionInput,\n} from \"./SessionViewer.model\";\nimport {\n collapseWaitRuns,\n isSessionEventGroup,\n} from \"./SessionViewer.grouping\";\nimport { SessionRow, WaitGroupRow } from \"./SessionViewer.rows\";\nimport { SessionMetadataBadges } from \"./SessionViewer.header\";\nimport {\n collectSessionFilters,\n isEncryptedReasoning,\n isEventVisible,\n type SessionCategory,\n} from \"./session-categories\";\nimport {\n SessionViewerMenu,\n type SessionThemeOverride,\n} from \"./SessionViewerMenu\";\nimport { useSessionScroll } from \"./use-session-scroll\";\nimport type {\n ApprovalDecisionFields,\n ApprovalKind,\n ApprovalRequest,\n} from \"./approval-request\";\n\nexport type {\n SessionEntry,\n SessionEvent,\n SessionInput,\n SessionActionMeta,\n} from \"./SessionViewer.model\";\nexport type { SessionThemeOverride } from \"./SessionViewerMenu\";\n\nexport interface SessionPendingTool {\n tool: string;\n input?: Record<string, unknown>;\n toolCallId?: string;\n approvalId?: string;\n sessionId?: string;\n /** What kind of approval this is. Absent means an untyped tool approval, which\n * renders as Allow / Reject. */\n kind?: ApprovalKind;\n /** The typed approval request; drives the per-kind controls. */\n request?: ApprovalRequest;\n}\n\n/** A decision on one pending tool. `allow`/`message`/`answers` are the original\n * fields; `interrupt`, `scope`, `grants` and `content` are set only for a typed\n * request that offers them. */\nexport interface SessionToolDecision extends ApprovalDecisionFields {\n event: SessionEvent;\n allow: boolean;\n message?: string;\n}\n\nexport interface SessionViewerProps {\n /** A captain session: parsed `SessionEntry[]` or raw log text (JSON / JSONL). */\n session: SessionInput;\n className?: string;\n /** Expand each tool call's input/output by default. Defaults to false. */\n defaultExpanded?: boolean;\n /** Render assistant reasoning (\"thinking\") blocks. Defaults to true. */\n showThinking?: boolean;\n /** Show the summary header (model + action counts). Defaults to true. */\n showHeader?: boolean;\n /** Show context usage in the summary header. Defaults to true. */\n showContextMeter?: boolean;\n /** Show the 3-dot menu (density + category/tool/source filters). Defaults to true. */\n showMenu?: boolean;\n /** Controls rendered beside the 3-dot menu in the summary header. */\n headerActions?: ReactNode;\n /** Host controls rendered at the top of the 3-dot menu. */\n menuHeader?: ReactNode;\n /** Portal the 3-dot menu into this element instead of rendering it inline in\n * the summary header — lets a host place the menu in its own toolbar while the\n * filter/density state stays owned by the viewer. Ignored when `showMenu` is\n * false; falls back to inline rendering when null/undefined. */\n menuContainer?: Element | null;\n /** Initial density override; undefined inherits the page/document density. */\n defaultDensity?: Density;\n /** Initial theme override; undefined inherits the page/document `data-theme`. */\n defaultTheme?: SessionThemeOverride;\n /** Own an internal scroll container that fills its parent's height: render only\n * the newest screenful, stay pinned to the bottom (most recent activity), and\n * backfill older rows as the reader scrolls up. Off by default, so inline\n * consumers keep rendering the whole log in normal page flow. Requires a\n * height-bounded parent. */\n scrollable?: boolean;\n /** Rows rendered on first paint in `scrollable` mode. Defaults to 60. */\n windowSize?: number;\n /** Rows added each time older content loads in `scrollable` mode. Defaults to 40. */\n batchSize?: number;\n /** Stable identity used to reset the transcript window when switching sessions. */\n scrollResetKey?: string;\n /** Show per-row timestamp/source/model/turn/agent metadata. Defaults to false. */\n showRowMetadata?: boolean;\n /** Show a per-row raw JSON payload expander when available. Defaults to false. */\n showRaw?: boolean;\n /** Render content before each assistant message body. */\n renderMessageBadge?: (event: SessionEvent) => ReactNode;\n pendingTools?: readonly SessionPendingTool[];\n onPendingToolDecision?:\n | ((decision: SessionToolDecision) => Promise<void> | void)\n | undefined;\n}\n\nfunction toggleInSet<T>(set: ReadonlySet<T>, value: T): Set<T> {\n const next = new Set(set);\n if (next.has(value)) next.delete(value);\n else next.add(value);\n return next;\n}\n\n/**\n * SessionViewer renders a recorded AI coding-agent session (the captain\n * `pkg/ai/history` JSON schema — Claude Code / Codex transcripts) as a vertical\n * action log. Each entry sits on a tone-colored icon disc from the Flanksource\n * \"Agent Action Icons\" set; user prompts/selections are right-aligned like a\n * chat. Shell commands render inline as bash blocks and file ops as their\n * cwd-relative path — the icon carries the verb. Tool responses expand behind\n * a chevron, rendered bare (no panel chrome). The \"3-dot\" menu mirrors\n * `captain history` filtering — toggle density and hide categories, tools or\n * sources.\n */\nexport function SessionViewer({\n session,\n className,\n defaultExpanded = false,\n showThinking = true,\n showHeader = true,\n showContextMeter = true,\n showMenu = true,\n headerActions,\n menuHeader,\n menuContainer,\n defaultDensity,\n defaultTheme,\n scrollable = false,\n windowSize = 60,\n batchSize = 40,\n scrollResetKey,\n showRowMetadata = false,\n showRaw = false,\n renderMessageBadge,\n pendingTools = [],\n onPendingToolDecision,\n}: SessionViewerProps) {\n const allEvents = useMemo(\n () => mergePendingTools(normalizeSession(session), pendingTools),\n [session, pendingTools],\n );\n const displayItems = useMemo(() => collapseWaitRuns(allEvents), [allEvents]);\n const metadata = useMemo(() => getSessionMetadata(session), [session]);\n\n const pageDensity = useDensityValue();\n const [densityOverride, setDensityOverride] = useState<Density | undefined>(\n defaultDensity,\n );\n const [themeOverride, setThemeOverride] = useState<\n SessionThemeOverride | undefined\n >(defaultTheme);\n const [hiddenCategories, setHiddenCategories] = useState<\n ReadonlySet<SessionCategory>\n >(() => new Set());\n const [hiddenTools, setHiddenTools] = useState<ReadonlySet<string>>(\n () => new Set(),\n );\n const [hiddenSources, setHiddenSources] = useState<ReadonlySet<string>>(\n () => new Set(),\n );\n // Undefined = follow the `showThinking` prop; the menu toggle sets an override.\n const [showThinkingOverride, setShowThinkingOverride] = useState<\n boolean | undefined\n >(undefined);\n const effectiveShowThinking = showThinkingOverride ?? showThinking;\n const [showEncryptedReasoning, setShowEncryptedReasoning] = useState(false);\n\n const filters = useMemo(() => collectSessionFilters(allEvents), [allEvents]);\n const hasThinking = useMemo(\n () => allEvents.some((e) => e.kind === \"thinking\"),\n [allEvents],\n );\n const hasEncryptedReasoning = useMemo(\n () => allEvents.some(isEncryptedReasoning),\n [allEvents],\n );\n\n const visibility = {\n hiddenCategories,\n hiddenTools,\n hiddenSources,\n showThinking: effectiveShowThinking,\n };\n const items = displayItems.filter((item) => {\n const event = isSessionEventGroup(item) ? item.representative : item;\n return (showEncryptedReasoning || !isEncryptedReasoning(event)) && isEventVisible(event, visibility);\n });\n const firstUserEventId = allEvents.find((event) => event.kind === \"user\")?.id;\n\n // Reset the window when the underlying session changes, not on filter toggles —\n // so hiding a category doesn't yank the reader back to the bottom.\n const resetKey = scrollResetKey ?? allEvents[0]?.id ?? \"\";\n const { scrollRef, contentRef, startIndex, following, resumeFollowing } = useSessionScroll({\n total: items.length,\n enabled: scrollable,\n windowSize,\n batchSize,\n resetKey,\n });\n\n if (allEvents.length === 0) {\n return (\n <div\n className={cn(\n \"rounded-md border border-dashed border-border p-density-4 text-center text-sm text-muted-foreground\",\n className,\n )}\n >\n No session activity.\n </div>\n );\n }\n\n const summary = summarizeSession(allEvents);\n const effectiveDensity = densityOverride ?? pageDensity;\n const dataAttrs: Record<string, string> = {\n ...(densityOverride ? { \"data-density\": densityOverride } : {}),\n ...(themeOverride ? { \"data-theme\": themeOverride } : {}),\n };\n\n const menu = showMenu ? (\n <SessionViewerMenu\n menuHeader={menuHeader}\n density={densityOverride}\n onDensityChange={setDensityOverride}\n theme={themeOverride}\n onThemeChange={setThemeOverride}\n filters={filters}\n hiddenCategories={hiddenCategories}\n hiddenTools={hiddenTools}\n hiddenSources={hiddenSources}\n onToggleCategory={(category) =>\n setHiddenCategories((set) => toggleInSet(set, category))\n }\n onToggleTool={(tool) => setHiddenTools((set) => toggleInSet(set, tool))}\n onToggleSource={(source) =>\n setHiddenSources((set) => toggleInSet(set, source))\n }\n showThinking={effectiveShowThinking}\n onToggleThinking={() => setShowThinkingOverride(!effectiveShowThinking)}\n hasThinking={hasThinking}\n hasEncryptedReasoning={hasEncryptedReasoning}\n showEncryptedReasoning={showEncryptedReasoning}\n onToggleEncryptedReasoning={() => setShowEncryptedReasoning((shown) => !shown)}\n />\n ) : null;\n // When a host supplies `menuContainer`, the menu is portaled into it (e.g. the\n // host's own toolbar) and the inline header collapses to just its summary.\n const inlineMenu = menu && !menuContainer;\n\n const list =\n items.length === 0 ? (\n <div className=\"rounded-md border border-dashed border-border p-density-4 text-center text-sm text-muted-foreground\">\n All actions are hidden by the active filters.\n </div>\n ) : (\n // In scrollable mode only the newest `startIndex..` slice is mounted; `last`\n // is measured against the full length so the timeline connector stays right.\n <ol className=\"relative\">\n {items.slice(startIndex).map((item, index) => {\n const last = startIndex + index === items.length - 1;\n return isSessionEventGroup(item) ? (\n <WaitGroupRow\n key={item.id}\n group={item}\n last={last}\n defaultExpanded={defaultExpanded}\n showRowMetadata={showRowMetadata}\n showRaw={showRaw}\n renderMessageBadge={renderMessageBadge}\n onPendingToolDecision={onPendingToolDecision}\n />\n ) : (\n <SessionRow\n key={item.id}\n event={item}\n initialPrompt={item.id === firstUserEventId}\n last={last}\n defaultExpanded={defaultExpanded}\n showRowMetadata={showRowMetadata}\n showRaw={showRaw}\n renderMessageBadge={renderMessageBadge}\n onPendingToolDecision={onPendingToolDecision}\n />\n );\n })}\n </ol>\n );\n\n return (\n <div\n className={cn(\n \"@container/session-viewer min-w-0 bg-background text-sm text-foreground data-[theme=dark]:bg-[var(--fs-bg-subtle)] [[data-theme=dark]_&]:bg-[var(--fs-bg-subtle)]\",\n scrollable && \"flex h-full min-h-0 flex-col\",\n className,\n )}\n {...dataAttrs}\n >\n <DensityValueProvider density={effectiveDensity}>\n {menu && menuContainer && createPortal(menu, menuContainer)}\n {(showHeader || headerActions || inlineMenu) && (\n <div\n data-session-viewer-header\n className={cn(\n \"flex min-w-0 flex-wrap items-center justify-between gap-x-density-3 gap-y-density-2\",\n scrollable\n ? \"shrink-0 border-b border-border px-density-3 py-density-2 @min-[48rem]/session-viewer:px-density-4\"\n : \"mb-density-3\",\n )}\n >\n {showHeader && (\n <div className=\"flex min-w-0 flex-1 flex-wrap items-center gap-x-density-3 gap-y-1 text-xs text-muted-foreground\">\n {summary.model && (\n <span className=\"inline-flex items-center gap-1 font-medium text-foreground\">\n <Icon icon={UiRobotAi} className=\"size-3.5\" />\n {summary.model}\n </span>\n )}\n <span>{summary.toolCount} actions</span>\n <span>{summary.messageCount} messages</span>\n {metadata && (\n <SessionMetadataBadges\n metadata={metadata}\n showContextMeter={showContextMeter}\n />\n )}\n </div>\n )}\n {(headerActions || inlineMenu) && (\n <div\n role=\"group\"\n aria-label=\"Session viewer actions\"\n className=\"ml-auto flex min-w-0 shrink-0 items-center gap-density-2\"\n >\n {headerActions}\n {inlineMenu && menu}\n </div>\n )}\n </div>\n )}\n\n {scrollable ? (\n <div className=\"relative min-h-0 flex-1\">\n <div ref={scrollRef} className=\"h-full overflow-y-auto\">\n <div\n ref={contentRef}\n data-session-viewer-content\n className=\"p-density-3 @min-[48rem]/session-viewer:p-density-4\"\n >\n {list}\n </div>\n </div>\n {!following && (\n <Button\n type=\"button\"\n variant=\"secondary\"\n size=\"sm\"\n onClick={resumeFollowing}\n className=\"absolute bottom-density-3 left-1/2 -translate-x-1/2 shadow-md\"\n >\n <Icon icon={UiArrowDown} className=\"size-4\" />\n Scroll to bottom\n </Button>\n )}\n </div>\n ) : (\n list\n )}\n </DensityValueProvider>\n </div>\n );\n}\n\nfunction mergePendingTools(\n events: SessionEvent[],\n pendingTools: readonly SessionPendingTool[],\n): SessionEvent[] {\n const merged = [...events];\n for (const [index, pending] of pendingTools.entries()) {\n const matches = merged.filter(\n (event) =>\n event.kind === \"tool\" &&\n ((pending.toolCallId && event.toolCallId === pending.toolCallId) ||\n (pending.approvalId && event.approvalId === pending.approvalId) ||\n (pending.sessionId &&\n event.sessionId === pending.sessionId &&\n event.tool === pending.tool)),\n );\n const match = matches.length === 1 ? matches[0] : undefined;\n if (match) {\n Object.assign(match, {\n pending: true,\n toolInput: pending.input ?? match.toolInput,\n toolCallId: pending.toolCallId ?? match.toolCallId,\n approvalId: pending.approvalId ?? match.approvalId,\n sessionId: pending.sessionId ?? match.sessionId,\n ...approvalFields(pending),\n });\n } else {\n merged.push({\n id: `pending-${\n pending.approvalId ?? pending.toolCallId ?? `${pending.tool}-${index}`\n }`,\n kind: \"tool\",\n tool: pending.tool,\n ...(pending.input ? { toolInput: pending.input } : {}),\n ...(pending.toolCallId ? { toolCallId: pending.toolCallId } : {}),\n ...(pending.approvalId ? { approvalId: pending.approvalId } : {}),\n ...(pending.sessionId ? { sessionId: pending.sessionId } : {}),\n ...approvalFields(pending),\n pending: true,\n });\n }\n }\n return merged;\n}\n\nfunction approvalFields(\n pending: SessionPendingTool,\n): Pick<SessionEvent, \"approvalKind\" | \"approvalRequest\"> {\n const kind = pending.kind ?? pending.request?.kind;\n return {\n ...(kind ? { approvalKind: kind } : {}),\n ...(pending.request ? { approvalRequest: pending.request } : {}),\n };\n}\n"],"names":["useMemo","normalizeSession","collapseWaitRuns","getSessionMetadata","useDensityValue","useState","collectSessionFilters","isEncryptedReasoning","isSessionEventGroup","isEventVisible","useSessionScroll","jsx","cn","summarizeSession","SessionViewerMenu","WaitGroupRow","SessionRow","jsxs","DensityValueProvider","createPortal","Icon","UiRobotAi","SessionMetadataBadges","Button","UiArrowDown"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SessionViewer.cjs","sources":["../../../src/data/ai/SessionViewer.tsx"],"sourcesContent":["import { useMemo, useState, type ReactNode } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { cn } from \"../../lib/utils\";\nimport { Icon } from \"../Icon\";\nimport { Button } from \"../../components/button\";\nimport { useDensityValue, type Density } from \"../../hooks/use-density\";\nimport { DensityValueProvider } from \"../../hooks/density-provider\";\nimport { UiArrowDown, UiRobotAi } from \"../../icons\";\nimport {\n getSessionMetadata,\n normalizeSession,\n summarizeSession,\n type SessionEvent,\n type SessionInput,\n} from \"./SessionViewer.model\";\nimport {\n collapseWaitRuns,\n isSessionEventGroup,\n} from \"./SessionViewer.grouping\";\nimport { SessionRow, WaitGroupRow } from \"./SessionViewer.rows\";\nimport { SessionMetadataBadges } from \"./SessionViewer.header\";\nimport {\n collectSessionFilters,\n isEncryptedReasoning,\n isEventVisible,\n type SessionCategory,\n} from \"./session-categories\";\nimport {\n SessionViewerMenu,\n type SessionThemeOverride,\n} from \"./SessionViewerMenu\";\nimport { useSessionScroll } from \"./use-session-scroll\";\nimport type {\n ApprovalDecisionFields,\n ApprovalKind,\n ApprovalRequest,\n} from \"./approval-request\";\nimport type { SessionTokenSizer } from \"./session-token-sizing\";\nimport { SessionTokenContext, useSessionTokenSizing } from \"./use-session-token-sizing\";\nexport type { SessionTokenSizer, SessionTokenSize, SessionTokenSizingRequest, SessionTokenSizingResult } from \"./session-token-sizing\";\n\nexport type {\n SessionEntry,\n SessionEvent,\n SessionInput,\n SessionActionMeta,\n} from \"./SessionViewer.model\";\nexport type { SessionThemeOverride } from \"./SessionViewerMenu\";\n\nexport interface SessionPendingTool {\n tool: string;\n input?: Record<string, unknown>;\n toolCallId?: string;\n approvalId?: string;\n sessionId?: string;\n /** What kind of approval this is. Absent means an untyped tool approval, which\n * renders as Allow / Reject. */\n kind?: ApprovalKind;\n /** The typed approval request; drives the per-kind controls. */\n request?: ApprovalRequest;\n}\n\n/** A decision on one pending tool. `allow`/`message`/`answers` are the original\n * fields; `interrupt`, `scope`, `grants` and `content` are set only for a typed\n * request that offers them. */\nexport interface SessionToolDecision extends ApprovalDecisionFields {\n event: SessionEvent;\n allow: boolean;\n message?: string;\n}\n\nexport interface SessionViewerProps {\n\n /** Explicit menu actions only; never invoked automatically when a transcript loads. */\n sizeTokens?: SessionTokenSizer;\n /** A captain session: parsed `SessionEntry[]` or raw log text (JSON / JSONL). */\n session: SessionInput;\n className?: string;\n /** Expand each tool call's input/output by default. Defaults to false. */\n defaultExpanded?: boolean;\n /** Render assistant reasoning (\"thinking\") blocks. Defaults to true. */\n showThinking?: boolean;\n /** Show the summary header (model + action counts). Defaults to true. */\n showHeader?: boolean;\n /** Show context usage in the summary header. Defaults to true. */\n showContextMeter?: boolean;\n /** Show the 3-dot menu (density + category/tool/source filters). Defaults to true. */\n showMenu?: boolean;\n /** Controls rendered beside the 3-dot menu in the summary header. */\n headerActions?: ReactNode;\n /** Host controls rendered at the top of the 3-dot menu. */\n menuHeader?: ReactNode;\n /** Portal the 3-dot menu into this element instead of rendering it inline in\n * the summary header — lets a host place the menu in its own toolbar while the\n * filter/density state stays owned by the viewer. Ignored when `showMenu` is\n * false; falls back to inline rendering when null/undefined. */\n menuContainer?: Element | null;\n /** Initial density override; undefined inherits the page/document density. */\n defaultDensity?: Density;\n /** Initial theme override; undefined inherits the page/document `data-theme`. */\n defaultTheme?: SessionThemeOverride;\n /** Own an internal scroll container that fills its parent's height: render only\n * the newest screenful, stay pinned to the bottom (most recent activity), and\n * backfill older rows as the reader scrolls up. Off by default, so inline\n * consumers keep rendering the whole log in normal page flow. Requires a\n * height-bounded parent. */\n scrollable?: boolean;\n /** Rows rendered on first paint in `scrollable` mode. Defaults to 60. */\n windowSize?: number;\n /** Rows added each time older content loads in `scrollable` mode. Defaults to 40. */\n batchSize?: number;\n /** Stable identity used to reset the transcript window when switching sessions. */\n scrollResetKey?: string;\n /** Show per-row timestamp/source/model/turn/agent metadata. Defaults to false. */\n showRowMetadata?: boolean;\n /** Show a per-row raw JSON payload expander when available. Defaults to false. */\n showRaw?: boolean;\n /** Render content before each assistant message body. */\n renderMessageBadge?: (event: SessionEvent) => ReactNode;\n pendingTools?: readonly SessionPendingTool[];\n onPendingToolDecision?:\n | ((decision: SessionToolDecision) => Promise<void> | void)\n | undefined;\n}\n\nfunction toggleInSet<T>(set: ReadonlySet<T>, value: T): Set<T> {\n const next = new Set(set);\n if (next.has(value)) next.delete(value);\n else next.add(value);\n return next;\n}\n\n/**\n * SessionViewer renders a recorded AI coding-agent session (the captain\n * `pkg/ai/history` JSON schema — Claude Code / Codex transcripts) as a vertical\n * action log. Each entry sits on a tone-colored icon disc from the Flanksource\n * \"Agent Action Icons\" set; user prompts/selections are right-aligned like a\n * chat. Shell commands render inline as bash blocks and file ops as their\n * cwd-relative path — the icon carries the verb. Tool responses expand behind\n * a chevron, rendered bare (no panel chrome). The \"3-dot\" menu mirrors\n * `captain history` filtering — toggle density and hide categories, tools or\n * sources.\n */\nexport function SessionViewer({\n session,\n className,\n defaultExpanded = false,\n showThinking = true,\n showHeader = true,\n showContextMeter = true,\n showMenu = true,\n headerActions,\n menuHeader,\n menuContainer,\n defaultDensity,\n defaultTheme,\n scrollable = false,\n windowSize = 60,\n batchSize = 40,\n scrollResetKey,\n showRowMetadata = false,\n showRaw = false,\n renderMessageBadge,\n pendingTools = [],\n onPendingToolDecision,\n sizeTokens,\n}: SessionViewerProps) {\n const allEvents = useMemo(\n () => mergePendingTools(normalizeSession(session), pendingTools),\n [session, pendingTools],\n );\n const displayItems = useMemo(() => collapseWaitRuns(allEvents), [allEvents]);\n const metadata = useMemo(() => getSessionMetadata(session), [session]);\n const tokenSizing = useSessionTokenSizing(session, allEvents, sizeTokens);\n\n const pageDensity = useDensityValue();\n const [densityOverride, setDensityOverride] = useState<Density | undefined>(\n defaultDensity,\n );\n const [themeOverride, setThemeOverride] = useState<\n SessionThemeOverride | undefined\n >(defaultTheme);\n const [hiddenCategories, setHiddenCategories] = useState<\n ReadonlySet<SessionCategory>\n >(() => new Set());\n const [hiddenTools, setHiddenTools] = useState<ReadonlySet<string>>(\n () => new Set(),\n );\n const [hiddenSources, setHiddenSources] = useState<ReadonlySet<string>>(\n () => new Set(),\n );\n // Undefined = follow the `showThinking` prop; the menu toggle sets an override.\n const [showThinkingOverride, setShowThinkingOverride] = useState<\n boolean | undefined\n >(undefined);\n const effectiveShowThinking = showThinkingOverride ?? showThinking;\n const [showEncryptedReasoning, setShowEncryptedReasoning] = useState(false);\n const [showEstimatedToolCost, setShowEstimatedToolCost] = useState(false);\n\n const filters = useMemo(() => collectSessionFilters(allEvents), [allEvents]);\n const hasThinking = useMemo(\n () => allEvents.some((e) => e.kind === \"thinking\"),\n [allEvents],\n );\n const hasEncryptedReasoning = useMemo(\n () => allEvents.some(isEncryptedReasoning),\n [allEvents],\n );\n\n const visibility = {\n hiddenCategories,\n hiddenTools,\n hiddenSources,\n showThinking: effectiveShowThinking,\n };\n const items = displayItems.filter((item) => {\n const event = isSessionEventGroup(item) ? item.representative : item;\n return (showEncryptedReasoning || !isEncryptedReasoning(event)) && isEventVisible(event, visibility);\n });\n const firstUserEventId = allEvents.find((event) => event.kind === \"user\")?.id;\n\n // Reset the window when the underlying session changes, not on filter toggles —\n // so hiding a category doesn't yank the reader back to the bottom.\n const resetKey = scrollResetKey ?? allEvents[0]?.id ?? \"\";\n const { scrollRef, contentRef, startIndex, following, resumeFollowing } = useSessionScroll({\n total: items.length,\n enabled: scrollable,\n windowSize,\n batchSize,\n resetKey,\n });\n\n if (allEvents.length === 0) {\n return (\n <div\n className={cn(\n \"rounded-md border border-dashed border-border p-density-4 text-center text-sm text-muted-foreground\",\n className,\n )}\n >\n No session activity.\n </div>\n );\n }\n\n const summary = summarizeSession(allEvents);\n const effectiveDensity = densityOverride ?? pageDensity;\n const dataAttrs: Record<string, string> = {\n ...(densityOverride ? { \"data-density\": densityOverride } : {}),\n ...(themeOverride ? { \"data-theme\": themeOverride } : {}),\n };\n\n const menu = showMenu ? (\n <SessionViewerMenu\n menuHeader={menuHeader}\n density={densityOverride}\n onDensityChange={setDensityOverride}\n theme={themeOverride}\n onThemeChange={setThemeOverride}\n filters={filters}\n hiddenCategories={hiddenCategories}\n hiddenTools={hiddenTools}\n hiddenSources={hiddenSources}\n onToggleCategory={(category) =>\n setHiddenCategories((set) => toggleInSet(set, category))\n }\n onToggleTool={(tool) => setHiddenTools((set) => toggleInSet(set, tool))}\n onToggleSource={(source) =>\n setHiddenSources((set) => toggleInSet(set, source))\n }\n showThinking={effectiveShowThinking}\n onToggleThinking={() => setShowThinkingOverride(!effectiveShowThinking)}\n hasThinking={hasThinking}\n hasEncryptedReasoning={hasEncryptedReasoning}\n showEncryptedReasoning={showEncryptedReasoning}\n onToggleEncryptedReasoning={() => setShowEncryptedReasoning((shown) => !shown)}\n showEstimatedToolCost={showEstimatedToolCost}\n onToggleEstimatedToolCost={() => setShowEstimatedToolCost((shown) => !shown)}\n {...(tokenSizing.estimateAll ? { onEstimateTokens: tokenSizing.estimateAll, onCalculateMissingTokens: tokenSizing.calculateMissing, estimatingTokens: tokenSizing.pending } : {})}\n />\n ) : null;\n // When a host supplies `menuContainer`, the menu is portaled into it (e.g. the\n // host's own toolbar) and the inline header collapses to just its summary.\n const inlineMenu = menu && !menuContainer;\n\n const list =\n items.length === 0 ? (\n <div className=\"rounded-md border border-dashed border-border p-density-4 text-center text-sm text-muted-foreground\">\n All actions are hidden by the active filters.\n </div>\n ) : (\n // In scrollable mode only the newest `startIndex..` slice is mounted; `last`\n // is measured against the full length so the timeline connector stays right.\n <ol className=\"relative\">\n {items.slice(startIndex).map((item, index) => {\n const last = startIndex + index === items.length - 1;\n return isSessionEventGroup(item) ? (\n <WaitGroupRow\n key={item.id}\n group={item}\n last={last}\n showEstimatedToolCost={showEstimatedToolCost}\n defaultExpanded={defaultExpanded}\n showRowMetadata={showRowMetadata}\n showRaw={showRaw}\n renderMessageBadge={renderMessageBadge}\n onPendingToolDecision={onPendingToolDecision}\n />\n ) : (\n <SessionRow\n key={item.id}\n event={item}\n initialPrompt={item.id === firstUserEventId}\n showEstimatedToolCost={showEstimatedToolCost}\n last={last}\n defaultExpanded={defaultExpanded}\n showRowMetadata={showRowMetadata}\n showRaw={showRaw}\n renderMessageBadge={renderMessageBadge}\n onPendingToolDecision={onPendingToolDecision}\n />\n );\n })}\n </ol>\n );\n\n return (\n <div\n className={cn(\n \"@container/session-viewer min-w-0 bg-background text-sm text-foreground data-[theme=dark]:bg-[var(--fs-bg-subtle)] [[data-theme=dark]_&]:bg-[var(--fs-bg-subtle)]\",\n scrollable && \"flex h-full min-h-0 flex-col\",\n className,\n )}\n {...dataAttrs}\n >\n <SessionTokenContext.Provider value={tokenSizing.context}>\n <DensityValueProvider density={effectiveDensity}>\n {menu && menuContainer && createPortal(menu, menuContainer)}\n {(showHeader || headerActions || inlineMenu) && (\n <div\n data-session-viewer-header\n className={cn(\n \"flex min-w-0 flex-wrap items-center justify-between gap-x-density-3 gap-y-density-2\",\n scrollable\n ? \"shrink-0 border-b border-border px-density-3 py-density-2 @min-[48rem]/session-viewer:px-density-4\"\n : \"mb-density-3\",\n )}\n >\n {showHeader && (\n <div className=\"flex min-w-0 flex-1 flex-wrap items-center gap-x-density-3 gap-y-1 text-xs text-muted-foreground\">\n {summary.model && (\n <span className=\"inline-flex items-center gap-1 font-medium text-foreground\">\n <Icon icon={UiRobotAi} className=\"size-3.5\" />\n {summary.model}\n </span>\n )}\n <span>{summary.toolCount} actions</span>\n <span>{summary.messageCount} messages</span>\n {metadata && (\n <SessionMetadataBadges\n metadata={metadata}\n showContextMeter={showContextMeter}\n />\n )}\n </div>\n )}\n {(headerActions || inlineMenu) && (\n <div\n role=\"group\"\n aria-label=\"Session viewer actions\"\n className=\"ml-auto flex min-w-0 shrink-0 items-center gap-density-2\"\n >\n {headerActions}\n {inlineMenu && menu}\n </div>\n )}\n </div>\n )}\n\n {scrollable ? (\n <div className=\"relative min-h-0 flex-1\">\n <div ref={scrollRef} className=\"h-full overflow-y-auto\">\n <div\n ref={contentRef}\n data-session-viewer-content\n className=\"p-density-3 @min-[48rem]/session-viewer:p-density-4\"\n >\n {list}\n </div>\n </div>\n {!following && (\n <Button\n type=\"button\"\n variant=\"secondary\"\n size=\"sm\"\n onClick={resumeFollowing}\n className=\"absolute bottom-density-3 left-1/2 -translate-x-1/2 shadow-md\"\n >\n <Icon icon={UiArrowDown} className=\"size-4\" />\n Scroll to bottom\n </Button>\n )}\n </div>\n ) : (\n list\n )}\n </DensityValueProvider>\n </SessionTokenContext.Provider>\n </div>\n );\n}\n\nfunction mergePendingTools(\n events: SessionEvent[],\n pendingTools: readonly SessionPendingTool[],\n): SessionEvent[] {\n const merged = [...events];\n for (const [index, pending] of pendingTools.entries()) {\n const matches = merged.filter(\n (event) =>\n event.kind === \"tool\" &&\n ((pending.toolCallId && event.toolCallId === pending.toolCallId) ||\n (pending.approvalId && event.approvalId === pending.approvalId) ||\n (pending.sessionId &&\n event.sessionId === pending.sessionId &&\n event.tool === pending.tool)),\n );\n const match = matches.length === 1 ? matches[0] : undefined;\n if (match) {\n Object.assign(match, {\n pending: true,\n toolInput: pending.input ?? match.toolInput,\n toolCallId: pending.toolCallId ?? match.toolCallId,\n approvalId: pending.approvalId ?? match.approvalId,\n sessionId: pending.sessionId ?? match.sessionId,\n ...approvalFields(pending),\n });\n } else {\n merged.push({\n id: `pending-${\n pending.approvalId ?? pending.toolCallId ?? `${pending.tool}-${index}`\n }`,\n kind: \"tool\",\n tool: pending.tool,\n ...(pending.input ? { toolInput: pending.input } : {}),\n ...(pending.toolCallId ? { toolCallId: pending.toolCallId } : {}),\n ...(pending.approvalId ? { approvalId: pending.approvalId } : {}),\n ...(pending.sessionId ? { sessionId: pending.sessionId } : {}),\n ...approvalFields(pending),\n pending: true,\n });\n }\n }\n return merged;\n}\n\nfunction approvalFields(\n pending: SessionPendingTool,\n): Pick<SessionEvent, \"approvalKind\" | \"approvalRequest\"> {\n const kind = pending.kind ?? pending.request?.kind;\n return {\n ...(kind ? { approvalKind: kind } : {}),\n ...(pending.request ? { approvalRequest: pending.request } : {}),\n };\n}\n"],"names":["useMemo","normalizeSession","collapseWaitRuns","getSessionMetadata","useSessionTokenSizing","useDensityValue","useState","collectSessionFilters","isEncryptedReasoning","isSessionEventGroup","isEventVisible","useSessionScroll","jsx","cn","summarizeSession","SessionViewerMenu","WaitGroupRow","SessionRow","SessionTokenContext","jsxs","DensityValueProvider","createPortal","Icon","UiRobotAi","SessionMetadataBadges","Button","UiArrowDown"],"mappings":"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"}
|
|
@@ -3,6 +3,8 @@ import { Density } from '../../hooks/use-density.js';
|
|
|
3
3
|
import { SessionEvent, SessionInput } from './SessionViewer.model.js';
|
|
4
4
|
import { SessionThemeOverride } from './SessionViewerMenu.js';
|
|
5
5
|
import { ApprovalDecisionFields, ApprovalKind, ApprovalRequest } from './approval-request.js';
|
|
6
|
+
import { SessionTokenSizer } from './session-token-sizing.js';
|
|
7
|
+
export type { SessionTokenSizer, SessionTokenSize, SessionTokenSizingRequest, SessionTokenSizingResult } from './session-token-sizing.js';
|
|
6
8
|
export type { SessionEntry, SessionEvent, SessionInput, SessionActionMeta, } from './SessionViewer.model.js';
|
|
7
9
|
export type { SessionThemeOverride } from './SessionViewerMenu.js';
|
|
8
10
|
export interface SessionPendingTool {
|
|
@@ -26,6 +28,8 @@ export interface SessionToolDecision extends ApprovalDecisionFields {
|
|
|
26
28
|
message?: string;
|
|
27
29
|
}
|
|
28
30
|
export interface SessionViewerProps {
|
|
31
|
+
/** Explicit menu actions only; never invoked automatically when a transcript loads. */
|
|
32
|
+
sizeTokens?: SessionTokenSizer;
|
|
29
33
|
/** A captain session: parsed `SessionEntry[]` or raw log text (JSON / JSONL). */
|
|
30
34
|
session: SessionInput;
|
|
31
35
|
className?: string;
|
|
@@ -84,5 +88,5 @@ export interface SessionViewerProps {
|
|
|
84
88
|
* `captain history` filtering — toggle density and hide categories, tools or
|
|
85
89
|
* sources.
|
|
86
90
|
*/
|
|
87
|
-
export declare function SessionViewer({ session, className, defaultExpanded, showThinking, showHeader, showContextMeter, showMenu, headerActions, menuHeader, menuContainer, defaultDensity, defaultTheme, scrollable, windowSize, batchSize, scrollResetKey, showRowMetadata, showRaw, renderMessageBadge, pendingTools, onPendingToolDecision, }: SessionViewerProps): import("react").JSX.Element;
|
|
91
|
+
export declare function SessionViewer({ session, className, defaultExpanded, showThinking, showHeader, showContextMeter, showMenu, headerActions, menuHeader, menuContainer, defaultDensity, defaultTheme, scrollable, windowSize, batchSize, scrollResetKey, showRowMetadata, showRaw, renderMessageBadge, pendingTools, onPendingToolDecision, sizeTokens, }: SessionViewerProps): import("react").JSX.Element;
|
|
88
92
|
//# sourceMappingURL=SessionViewer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SessionViewer.d.ts","sourceRoot":"","sources":["../../../src/data/ai/SessionViewer.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAK1D,OAAO,EAAmB,KAAK,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAGxE,OAAO,EAIL,KAAK,YAAY,EACjB,KAAK,YAAY,EAClB,MAAM,uBAAuB,CAAC;AAa/B,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,KAAK,EACV,sBAAsB,EACtB,YAAY,EACZ,eAAe,EAChB,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"SessionViewer.d.ts","sourceRoot":"","sources":["../../../src/data/ai/SessionViewer.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAK1D,OAAO,EAAmB,KAAK,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAGxE,OAAO,EAIL,KAAK,YAAY,EACjB,KAAK,YAAY,EAClB,MAAM,uBAAuB,CAAC;AAa/B,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,KAAK,EACV,sBAAsB,EACtB,YAAY,EACZ,eAAe,EAChB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAEhE,YAAY,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,yBAAyB,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAEvI,YAAY,EACV,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,iBAAiB,GAClB,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAEhE,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;qCACiC;IACjC,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,gEAAgE;IAChE,OAAO,CAAC,EAAE,eAAe,CAAC;CAC3B;AAED;;gCAEgC;AAChC,MAAM,WAAW,mBAAoB,SAAQ,sBAAsB;IACjE,KAAK,EAAE,YAAY,CAAC;IACpB,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,kBAAkB;IAEjC,uFAAuF;IACvF,UAAU,CAAC,EAAE,iBAAiB,CAAC;IAC/B,iFAAiF;IACjF,OAAO,EAAE,YAAY,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0EAA0E;IAC1E,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,wEAAwE;IACxE,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,yEAAyE;IACzE,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,kEAAkE;IAClE,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,sFAAsF;IACtF,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,qEAAqE;IACrE,aAAa,CAAC,EAAE,SAAS,CAAC;IAC1B,2DAA2D;IAC3D,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB;;;qEAGiE;IACjE,aAAa,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAC/B,8EAA8E;IAC9E,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,iFAAiF;IACjF,YAAY,CAAC,EAAE,oBAAoB,CAAC;IACpC;;;;iCAI6B;IAC7B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,yEAAyE;IACzE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qFAAqF;IACrF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mFAAmF;IACnF,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kFAAkF;IAClF,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,kFAAkF;IAClF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,yDAAyD;IACzD,kBAAkB,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,SAAS,CAAC;IACxD,YAAY,CAAC,EAAE,SAAS,kBAAkB,EAAE,CAAC;IAC7C,qBAAqB,CAAC,EAClB,CAAC,CAAC,QAAQ,EAAE,mBAAmB,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,GACzD,SAAS,CAAC;CACf;AASD;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,EAC5B,OAAO,EACP,SAAS,EACT,eAAuB,EACvB,YAAmB,EACnB,UAAiB,EACjB,gBAAuB,EACvB,QAAe,EACf,aAAa,EACb,UAAU,EACV,aAAa,EACb,cAAc,EACd,YAAY,EACZ,UAAkB,EAClB,UAAe,EACf,SAAc,EACd,cAAc,EACd,eAAuB,EACvB,OAAe,EACf,kBAAkB,EAClB,YAAiB,EACjB,qBAAqB,EACrB,UAAU,GACX,EAAE,kBAAkB,+BAoPpB"}
|
|
@@ -22,7 +22,7 @@ function SessionContextMeter({
|
|
|
22
22
|
ContextMeter.ContextMeter,
|
|
23
23
|
{
|
|
24
24
|
mode,
|
|
25
|
-
usedPercent: context ? 100 - context.freePercent : 0,
|
|
25
|
+
usedPercent: context ? 100 - context.freePercent : void 0,
|
|
26
26
|
...context ? {
|
|
27
27
|
usedTokens: context.usedTokens,
|
|
28
28
|
windowTokens: context.windowTokens
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SessionViewer.header.cjs","sources":["../../../src/data/ai/SessionViewer.header.tsx"],"sourcesContent":["import { ContextMeter, type ContextMeterMode } from \"../chat/ContextMeter\";\nimport { providerIcon, providerIconColor } from \"../chat/provider-icons\";\nimport { Icon } from \"../Icon\";\nimport { PERMISSION_MODE_ICONS } from \"./agent-action-icons\";\nimport { costTotal, tokenTotal } from \"./session-cost\";\nimport { sessionTone } from \"./session-tones\";\nimport type { SessionMetadataSummary } from \"./SessionViewer.model\";\nimport { SPEC_PERMISSION_MODES } from \"./SpecRuntimeEditor.model\";\n\nfunction hasContextMeterMetadata(metadata: SessionMetadataSummary) {\n return Boolean(metadata.context || metadata.sessionId || metadata.model);\n}\n\nexport function SessionContextMeter({\n metadata,\n mode,\n}: {\n metadata: SessionMetadataSummary;\n mode: ContextMeterMode;\n}) {\n if (!hasContextMeterMetadata(metadata)) return null;\n const context = metadata.context;\n const modelIcon = metadata.provider\n ? providerIcon(metadata.provider)\n : undefined;\n\n return (\n <ContextMeter\n mode={mode}\n usedPercent={context ? 100 - context.freePercent : 0}\n {...(context\n ? {\n usedTokens: context.usedTokens,\n windowTokens: context.windowTokens,\n }\n : {})}\n {...(metadata.sessionId ? { sessionId: metadata.sessionId } : {})}\n {...(metadata.executionMode\n ? { executionMode: metadata.executionMode }\n : {})}\n {...(metadata.model ? { model: metadata.model } : {})}\n {...(metadata.reasoningEffort\n ? { effort: metadata.reasoningEffort }\n : {})}\n {...(modelIcon ? { modelIcon } : {})}\n {...(metadata.provider\n ? {\n provider: metadata.provider,\n modelIconClassName: providerIconColor(metadata.provider),\n }\n : {})}\n {...(metadata.usage\n ? {\n tokens: {\n input: metadata.usage.inputTokens,\n output: metadata.usage.outputTokens,\n reasoning: metadata.usage.reasoningTokens,\n cacheRead: metadata.usage.cacheReadTokens,\n cacheWrite: metadata.usage.cacheWriteTokens,\n total: tokenTotal(metadata.usage),\n },\n }\n : {})}\n {...(metadata.cost\n ? {\n cost: {\n input: metadata.cost.inputCost,\n output: metadata.cost.outputCost,\n reasoning: metadata.cost.reasoningCost,\n cacheRead: metadata.cost.cacheReadCost,\n cacheWrite: metadata.cost.cacheWriteCost,\n total: costTotal(metadata.cost),\n },\n }\n : {})}\n {...(metadata.budget ? { budget: metadata.budget } : {})}\n />\n );\n}\n\nexport function SessionMetadataBadges({\n metadata,\n showContextMeter,\n}: {\n metadata: SessionMetadataSummary;\n showContextMeter: boolean;\n}) {\n const capabilityBadges = [\n countBadge(\"tool\", metadata.capabilities?.tools),\n countBadge(\"mcp\", metadata.capabilities?.pendingMcpServers),\n countBadge(\"agent\", metadata.capabilities?.agents),\n countBadge(\"skill\", metadata.capabilities?.skills),\n ].filter(Boolean) as Array<{ key: string; label: string; title?: string }>;\n const badges: Array<{ key: string; label: string; title?: string }> = [\n ...(metadata.turns?.length\n ? [{ key: \"turns\", label: countLabel(metadata.turns.length, \"turn\") }]\n : []),\n ...capabilityBadges,\n ...(!metadata.context && metadata.budget\n ? [{ key: \"budget\", label: budgetLabel(metadata.budget) }]\n : []),\n ...(metadata.events?.length\n ? [{ key: \"events\", label: countLabel(metadata.events.length, \"event\") }]\n : []),\n ];\n const permissionMode = permissionModeBadge(metadata.permissionMode);\n const renderContextMeter =\n showContextMeter && hasContextMeterMetadata(metadata);\n if (badges.length === 0 && !permissionMode && !renderContextMeter) {\n return null;\n }\n\n return (\n <>\n {badges.map((badge) => (\n <span\n key={badge.key}\n title={badge.title}\n className=\"inline-flex max-w-40 items-center rounded border border-border px-1.5 py-0.5 text-[11px] text-muted-foreground\"\n >\n <span className=\"truncate\">{badge.label}</span>\n </span>\n ))}\n {permissionMode && (\n <span\n title={`Permission mode: ${permissionMode.label}`}\n className=\"inline-flex max-w-40 items-center gap-1 rounded border border-border px-1.5 py-0.5 text-[11px] text-muted-foreground\"\n >\n {permissionMode.icon && (\n <Icon\n icon={permissionMode.icon}\n className={`size-3 shrink-0 ${sessionTone(permissionMode.tone).text}`}\n />\n )}\n <span className=\"truncate\">{permissionMode.label}</span>\n </span>\n )}\n {renderContextMeter ? (\n <SessionContextMeter metadata={metadata} mode=\"bar\" />\n ) : null}\n </>\n );\n}\n\nfunction permissionModeBadge(mode: string | undefined) {\n if (!mode) return undefined;\n const posture = SPEC_PERMISSION_MODES.find((candidate) => candidate === mode);\n const known = posture ? PERMISSION_MODE_ICONS[posture] : undefined;\n return {\n label: known?.label ?? mode,\n icon: known?.icon,\n tone: known?.tone ?? (\"slate\" as const),\n };\n}\n\nfunction countBadge(label: string, values: string[] | undefined) {\n const count = values?.length ?? 0;\n if (!count) return null;\n return {\n key: label,\n label: countLabel(count, label),\n title: values?.join(\", \"),\n };\n}\n\nfunction countLabel(count: number, label: string) {\n if (label === \"mcp\") return `${count} mcp`;\n return `${count} ${label}${count === 1 ? \"\" : \"s\"}`;\n}\n\nfunction budgetLabel(budget: {\n used?: number;\n total?: number;\n remaining?: number;\n}) {\n if (budget.total !== undefined && budget.total > 0) {\n return `budget ${formatUSD(budget.used ?? 0)}/${formatUSD(budget.total)}`;\n }\n if (budget.remaining !== undefined)\n return `budget ${formatUSD(budget.remaining)} left`;\n if (budget.used !== undefined) return `budget ${formatUSD(budget.used)} used`;\n return \"budget\";\n}\n\nfunction formatUSD(value: number) {\n if (value < 1 || !Number.isInteger(value)) return `$${value.toFixed(2)}`;\n return `$${value.toFixed(0)}`;\n}\n"],"names":["providerIcon","jsx","ContextMeter","providerIconColor","tokenTotal","costTotal","jsxs","Fragment","Icon","sessionTone","SPEC_PERMISSION_MODES","PERMISSION_MODE_ICONS"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SessionViewer.header.cjs","sources":["../../../src/data/ai/SessionViewer.header.tsx"],"sourcesContent":["import { ContextMeter, type ContextMeterMode } from \"../chat/ContextMeter\";\nimport { providerIcon, providerIconColor } from \"../chat/provider-icons\";\nimport { Icon } from \"../Icon\";\nimport { PERMISSION_MODE_ICONS } from \"./agent-action-icons\";\nimport { costTotal, tokenTotal } from \"./session-cost\";\nimport { sessionTone } from \"./session-tones\";\nimport type { SessionMetadataSummary } from \"./SessionViewer.model\";\nimport { SPEC_PERMISSION_MODES } from \"./SpecRuntimeEditor.model\";\n\nfunction hasContextMeterMetadata(metadata: SessionMetadataSummary) {\n return Boolean(metadata.context || metadata.sessionId || metadata.model);\n}\n\nexport function SessionContextMeter({\n metadata,\n mode,\n}: {\n metadata: SessionMetadataSummary;\n mode: ContextMeterMode;\n}) {\n if (!hasContextMeterMetadata(metadata)) return null;\n const context = metadata.context;\n const modelIcon = metadata.provider\n ? providerIcon(metadata.provider)\n : undefined;\n\n return (\n <ContextMeter\n mode={mode}\n usedPercent={context ? 100 - context.freePercent : undefined}\n {...(context\n ? {\n usedTokens: context.usedTokens,\n windowTokens: context.windowTokens,\n }\n : {})}\n {...(metadata.sessionId ? { sessionId: metadata.sessionId } : {})}\n {...(metadata.executionMode\n ? { executionMode: metadata.executionMode }\n : {})}\n {...(metadata.model ? { model: metadata.model } : {})}\n {...(metadata.reasoningEffort\n ? { effort: metadata.reasoningEffort }\n : {})}\n {...(modelIcon ? { modelIcon } : {})}\n {...(metadata.provider\n ? {\n provider: metadata.provider,\n modelIconClassName: providerIconColor(metadata.provider),\n }\n : {})}\n {...(metadata.usage\n ? {\n tokens: {\n input: metadata.usage.inputTokens,\n output: metadata.usage.outputTokens,\n reasoning: metadata.usage.reasoningTokens,\n cacheRead: metadata.usage.cacheReadTokens,\n cacheWrite: metadata.usage.cacheWriteTokens,\n total: tokenTotal(metadata.usage),\n },\n }\n : {})}\n {...(metadata.cost\n ? {\n cost: {\n input: metadata.cost.inputCost,\n output: metadata.cost.outputCost,\n reasoning: metadata.cost.reasoningCost,\n cacheRead: metadata.cost.cacheReadCost,\n cacheWrite: metadata.cost.cacheWriteCost,\n total: costTotal(metadata.cost),\n },\n }\n : {})}\n {...(metadata.budget ? { budget: metadata.budget } : {})}\n />\n );\n}\n\nexport function SessionMetadataBadges({\n metadata,\n showContextMeter,\n}: {\n metadata: SessionMetadataSummary;\n showContextMeter: boolean;\n}) {\n const capabilityBadges = [\n countBadge(\"tool\", metadata.capabilities?.tools),\n countBadge(\"mcp\", metadata.capabilities?.pendingMcpServers),\n countBadge(\"agent\", metadata.capabilities?.agents),\n countBadge(\"skill\", metadata.capabilities?.skills),\n ].filter(Boolean) as Array<{ key: string; label: string; title?: string }>;\n const badges: Array<{ key: string; label: string; title?: string }> = [\n ...(metadata.turns?.length\n ? [{ key: \"turns\", label: countLabel(metadata.turns.length, \"turn\") }]\n : []),\n ...capabilityBadges,\n ...(!metadata.context && metadata.budget\n ? [{ key: \"budget\", label: budgetLabel(metadata.budget) }]\n : []),\n ...(metadata.events?.length\n ? [{ key: \"events\", label: countLabel(metadata.events.length, \"event\") }]\n : []),\n ];\n const permissionMode = permissionModeBadge(metadata.permissionMode);\n const renderContextMeter =\n showContextMeter && hasContextMeterMetadata(metadata);\n if (badges.length === 0 && !permissionMode && !renderContextMeter) {\n return null;\n }\n\n return (\n <>\n {badges.map((badge) => (\n <span\n key={badge.key}\n title={badge.title}\n className=\"inline-flex max-w-40 items-center rounded border border-border px-1.5 py-0.5 text-[11px] text-muted-foreground\"\n >\n <span className=\"truncate\">{badge.label}</span>\n </span>\n ))}\n {permissionMode && (\n <span\n title={`Permission mode: ${permissionMode.label}`}\n className=\"inline-flex max-w-40 items-center gap-1 rounded border border-border px-1.5 py-0.5 text-[11px] text-muted-foreground\"\n >\n {permissionMode.icon && (\n <Icon\n icon={permissionMode.icon}\n className={`size-3 shrink-0 ${sessionTone(permissionMode.tone).text}`}\n />\n )}\n <span className=\"truncate\">{permissionMode.label}</span>\n </span>\n )}\n {renderContextMeter ? (\n <SessionContextMeter metadata={metadata} mode=\"bar\" />\n ) : null}\n </>\n );\n}\n\nfunction permissionModeBadge(mode: string | undefined) {\n if (!mode) return undefined;\n const posture = SPEC_PERMISSION_MODES.find((candidate) => candidate === mode);\n const known = posture ? PERMISSION_MODE_ICONS[posture] : undefined;\n return {\n label: known?.label ?? mode,\n icon: known?.icon,\n tone: known?.tone ?? (\"slate\" as const),\n };\n}\n\nfunction countBadge(label: string, values: string[] | undefined) {\n const count = values?.length ?? 0;\n if (!count) return null;\n return {\n key: label,\n label: countLabel(count, label),\n title: values?.join(\", \"),\n };\n}\n\nfunction countLabel(count: number, label: string) {\n if (label === \"mcp\") return `${count} mcp`;\n return `${count} ${label}${count === 1 ? \"\" : \"s\"}`;\n}\n\nfunction budgetLabel(budget: {\n used?: number;\n total?: number;\n remaining?: number;\n}) {\n if (budget.total !== undefined && budget.total > 0) {\n return `budget ${formatUSD(budget.used ?? 0)}/${formatUSD(budget.total)}`;\n }\n if (budget.remaining !== undefined)\n return `budget ${formatUSD(budget.remaining)} left`;\n if (budget.used !== undefined) return `budget ${formatUSD(budget.used)} used`;\n return \"budget\";\n}\n\nfunction formatUSD(value: number) {\n if (value < 1 || !Number.isInteger(value)) return `$${value.toFixed(2)}`;\n return `$${value.toFixed(0)}`;\n}\n"],"names":["providerIcon","jsx","ContextMeter","providerIconColor","tokenTotal","costTotal","jsxs","Fragment","Icon","sessionTone","SPEC_PERMISSION_MODES","PERMISSION_MODE_ICONS"],"mappings":"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"}
|
|
@@ -20,7 +20,7 @@ function SessionContextMeter({
|
|
|
20
20
|
ContextMeter,
|
|
21
21
|
{
|
|
22
22
|
mode,
|
|
23
|
-
usedPercent: context ? 100 - context.freePercent : 0,
|
|
23
|
+
usedPercent: context ? 100 - context.freePercent : void 0,
|
|
24
24
|
...context ? {
|
|
25
25
|
usedTokens: context.usedTokens,
|
|
26
26
|
windowTokens: context.windowTokens
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SessionViewer.header.js","sources":["../../../src/data/ai/SessionViewer.header.tsx"],"sourcesContent":["import { ContextMeter, type ContextMeterMode } from \"../chat/ContextMeter\";\nimport { providerIcon, providerIconColor } from \"../chat/provider-icons\";\nimport { Icon } from \"../Icon\";\nimport { PERMISSION_MODE_ICONS } from \"./agent-action-icons\";\nimport { costTotal, tokenTotal } from \"./session-cost\";\nimport { sessionTone } from \"./session-tones\";\nimport type { SessionMetadataSummary } from \"./SessionViewer.model\";\nimport { SPEC_PERMISSION_MODES } from \"./SpecRuntimeEditor.model\";\n\nfunction hasContextMeterMetadata(metadata: SessionMetadataSummary) {\n return Boolean(metadata.context || metadata.sessionId || metadata.model);\n}\n\nexport function SessionContextMeter({\n metadata,\n mode,\n}: {\n metadata: SessionMetadataSummary;\n mode: ContextMeterMode;\n}) {\n if (!hasContextMeterMetadata(metadata)) return null;\n const context = metadata.context;\n const modelIcon = metadata.provider\n ? providerIcon(metadata.provider)\n : undefined;\n\n return (\n <ContextMeter\n mode={mode}\n usedPercent={context ? 100 - context.freePercent : 0}\n {...(context\n ? {\n usedTokens: context.usedTokens,\n windowTokens: context.windowTokens,\n }\n : {})}\n {...(metadata.sessionId ? { sessionId: metadata.sessionId } : {})}\n {...(metadata.executionMode\n ? { executionMode: metadata.executionMode }\n : {})}\n {...(metadata.model ? { model: metadata.model } : {})}\n {...(metadata.reasoningEffort\n ? { effort: metadata.reasoningEffort }\n : {})}\n {...(modelIcon ? { modelIcon } : {})}\n {...(metadata.provider\n ? {\n provider: metadata.provider,\n modelIconClassName: providerIconColor(metadata.provider),\n }\n : {})}\n {...(metadata.usage\n ? {\n tokens: {\n input: metadata.usage.inputTokens,\n output: metadata.usage.outputTokens,\n reasoning: metadata.usage.reasoningTokens,\n cacheRead: metadata.usage.cacheReadTokens,\n cacheWrite: metadata.usage.cacheWriteTokens,\n total: tokenTotal(metadata.usage),\n },\n }\n : {})}\n {...(metadata.cost\n ? {\n cost: {\n input: metadata.cost.inputCost,\n output: metadata.cost.outputCost,\n reasoning: metadata.cost.reasoningCost,\n cacheRead: metadata.cost.cacheReadCost,\n cacheWrite: metadata.cost.cacheWriteCost,\n total: costTotal(metadata.cost),\n },\n }\n : {})}\n {...(metadata.budget ? { budget: metadata.budget } : {})}\n />\n );\n}\n\nexport function SessionMetadataBadges({\n metadata,\n showContextMeter,\n}: {\n metadata: SessionMetadataSummary;\n showContextMeter: boolean;\n}) {\n const capabilityBadges = [\n countBadge(\"tool\", metadata.capabilities?.tools),\n countBadge(\"mcp\", metadata.capabilities?.pendingMcpServers),\n countBadge(\"agent\", metadata.capabilities?.agents),\n countBadge(\"skill\", metadata.capabilities?.skills),\n ].filter(Boolean) as Array<{ key: string; label: string; title?: string }>;\n const badges: Array<{ key: string; label: string; title?: string }> = [\n ...(metadata.turns?.length\n ? [{ key: \"turns\", label: countLabel(metadata.turns.length, \"turn\") }]\n : []),\n ...capabilityBadges,\n ...(!metadata.context && metadata.budget\n ? [{ key: \"budget\", label: budgetLabel(metadata.budget) }]\n : []),\n ...(metadata.events?.length\n ? [{ key: \"events\", label: countLabel(metadata.events.length, \"event\") }]\n : []),\n ];\n const permissionMode = permissionModeBadge(metadata.permissionMode);\n const renderContextMeter =\n showContextMeter && hasContextMeterMetadata(metadata);\n if (badges.length === 0 && !permissionMode && !renderContextMeter) {\n return null;\n }\n\n return (\n <>\n {badges.map((badge) => (\n <span\n key={badge.key}\n title={badge.title}\n className=\"inline-flex max-w-40 items-center rounded border border-border px-1.5 py-0.5 text-[11px] text-muted-foreground\"\n >\n <span className=\"truncate\">{badge.label}</span>\n </span>\n ))}\n {permissionMode && (\n <span\n title={`Permission mode: ${permissionMode.label}`}\n className=\"inline-flex max-w-40 items-center gap-1 rounded border border-border px-1.5 py-0.5 text-[11px] text-muted-foreground\"\n >\n {permissionMode.icon && (\n <Icon\n icon={permissionMode.icon}\n className={`size-3 shrink-0 ${sessionTone(permissionMode.tone).text}`}\n />\n )}\n <span className=\"truncate\">{permissionMode.label}</span>\n </span>\n )}\n {renderContextMeter ? (\n <SessionContextMeter metadata={metadata} mode=\"bar\" />\n ) : null}\n </>\n );\n}\n\nfunction permissionModeBadge(mode: string | undefined) {\n if (!mode) return undefined;\n const posture = SPEC_PERMISSION_MODES.find((candidate) => candidate === mode);\n const known = posture ? PERMISSION_MODE_ICONS[posture] : undefined;\n return {\n label: known?.label ?? mode,\n icon: known?.icon,\n tone: known?.tone ?? (\"slate\" as const),\n };\n}\n\nfunction countBadge(label: string, values: string[] | undefined) {\n const count = values?.length ?? 0;\n if (!count) return null;\n return {\n key: label,\n label: countLabel(count, label),\n title: values?.join(\", \"),\n };\n}\n\nfunction countLabel(count: number, label: string) {\n if (label === \"mcp\") return `${count} mcp`;\n return `${count} ${label}${count === 1 ? \"\" : \"s\"}`;\n}\n\nfunction budgetLabel(budget: {\n used?: number;\n total?: number;\n remaining?: number;\n}) {\n if (budget.total !== undefined && budget.total > 0) {\n return `budget ${formatUSD(budget.used ?? 0)}/${formatUSD(budget.total)}`;\n }\n if (budget.remaining !== undefined)\n return `budget ${formatUSD(budget.remaining)} left`;\n if (budget.used !== undefined) return `budget ${formatUSD(budget.used)} used`;\n return \"budget\";\n}\n\nfunction formatUSD(value: number) {\n if (value < 1 || !Number.isInteger(value)) return `$${value.toFixed(2)}`;\n return `$${value.toFixed(0)}`;\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SessionViewer.header.js","sources":["../../../src/data/ai/SessionViewer.header.tsx"],"sourcesContent":["import { ContextMeter, type ContextMeterMode } from \"../chat/ContextMeter\";\nimport { providerIcon, providerIconColor } from \"../chat/provider-icons\";\nimport { Icon } from \"../Icon\";\nimport { PERMISSION_MODE_ICONS } from \"./agent-action-icons\";\nimport { costTotal, tokenTotal } from \"./session-cost\";\nimport { sessionTone } from \"./session-tones\";\nimport type { SessionMetadataSummary } from \"./SessionViewer.model\";\nimport { SPEC_PERMISSION_MODES } from \"./SpecRuntimeEditor.model\";\n\nfunction hasContextMeterMetadata(metadata: SessionMetadataSummary) {\n return Boolean(metadata.context || metadata.sessionId || metadata.model);\n}\n\nexport function SessionContextMeter({\n metadata,\n mode,\n}: {\n metadata: SessionMetadataSummary;\n mode: ContextMeterMode;\n}) {\n if (!hasContextMeterMetadata(metadata)) return null;\n const context = metadata.context;\n const modelIcon = metadata.provider\n ? providerIcon(metadata.provider)\n : undefined;\n\n return (\n <ContextMeter\n mode={mode}\n usedPercent={context ? 100 - context.freePercent : undefined}\n {...(context\n ? {\n usedTokens: context.usedTokens,\n windowTokens: context.windowTokens,\n }\n : {})}\n {...(metadata.sessionId ? { sessionId: metadata.sessionId } : {})}\n {...(metadata.executionMode\n ? { executionMode: metadata.executionMode }\n : {})}\n {...(metadata.model ? { model: metadata.model } : {})}\n {...(metadata.reasoningEffort\n ? { effort: metadata.reasoningEffort }\n : {})}\n {...(modelIcon ? { modelIcon } : {})}\n {...(metadata.provider\n ? {\n provider: metadata.provider,\n modelIconClassName: providerIconColor(metadata.provider),\n }\n : {})}\n {...(metadata.usage\n ? {\n tokens: {\n input: metadata.usage.inputTokens,\n output: metadata.usage.outputTokens,\n reasoning: metadata.usage.reasoningTokens,\n cacheRead: metadata.usage.cacheReadTokens,\n cacheWrite: metadata.usage.cacheWriteTokens,\n total: tokenTotal(metadata.usage),\n },\n }\n : {})}\n {...(metadata.cost\n ? {\n cost: {\n input: metadata.cost.inputCost,\n output: metadata.cost.outputCost,\n reasoning: metadata.cost.reasoningCost,\n cacheRead: metadata.cost.cacheReadCost,\n cacheWrite: metadata.cost.cacheWriteCost,\n total: costTotal(metadata.cost),\n },\n }\n : {})}\n {...(metadata.budget ? { budget: metadata.budget } : {})}\n />\n );\n}\n\nexport function SessionMetadataBadges({\n metadata,\n showContextMeter,\n}: {\n metadata: SessionMetadataSummary;\n showContextMeter: boolean;\n}) {\n const capabilityBadges = [\n countBadge(\"tool\", metadata.capabilities?.tools),\n countBadge(\"mcp\", metadata.capabilities?.pendingMcpServers),\n countBadge(\"agent\", metadata.capabilities?.agents),\n countBadge(\"skill\", metadata.capabilities?.skills),\n ].filter(Boolean) as Array<{ key: string; label: string; title?: string }>;\n const badges: Array<{ key: string; label: string; title?: string }> = [\n ...(metadata.turns?.length\n ? [{ key: \"turns\", label: countLabel(metadata.turns.length, \"turn\") }]\n : []),\n ...capabilityBadges,\n ...(!metadata.context && metadata.budget\n ? [{ key: \"budget\", label: budgetLabel(metadata.budget) }]\n : []),\n ...(metadata.events?.length\n ? [{ key: \"events\", label: countLabel(metadata.events.length, \"event\") }]\n : []),\n ];\n const permissionMode = permissionModeBadge(metadata.permissionMode);\n const renderContextMeter =\n showContextMeter && hasContextMeterMetadata(metadata);\n if (badges.length === 0 && !permissionMode && !renderContextMeter) {\n return null;\n }\n\n return (\n <>\n {badges.map((badge) => (\n <span\n key={badge.key}\n title={badge.title}\n className=\"inline-flex max-w-40 items-center rounded border border-border px-1.5 py-0.5 text-[11px] text-muted-foreground\"\n >\n <span className=\"truncate\">{badge.label}</span>\n </span>\n ))}\n {permissionMode && (\n <span\n title={`Permission mode: ${permissionMode.label}`}\n className=\"inline-flex max-w-40 items-center gap-1 rounded border border-border px-1.5 py-0.5 text-[11px] text-muted-foreground\"\n >\n {permissionMode.icon && (\n <Icon\n icon={permissionMode.icon}\n className={`size-3 shrink-0 ${sessionTone(permissionMode.tone).text}`}\n />\n )}\n <span className=\"truncate\">{permissionMode.label}</span>\n </span>\n )}\n {renderContextMeter ? (\n <SessionContextMeter metadata={metadata} mode=\"bar\" />\n ) : null}\n </>\n );\n}\n\nfunction permissionModeBadge(mode: string | undefined) {\n if (!mode) return undefined;\n const posture = SPEC_PERMISSION_MODES.find((candidate) => candidate === mode);\n const known = posture ? PERMISSION_MODE_ICONS[posture] : undefined;\n return {\n label: known?.label ?? mode,\n icon: known?.icon,\n tone: known?.tone ?? (\"slate\" as const),\n };\n}\n\nfunction countBadge(label: string, values: string[] | undefined) {\n const count = values?.length ?? 0;\n if (!count) return null;\n return {\n key: label,\n label: countLabel(count, label),\n title: values?.join(\", \"),\n };\n}\n\nfunction countLabel(count: number, label: string) {\n if (label === \"mcp\") return `${count} mcp`;\n return `${count} ${label}${count === 1 ? \"\" : \"s\"}`;\n}\n\nfunction budgetLabel(budget: {\n used?: number;\n total?: number;\n remaining?: number;\n}) {\n if (budget.total !== undefined && budget.total > 0) {\n return `budget ${formatUSD(budget.used ?? 0)}/${formatUSD(budget.total)}`;\n }\n if (budget.remaining !== undefined)\n return `budget ${formatUSD(budget.remaining)} left`;\n if (budget.used !== undefined) return `budget ${formatUSD(budget.used)} used`;\n return \"budget\";\n}\n\nfunction formatUSD(value: number) {\n if (value < 1 || !Number.isInteger(value)) return `$${value.toFixed(2)}`;\n return `$${value.toFixed(0)}`;\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -13,6 +13,7 @@ import { SessionMetadataBadges } from "./SessionViewer.header.js";
|
|
|
13
13
|
import { collectSessionFilters, isEncryptedReasoning, isEventVisible } from "./session-categories.js";
|
|
14
14
|
import { SessionViewerMenu } from "./SessionViewerMenu.js";
|
|
15
15
|
import { useSessionScroll } from "./use-session-scroll.js";
|
|
16
|
+
import { useSessionTokenSizing, SessionTokenContext } from "./use-session-token-sizing.js";
|
|
16
17
|
import { UiRobotAi } from "../../icons/components/UiRobotAi.js";
|
|
17
18
|
import { UiArrowDown } from "../../icons/components/UiArrowDown.js";
|
|
18
19
|
function toggleInSet(set, value) {
|
|
@@ -42,7 +43,8 @@ function SessionViewer({
|
|
|
42
43
|
showRaw = false,
|
|
43
44
|
renderMessageBadge,
|
|
44
45
|
pendingTools = [],
|
|
45
|
-
onPendingToolDecision
|
|
46
|
+
onPendingToolDecision,
|
|
47
|
+
sizeTokens
|
|
46
48
|
}) {
|
|
47
49
|
var _a, _b;
|
|
48
50
|
const allEvents = useMemo(
|
|
@@ -51,6 +53,7 @@ function SessionViewer({
|
|
|
51
53
|
);
|
|
52
54
|
const displayItems = useMemo(() => collapseWaitRuns(allEvents), [allEvents]);
|
|
53
55
|
const metadata = useMemo(() => getSessionMetadata(session), [session]);
|
|
56
|
+
const tokenSizing = useSessionTokenSizing(session, allEvents, sizeTokens);
|
|
54
57
|
const pageDensity = useDensityValue();
|
|
55
58
|
const [densityOverride, setDensityOverride] = useState(
|
|
56
59
|
defaultDensity
|
|
@@ -66,6 +69,7 @@ function SessionViewer({
|
|
|
66
69
|
const [showThinkingOverride, setShowThinkingOverride] = useState(void 0);
|
|
67
70
|
const effectiveShowThinking = showThinkingOverride ?? showThinking;
|
|
68
71
|
const [showEncryptedReasoning, setShowEncryptedReasoning] = useState(false);
|
|
72
|
+
const [showEstimatedToolCost, setShowEstimatedToolCost] = useState(false);
|
|
69
73
|
const filters = useMemo(() => collectSessionFilters(allEvents), [allEvents]);
|
|
70
74
|
const hasThinking = useMemo(
|
|
71
75
|
() => allEvents.some((e) => e.kind === "thinking"),
|
|
@@ -132,7 +136,10 @@ function SessionViewer({
|
|
|
132
136
|
hasThinking,
|
|
133
137
|
hasEncryptedReasoning,
|
|
134
138
|
showEncryptedReasoning,
|
|
135
|
-
onToggleEncryptedReasoning: () => setShowEncryptedReasoning((shown) => !shown)
|
|
139
|
+
onToggleEncryptedReasoning: () => setShowEncryptedReasoning((shown) => !shown),
|
|
140
|
+
showEstimatedToolCost,
|
|
141
|
+
onToggleEstimatedToolCost: () => setShowEstimatedToolCost((shown) => !shown),
|
|
142
|
+
...tokenSizing.estimateAll ? { onEstimateTokens: tokenSizing.estimateAll, onCalculateMissingTokens: tokenSizing.calculateMissing, estimatingTokens: tokenSizing.pending } : {}
|
|
136
143
|
}
|
|
137
144
|
) : null;
|
|
138
145
|
const inlineMenu = menu && !menuContainer;
|
|
@@ -146,6 +153,7 @@ function SessionViewer({
|
|
|
146
153
|
{
|
|
147
154
|
group: item,
|
|
148
155
|
last,
|
|
156
|
+
showEstimatedToolCost,
|
|
149
157
|
defaultExpanded,
|
|
150
158
|
showRowMetadata,
|
|
151
159
|
showRaw,
|
|
@@ -158,6 +166,7 @@ function SessionViewer({
|
|
|
158
166
|
{
|
|
159
167
|
event: item,
|
|
160
168
|
initialPrompt: item.id === firstUserEventId,
|
|
169
|
+
showEstimatedToolCost,
|
|
161
170
|
last,
|
|
162
171
|
defaultExpanded,
|
|
163
172
|
showRowMetadata,
|
|
@@ -178,7 +187,7 @@ function SessionViewer({
|
|
|
178
187
|
className
|
|
179
188
|
),
|
|
180
189
|
...dataAttrs,
|
|
181
|
-
children: /* @__PURE__ */ jsxs(DensityValueProvider, { density: effectiveDensity, children: [
|
|
190
|
+
children: /* @__PURE__ */ jsx(SessionTokenContext.Provider, { value: tokenSizing.context, children: /* @__PURE__ */ jsxs(DensityValueProvider, { density: effectiveDensity, children: [
|
|
182
191
|
menu && menuContainer && createPortal(menu, menuContainer),
|
|
183
192
|
(showHeader || headerActions || inlineMenu) && /* @__PURE__ */ jsxs(
|
|
184
193
|
"div",
|
|
@@ -250,7 +259,7 @@ function SessionViewer({
|
|
|
250
259
|
}
|
|
251
260
|
)
|
|
252
261
|
] }) : list
|
|
253
|
-
] })
|
|
262
|
+
] }) })
|
|
254
263
|
}
|
|
255
264
|
);
|
|
256
265
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SessionViewer.js","sources":["../../../src/data/ai/SessionViewer.tsx"],"sourcesContent":["import { useMemo, useState, type ReactNode } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { cn } from \"../../lib/utils\";\nimport { Icon } from \"../Icon\";\nimport { Button } from \"../../components/button\";\nimport { useDensityValue, type Density } from \"../../hooks/use-density\";\nimport { DensityValueProvider } from \"../../hooks/density-provider\";\nimport { UiArrowDown, UiRobotAi } from \"../../icons\";\nimport {\n getSessionMetadata,\n normalizeSession,\n summarizeSession,\n type SessionEvent,\n type SessionInput,\n} from \"./SessionViewer.model\";\nimport {\n collapseWaitRuns,\n isSessionEventGroup,\n} from \"./SessionViewer.grouping\";\nimport { SessionRow, WaitGroupRow } from \"./SessionViewer.rows\";\nimport { SessionMetadataBadges } from \"./SessionViewer.header\";\nimport {\n collectSessionFilters,\n isEncryptedReasoning,\n isEventVisible,\n type SessionCategory,\n} from \"./session-categories\";\nimport {\n SessionViewerMenu,\n type SessionThemeOverride,\n} from \"./SessionViewerMenu\";\nimport { useSessionScroll } from \"./use-session-scroll\";\nimport type {\n ApprovalDecisionFields,\n ApprovalKind,\n ApprovalRequest,\n} from \"./approval-request\";\n\nexport type {\n SessionEntry,\n SessionEvent,\n SessionInput,\n SessionActionMeta,\n} from \"./SessionViewer.model\";\nexport type { SessionThemeOverride } from \"./SessionViewerMenu\";\n\nexport interface SessionPendingTool {\n tool: string;\n input?: Record<string, unknown>;\n toolCallId?: string;\n approvalId?: string;\n sessionId?: string;\n /** What kind of approval this is. Absent means an untyped tool approval, which\n * renders as Allow / Reject. */\n kind?: ApprovalKind;\n /** The typed approval request; drives the per-kind controls. */\n request?: ApprovalRequest;\n}\n\n/** A decision on one pending tool. `allow`/`message`/`answers` are the original\n * fields; `interrupt`, `scope`, `grants` and `content` are set only for a typed\n * request that offers them. */\nexport interface SessionToolDecision extends ApprovalDecisionFields {\n event: SessionEvent;\n allow: boolean;\n message?: string;\n}\n\nexport interface SessionViewerProps {\n /** A captain session: parsed `SessionEntry[]` or raw log text (JSON / JSONL). */\n session: SessionInput;\n className?: string;\n /** Expand each tool call's input/output by default. Defaults to false. */\n defaultExpanded?: boolean;\n /** Render assistant reasoning (\"thinking\") blocks. Defaults to true. */\n showThinking?: boolean;\n /** Show the summary header (model + action counts). Defaults to true. */\n showHeader?: boolean;\n /** Show context usage in the summary header. Defaults to true. */\n showContextMeter?: boolean;\n /** Show the 3-dot menu (density + category/tool/source filters). Defaults to true. */\n showMenu?: boolean;\n /** Controls rendered beside the 3-dot menu in the summary header. */\n headerActions?: ReactNode;\n /** Host controls rendered at the top of the 3-dot menu. */\n menuHeader?: ReactNode;\n /** Portal the 3-dot menu into this element instead of rendering it inline in\n * the summary header — lets a host place the menu in its own toolbar while the\n * filter/density state stays owned by the viewer. Ignored when `showMenu` is\n * false; falls back to inline rendering when null/undefined. */\n menuContainer?: Element | null;\n /** Initial density override; undefined inherits the page/document density. */\n defaultDensity?: Density;\n /** Initial theme override; undefined inherits the page/document `data-theme`. */\n defaultTheme?: SessionThemeOverride;\n /** Own an internal scroll container that fills its parent's height: render only\n * the newest screenful, stay pinned to the bottom (most recent activity), and\n * backfill older rows as the reader scrolls up. Off by default, so inline\n * consumers keep rendering the whole log in normal page flow. Requires a\n * height-bounded parent. */\n scrollable?: boolean;\n /** Rows rendered on first paint in `scrollable` mode. Defaults to 60. */\n windowSize?: number;\n /** Rows added each time older content loads in `scrollable` mode. Defaults to 40. */\n batchSize?: number;\n /** Stable identity used to reset the transcript window when switching sessions. */\n scrollResetKey?: string;\n /** Show per-row timestamp/source/model/turn/agent metadata. Defaults to false. */\n showRowMetadata?: boolean;\n /** Show a per-row raw JSON payload expander when available. Defaults to false. */\n showRaw?: boolean;\n /** Render content before each assistant message body. */\n renderMessageBadge?: (event: SessionEvent) => ReactNode;\n pendingTools?: readonly SessionPendingTool[];\n onPendingToolDecision?:\n | ((decision: SessionToolDecision) => Promise<void> | void)\n | undefined;\n}\n\nfunction toggleInSet<T>(set: ReadonlySet<T>, value: T): Set<T> {\n const next = new Set(set);\n if (next.has(value)) next.delete(value);\n else next.add(value);\n return next;\n}\n\n/**\n * SessionViewer renders a recorded AI coding-agent session (the captain\n * `pkg/ai/history` JSON schema — Claude Code / Codex transcripts) as a vertical\n * action log. Each entry sits on a tone-colored icon disc from the Flanksource\n * \"Agent Action Icons\" set; user prompts/selections are right-aligned like a\n * chat. Shell commands render inline as bash blocks and file ops as their\n * cwd-relative path — the icon carries the verb. Tool responses expand behind\n * a chevron, rendered bare (no panel chrome). The \"3-dot\" menu mirrors\n * `captain history` filtering — toggle density and hide categories, tools or\n * sources.\n */\nexport function SessionViewer({\n session,\n className,\n defaultExpanded = false,\n showThinking = true,\n showHeader = true,\n showContextMeter = true,\n showMenu = true,\n headerActions,\n menuHeader,\n menuContainer,\n defaultDensity,\n defaultTheme,\n scrollable = false,\n windowSize = 60,\n batchSize = 40,\n scrollResetKey,\n showRowMetadata = false,\n showRaw = false,\n renderMessageBadge,\n pendingTools = [],\n onPendingToolDecision,\n}: SessionViewerProps) {\n const allEvents = useMemo(\n () => mergePendingTools(normalizeSession(session), pendingTools),\n [session, pendingTools],\n );\n const displayItems = useMemo(() => collapseWaitRuns(allEvents), [allEvents]);\n const metadata = useMemo(() => getSessionMetadata(session), [session]);\n\n const pageDensity = useDensityValue();\n const [densityOverride, setDensityOverride] = useState<Density | undefined>(\n defaultDensity,\n );\n const [themeOverride, setThemeOverride] = useState<\n SessionThemeOverride | undefined\n >(defaultTheme);\n const [hiddenCategories, setHiddenCategories] = useState<\n ReadonlySet<SessionCategory>\n >(() => new Set());\n const [hiddenTools, setHiddenTools] = useState<ReadonlySet<string>>(\n () => new Set(),\n );\n const [hiddenSources, setHiddenSources] = useState<ReadonlySet<string>>(\n () => new Set(),\n );\n // Undefined = follow the `showThinking` prop; the menu toggle sets an override.\n const [showThinkingOverride, setShowThinkingOverride] = useState<\n boolean | undefined\n >(undefined);\n const effectiveShowThinking = showThinkingOverride ?? showThinking;\n const [showEncryptedReasoning, setShowEncryptedReasoning] = useState(false);\n\n const filters = useMemo(() => collectSessionFilters(allEvents), [allEvents]);\n const hasThinking = useMemo(\n () => allEvents.some((e) => e.kind === \"thinking\"),\n [allEvents],\n );\n const hasEncryptedReasoning = useMemo(\n () => allEvents.some(isEncryptedReasoning),\n [allEvents],\n );\n\n const visibility = {\n hiddenCategories,\n hiddenTools,\n hiddenSources,\n showThinking: effectiveShowThinking,\n };\n const items = displayItems.filter((item) => {\n const event = isSessionEventGroup(item) ? item.representative : item;\n return (showEncryptedReasoning || !isEncryptedReasoning(event)) && isEventVisible(event, visibility);\n });\n const firstUserEventId = allEvents.find((event) => event.kind === \"user\")?.id;\n\n // Reset the window when the underlying session changes, not on filter toggles —\n // so hiding a category doesn't yank the reader back to the bottom.\n const resetKey = scrollResetKey ?? allEvents[0]?.id ?? \"\";\n const { scrollRef, contentRef, startIndex, following, resumeFollowing } = useSessionScroll({\n total: items.length,\n enabled: scrollable,\n windowSize,\n batchSize,\n resetKey,\n });\n\n if (allEvents.length === 0) {\n return (\n <div\n className={cn(\n \"rounded-md border border-dashed border-border p-density-4 text-center text-sm text-muted-foreground\",\n className,\n )}\n >\n No session activity.\n </div>\n );\n }\n\n const summary = summarizeSession(allEvents);\n const effectiveDensity = densityOverride ?? pageDensity;\n const dataAttrs: Record<string, string> = {\n ...(densityOverride ? { \"data-density\": densityOverride } : {}),\n ...(themeOverride ? { \"data-theme\": themeOverride } : {}),\n };\n\n const menu = showMenu ? (\n <SessionViewerMenu\n menuHeader={menuHeader}\n density={densityOverride}\n onDensityChange={setDensityOverride}\n theme={themeOverride}\n onThemeChange={setThemeOverride}\n filters={filters}\n hiddenCategories={hiddenCategories}\n hiddenTools={hiddenTools}\n hiddenSources={hiddenSources}\n onToggleCategory={(category) =>\n setHiddenCategories((set) => toggleInSet(set, category))\n }\n onToggleTool={(tool) => setHiddenTools((set) => toggleInSet(set, tool))}\n onToggleSource={(source) =>\n setHiddenSources((set) => toggleInSet(set, source))\n }\n showThinking={effectiveShowThinking}\n onToggleThinking={() => setShowThinkingOverride(!effectiveShowThinking)}\n hasThinking={hasThinking}\n hasEncryptedReasoning={hasEncryptedReasoning}\n showEncryptedReasoning={showEncryptedReasoning}\n onToggleEncryptedReasoning={() => setShowEncryptedReasoning((shown) => !shown)}\n />\n ) : null;\n // When a host supplies `menuContainer`, the menu is portaled into it (e.g. the\n // host's own toolbar) and the inline header collapses to just its summary.\n const inlineMenu = menu && !menuContainer;\n\n const list =\n items.length === 0 ? (\n <div className=\"rounded-md border border-dashed border-border p-density-4 text-center text-sm text-muted-foreground\">\n All actions are hidden by the active filters.\n </div>\n ) : (\n // In scrollable mode only the newest `startIndex..` slice is mounted; `last`\n // is measured against the full length so the timeline connector stays right.\n <ol className=\"relative\">\n {items.slice(startIndex).map((item, index) => {\n const last = startIndex + index === items.length - 1;\n return isSessionEventGroup(item) ? (\n <WaitGroupRow\n key={item.id}\n group={item}\n last={last}\n defaultExpanded={defaultExpanded}\n showRowMetadata={showRowMetadata}\n showRaw={showRaw}\n renderMessageBadge={renderMessageBadge}\n onPendingToolDecision={onPendingToolDecision}\n />\n ) : (\n <SessionRow\n key={item.id}\n event={item}\n initialPrompt={item.id === firstUserEventId}\n last={last}\n defaultExpanded={defaultExpanded}\n showRowMetadata={showRowMetadata}\n showRaw={showRaw}\n renderMessageBadge={renderMessageBadge}\n onPendingToolDecision={onPendingToolDecision}\n />\n );\n })}\n </ol>\n );\n\n return (\n <div\n className={cn(\n \"@container/session-viewer min-w-0 bg-background text-sm text-foreground data-[theme=dark]:bg-[var(--fs-bg-subtle)] [[data-theme=dark]_&]:bg-[var(--fs-bg-subtle)]\",\n scrollable && \"flex h-full min-h-0 flex-col\",\n className,\n )}\n {...dataAttrs}\n >\n <DensityValueProvider density={effectiveDensity}>\n {menu && menuContainer && createPortal(menu, menuContainer)}\n {(showHeader || headerActions || inlineMenu) && (\n <div\n data-session-viewer-header\n className={cn(\n \"flex min-w-0 flex-wrap items-center justify-between gap-x-density-3 gap-y-density-2\",\n scrollable\n ? \"shrink-0 border-b border-border px-density-3 py-density-2 @min-[48rem]/session-viewer:px-density-4\"\n : \"mb-density-3\",\n )}\n >\n {showHeader && (\n <div className=\"flex min-w-0 flex-1 flex-wrap items-center gap-x-density-3 gap-y-1 text-xs text-muted-foreground\">\n {summary.model && (\n <span className=\"inline-flex items-center gap-1 font-medium text-foreground\">\n <Icon icon={UiRobotAi} className=\"size-3.5\" />\n {summary.model}\n </span>\n )}\n <span>{summary.toolCount} actions</span>\n <span>{summary.messageCount} messages</span>\n {metadata && (\n <SessionMetadataBadges\n metadata={metadata}\n showContextMeter={showContextMeter}\n />\n )}\n </div>\n )}\n {(headerActions || inlineMenu) && (\n <div\n role=\"group\"\n aria-label=\"Session viewer actions\"\n className=\"ml-auto flex min-w-0 shrink-0 items-center gap-density-2\"\n >\n {headerActions}\n {inlineMenu && menu}\n </div>\n )}\n </div>\n )}\n\n {scrollable ? (\n <div className=\"relative min-h-0 flex-1\">\n <div ref={scrollRef} className=\"h-full overflow-y-auto\">\n <div\n ref={contentRef}\n data-session-viewer-content\n className=\"p-density-3 @min-[48rem]/session-viewer:p-density-4\"\n >\n {list}\n </div>\n </div>\n {!following && (\n <Button\n type=\"button\"\n variant=\"secondary\"\n size=\"sm\"\n onClick={resumeFollowing}\n className=\"absolute bottom-density-3 left-1/2 -translate-x-1/2 shadow-md\"\n >\n <Icon icon={UiArrowDown} className=\"size-4\" />\n Scroll to bottom\n </Button>\n )}\n </div>\n ) : (\n list\n )}\n </DensityValueProvider>\n </div>\n );\n}\n\nfunction mergePendingTools(\n events: SessionEvent[],\n pendingTools: readonly SessionPendingTool[],\n): SessionEvent[] {\n const merged = [...events];\n for (const [index, pending] of pendingTools.entries()) {\n const matches = merged.filter(\n (event) =>\n event.kind === \"tool\" &&\n ((pending.toolCallId && event.toolCallId === pending.toolCallId) ||\n (pending.approvalId && event.approvalId === pending.approvalId) ||\n (pending.sessionId &&\n event.sessionId === pending.sessionId &&\n event.tool === pending.tool)),\n );\n const match = matches.length === 1 ? matches[0] : undefined;\n if (match) {\n Object.assign(match, {\n pending: true,\n toolInput: pending.input ?? match.toolInput,\n toolCallId: pending.toolCallId ?? match.toolCallId,\n approvalId: pending.approvalId ?? match.approvalId,\n sessionId: pending.sessionId ?? match.sessionId,\n ...approvalFields(pending),\n });\n } else {\n merged.push({\n id: `pending-${\n pending.approvalId ?? pending.toolCallId ?? `${pending.tool}-${index}`\n }`,\n kind: \"tool\",\n tool: pending.tool,\n ...(pending.input ? { toolInput: pending.input } : {}),\n ...(pending.toolCallId ? { toolCallId: pending.toolCallId } : {}),\n ...(pending.approvalId ? { approvalId: pending.approvalId } : {}),\n ...(pending.sessionId ? { sessionId: pending.sessionId } : {}),\n ...approvalFields(pending),\n pending: true,\n });\n }\n }\n return merged;\n}\n\nfunction approvalFields(\n pending: SessionPendingTool,\n): Pick<SessionEvent, \"approvalKind\" | \"approvalRequest\"> {\n const kind = pending.kind ?? pending.request?.kind;\n return {\n ...(kind ? { approvalKind: kind } : {}),\n ...(pending.request ? { approvalRequest: pending.request } : {}),\n };\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SessionViewer.js","sources":["../../../src/data/ai/SessionViewer.tsx"],"sourcesContent":["import { useMemo, useState, type ReactNode } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { cn } from \"../../lib/utils\";\nimport { Icon } from \"../Icon\";\nimport { Button } from \"../../components/button\";\nimport { useDensityValue, type Density } from \"../../hooks/use-density\";\nimport { DensityValueProvider } from \"../../hooks/density-provider\";\nimport { UiArrowDown, UiRobotAi } from \"../../icons\";\nimport {\n getSessionMetadata,\n normalizeSession,\n summarizeSession,\n type SessionEvent,\n type SessionInput,\n} from \"./SessionViewer.model\";\nimport {\n collapseWaitRuns,\n isSessionEventGroup,\n} from \"./SessionViewer.grouping\";\nimport { SessionRow, WaitGroupRow } from \"./SessionViewer.rows\";\nimport { SessionMetadataBadges } from \"./SessionViewer.header\";\nimport {\n collectSessionFilters,\n isEncryptedReasoning,\n isEventVisible,\n type SessionCategory,\n} from \"./session-categories\";\nimport {\n SessionViewerMenu,\n type SessionThemeOverride,\n} from \"./SessionViewerMenu\";\nimport { useSessionScroll } from \"./use-session-scroll\";\nimport type {\n ApprovalDecisionFields,\n ApprovalKind,\n ApprovalRequest,\n} from \"./approval-request\";\nimport type { SessionTokenSizer } from \"./session-token-sizing\";\nimport { SessionTokenContext, useSessionTokenSizing } from \"./use-session-token-sizing\";\nexport type { SessionTokenSizer, SessionTokenSize, SessionTokenSizingRequest, SessionTokenSizingResult } from \"./session-token-sizing\";\n\nexport type {\n SessionEntry,\n SessionEvent,\n SessionInput,\n SessionActionMeta,\n} from \"./SessionViewer.model\";\nexport type { SessionThemeOverride } from \"./SessionViewerMenu\";\n\nexport interface SessionPendingTool {\n tool: string;\n input?: Record<string, unknown>;\n toolCallId?: string;\n approvalId?: string;\n sessionId?: string;\n /** What kind of approval this is. Absent means an untyped tool approval, which\n * renders as Allow / Reject. */\n kind?: ApprovalKind;\n /** The typed approval request; drives the per-kind controls. */\n request?: ApprovalRequest;\n}\n\n/** A decision on one pending tool. `allow`/`message`/`answers` are the original\n * fields; `interrupt`, `scope`, `grants` and `content` are set only for a typed\n * request that offers them. */\nexport interface SessionToolDecision extends ApprovalDecisionFields {\n event: SessionEvent;\n allow: boolean;\n message?: string;\n}\n\nexport interface SessionViewerProps {\n\n /** Explicit menu actions only; never invoked automatically when a transcript loads. */\n sizeTokens?: SessionTokenSizer;\n /** A captain session: parsed `SessionEntry[]` or raw log text (JSON / JSONL). */\n session: SessionInput;\n className?: string;\n /** Expand each tool call's input/output by default. Defaults to false. */\n defaultExpanded?: boolean;\n /** Render assistant reasoning (\"thinking\") blocks. Defaults to true. */\n showThinking?: boolean;\n /** Show the summary header (model + action counts). Defaults to true. */\n showHeader?: boolean;\n /** Show context usage in the summary header. Defaults to true. */\n showContextMeter?: boolean;\n /** Show the 3-dot menu (density + category/tool/source filters). Defaults to true. */\n showMenu?: boolean;\n /** Controls rendered beside the 3-dot menu in the summary header. */\n headerActions?: ReactNode;\n /** Host controls rendered at the top of the 3-dot menu. */\n menuHeader?: ReactNode;\n /** Portal the 3-dot menu into this element instead of rendering it inline in\n * the summary header — lets a host place the menu in its own toolbar while the\n * filter/density state stays owned by the viewer. Ignored when `showMenu` is\n * false; falls back to inline rendering when null/undefined. */\n menuContainer?: Element | null;\n /** Initial density override; undefined inherits the page/document density. */\n defaultDensity?: Density;\n /** Initial theme override; undefined inherits the page/document `data-theme`. */\n defaultTheme?: SessionThemeOverride;\n /** Own an internal scroll container that fills its parent's height: render only\n * the newest screenful, stay pinned to the bottom (most recent activity), and\n * backfill older rows as the reader scrolls up. Off by default, so inline\n * consumers keep rendering the whole log in normal page flow. Requires a\n * height-bounded parent. */\n scrollable?: boolean;\n /** Rows rendered on first paint in `scrollable` mode. Defaults to 60. */\n windowSize?: number;\n /** Rows added each time older content loads in `scrollable` mode. Defaults to 40. */\n batchSize?: number;\n /** Stable identity used to reset the transcript window when switching sessions. */\n scrollResetKey?: string;\n /** Show per-row timestamp/source/model/turn/agent metadata. Defaults to false. */\n showRowMetadata?: boolean;\n /** Show a per-row raw JSON payload expander when available. Defaults to false. */\n showRaw?: boolean;\n /** Render content before each assistant message body. */\n renderMessageBadge?: (event: SessionEvent) => ReactNode;\n pendingTools?: readonly SessionPendingTool[];\n onPendingToolDecision?:\n | ((decision: SessionToolDecision) => Promise<void> | void)\n | undefined;\n}\n\nfunction toggleInSet<T>(set: ReadonlySet<T>, value: T): Set<T> {\n const next = new Set(set);\n if (next.has(value)) next.delete(value);\n else next.add(value);\n return next;\n}\n\n/**\n * SessionViewer renders a recorded AI coding-agent session (the captain\n * `pkg/ai/history` JSON schema — Claude Code / Codex transcripts) as a vertical\n * action log. Each entry sits on a tone-colored icon disc from the Flanksource\n * \"Agent Action Icons\" set; user prompts/selections are right-aligned like a\n * chat. Shell commands render inline as bash blocks and file ops as their\n * cwd-relative path — the icon carries the verb. Tool responses expand behind\n * a chevron, rendered bare (no panel chrome). The \"3-dot\" menu mirrors\n * `captain history` filtering — toggle density and hide categories, tools or\n * sources.\n */\nexport function SessionViewer({\n session,\n className,\n defaultExpanded = false,\n showThinking = true,\n showHeader = true,\n showContextMeter = true,\n showMenu = true,\n headerActions,\n menuHeader,\n menuContainer,\n defaultDensity,\n defaultTheme,\n scrollable = false,\n windowSize = 60,\n batchSize = 40,\n scrollResetKey,\n showRowMetadata = false,\n showRaw = false,\n renderMessageBadge,\n pendingTools = [],\n onPendingToolDecision,\n sizeTokens,\n}: SessionViewerProps) {\n const allEvents = useMemo(\n () => mergePendingTools(normalizeSession(session), pendingTools),\n [session, pendingTools],\n );\n const displayItems = useMemo(() => collapseWaitRuns(allEvents), [allEvents]);\n const metadata = useMemo(() => getSessionMetadata(session), [session]);\n const tokenSizing = useSessionTokenSizing(session, allEvents, sizeTokens);\n\n const pageDensity = useDensityValue();\n const [densityOverride, setDensityOverride] = useState<Density | undefined>(\n defaultDensity,\n );\n const [themeOverride, setThemeOverride] = useState<\n SessionThemeOverride | undefined\n >(defaultTheme);\n const [hiddenCategories, setHiddenCategories] = useState<\n ReadonlySet<SessionCategory>\n >(() => new Set());\n const [hiddenTools, setHiddenTools] = useState<ReadonlySet<string>>(\n () => new Set(),\n );\n const [hiddenSources, setHiddenSources] = useState<ReadonlySet<string>>(\n () => new Set(),\n );\n // Undefined = follow the `showThinking` prop; the menu toggle sets an override.\n const [showThinkingOverride, setShowThinkingOverride] = useState<\n boolean | undefined\n >(undefined);\n const effectiveShowThinking = showThinkingOverride ?? showThinking;\n const [showEncryptedReasoning, setShowEncryptedReasoning] = useState(false);\n const [showEstimatedToolCost, setShowEstimatedToolCost] = useState(false);\n\n const filters = useMemo(() => collectSessionFilters(allEvents), [allEvents]);\n const hasThinking = useMemo(\n () => allEvents.some((e) => e.kind === \"thinking\"),\n [allEvents],\n );\n const hasEncryptedReasoning = useMemo(\n () => allEvents.some(isEncryptedReasoning),\n [allEvents],\n );\n\n const visibility = {\n hiddenCategories,\n hiddenTools,\n hiddenSources,\n showThinking: effectiveShowThinking,\n };\n const items = displayItems.filter((item) => {\n const event = isSessionEventGroup(item) ? item.representative : item;\n return (showEncryptedReasoning || !isEncryptedReasoning(event)) && isEventVisible(event, visibility);\n });\n const firstUserEventId = allEvents.find((event) => event.kind === \"user\")?.id;\n\n // Reset the window when the underlying session changes, not on filter toggles —\n // so hiding a category doesn't yank the reader back to the bottom.\n const resetKey = scrollResetKey ?? allEvents[0]?.id ?? \"\";\n const { scrollRef, contentRef, startIndex, following, resumeFollowing } = useSessionScroll({\n total: items.length,\n enabled: scrollable,\n windowSize,\n batchSize,\n resetKey,\n });\n\n if (allEvents.length === 0) {\n return (\n <div\n className={cn(\n \"rounded-md border border-dashed border-border p-density-4 text-center text-sm text-muted-foreground\",\n className,\n )}\n >\n No session activity.\n </div>\n );\n }\n\n const summary = summarizeSession(allEvents);\n const effectiveDensity = densityOverride ?? pageDensity;\n const dataAttrs: Record<string, string> = {\n ...(densityOverride ? { \"data-density\": densityOverride } : {}),\n ...(themeOverride ? { \"data-theme\": themeOverride } : {}),\n };\n\n const menu = showMenu ? (\n <SessionViewerMenu\n menuHeader={menuHeader}\n density={densityOverride}\n onDensityChange={setDensityOverride}\n theme={themeOverride}\n onThemeChange={setThemeOverride}\n filters={filters}\n hiddenCategories={hiddenCategories}\n hiddenTools={hiddenTools}\n hiddenSources={hiddenSources}\n onToggleCategory={(category) =>\n setHiddenCategories((set) => toggleInSet(set, category))\n }\n onToggleTool={(tool) => setHiddenTools((set) => toggleInSet(set, tool))}\n onToggleSource={(source) =>\n setHiddenSources((set) => toggleInSet(set, source))\n }\n showThinking={effectiveShowThinking}\n onToggleThinking={() => setShowThinkingOverride(!effectiveShowThinking)}\n hasThinking={hasThinking}\n hasEncryptedReasoning={hasEncryptedReasoning}\n showEncryptedReasoning={showEncryptedReasoning}\n onToggleEncryptedReasoning={() => setShowEncryptedReasoning((shown) => !shown)}\n showEstimatedToolCost={showEstimatedToolCost}\n onToggleEstimatedToolCost={() => setShowEstimatedToolCost((shown) => !shown)}\n {...(tokenSizing.estimateAll ? { onEstimateTokens: tokenSizing.estimateAll, onCalculateMissingTokens: tokenSizing.calculateMissing, estimatingTokens: tokenSizing.pending } : {})}\n />\n ) : null;\n // When a host supplies `menuContainer`, the menu is portaled into it (e.g. the\n // host's own toolbar) and the inline header collapses to just its summary.\n const inlineMenu = menu && !menuContainer;\n\n const list =\n items.length === 0 ? (\n <div className=\"rounded-md border border-dashed border-border p-density-4 text-center text-sm text-muted-foreground\">\n All actions are hidden by the active filters.\n </div>\n ) : (\n // In scrollable mode only the newest `startIndex..` slice is mounted; `last`\n // is measured against the full length so the timeline connector stays right.\n <ol className=\"relative\">\n {items.slice(startIndex).map((item, index) => {\n const last = startIndex + index === items.length - 1;\n return isSessionEventGroup(item) ? (\n <WaitGroupRow\n key={item.id}\n group={item}\n last={last}\n showEstimatedToolCost={showEstimatedToolCost}\n defaultExpanded={defaultExpanded}\n showRowMetadata={showRowMetadata}\n showRaw={showRaw}\n renderMessageBadge={renderMessageBadge}\n onPendingToolDecision={onPendingToolDecision}\n />\n ) : (\n <SessionRow\n key={item.id}\n event={item}\n initialPrompt={item.id === firstUserEventId}\n showEstimatedToolCost={showEstimatedToolCost}\n last={last}\n defaultExpanded={defaultExpanded}\n showRowMetadata={showRowMetadata}\n showRaw={showRaw}\n renderMessageBadge={renderMessageBadge}\n onPendingToolDecision={onPendingToolDecision}\n />\n );\n })}\n </ol>\n );\n\n return (\n <div\n className={cn(\n \"@container/session-viewer min-w-0 bg-background text-sm text-foreground data-[theme=dark]:bg-[var(--fs-bg-subtle)] [[data-theme=dark]_&]:bg-[var(--fs-bg-subtle)]\",\n scrollable && \"flex h-full min-h-0 flex-col\",\n className,\n )}\n {...dataAttrs}\n >\n <SessionTokenContext.Provider value={tokenSizing.context}>\n <DensityValueProvider density={effectiveDensity}>\n {menu && menuContainer && createPortal(menu, menuContainer)}\n {(showHeader || headerActions || inlineMenu) && (\n <div\n data-session-viewer-header\n className={cn(\n \"flex min-w-0 flex-wrap items-center justify-between gap-x-density-3 gap-y-density-2\",\n scrollable\n ? \"shrink-0 border-b border-border px-density-3 py-density-2 @min-[48rem]/session-viewer:px-density-4\"\n : \"mb-density-3\",\n )}\n >\n {showHeader && (\n <div className=\"flex min-w-0 flex-1 flex-wrap items-center gap-x-density-3 gap-y-1 text-xs text-muted-foreground\">\n {summary.model && (\n <span className=\"inline-flex items-center gap-1 font-medium text-foreground\">\n <Icon icon={UiRobotAi} className=\"size-3.5\" />\n {summary.model}\n </span>\n )}\n <span>{summary.toolCount} actions</span>\n <span>{summary.messageCount} messages</span>\n {metadata && (\n <SessionMetadataBadges\n metadata={metadata}\n showContextMeter={showContextMeter}\n />\n )}\n </div>\n )}\n {(headerActions || inlineMenu) && (\n <div\n role=\"group\"\n aria-label=\"Session viewer actions\"\n className=\"ml-auto flex min-w-0 shrink-0 items-center gap-density-2\"\n >\n {headerActions}\n {inlineMenu && menu}\n </div>\n )}\n </div>\n )}\n\n {scrollable ? (\n <div className=\"relative min-h-0 flex-1\">\n <div ref={scrollRef} className=\"h-full overflow-y-auto\">\n <div\n ref={contentRef}\n data-session-viewer-content\n className=\"p-density-3 @min-[48rem]/session-viewer:p-density-4\"\n >\n {list}\n </div>\n </div>\n {!following && (\n <Button\n type=\"button\"\n variant=\"secondary\"\n size=\"sm\"\n onClick={resumeFollowing}\n className=\"absolute bottom-density-3 left-1/2 -translate-x-1/2 shadow-md\"\n >\n <Icon icon={UiArrowDown} className=\"size-4\" />\n Scroll to bottom\n </Button>\n )}\n </div>\n ) : (\n list\n )}\n </DensityValueProvider>\n </SessionTokenContext.Provider>\n </div>\n );\n}\n\nfunction mergePendingTools(\n events: SessionEvent[],\n pendingTools: readonly SessionPendingTool[],\n): SessionEvent[] {\n const merged = [...events];\n for (const [index, pending] of pendingTools.entries()) {\n const matches = merged.filter(\n (event) =>\n event.kind === \"tool\" &&\n ((pending.toolCallId && event.toolCallId === pending.toolCallId) ||\n (pending.approvalId && event.approvalId === pending.approvalId) ||\n (pending.sessionId &&\n event.sessionId === pending.sessionId &&\n event.tool === pending.tool)),\n );\n const match = matches.length === 1 ? matches[0] : undefined;\n if (match) {\n Object.assign(match, {\n pending: true,\n toolInput: pending.input ?? match.toolInput,\n toolCallId: pending.toolCallId ?? match.toolCallId,\n approvalId: pending.approvalId ?? match.approvalId,\n sessionId: pending.sessionId ?? match.sessionId,\n ...approvalFields(pending),\n });\n } else {\n merged.push({\n id: `pending-${\n pending.approvalId ?? pending.toolCallId ?? `${pending.tool}-${index}`\n }`,\n kind: \"tool\",\n tool: pending.tool,\n ...(pending.input ? { toolInput: pending.input } : {}),\n ...(pending.toolCallId ? { toolCallId: pending.toolCallId } : {}),\n ...(pending.approvalId ? { approvalId: pending.approvalId } : {}),\n ...(pending.sessionId ? { sessionId: pending.sessionId } : {}),\n ...approvalFields(pending),\n pending: true,\n });\n }\n }\n return merged;\n}\n\nfunction approvalFields(\n pending: SessionPendingTool,\n): Pick<SessionEvent, \"approvalKind\" | \"approvalRequest\"> {\n const kind = pending.kind ?? pending.request?.kind;\n return {\n ...(kind ? { approvalKind: kind } : {}),\n ...(pending.request ? { approvalRequest: pending.request } : {}),\n };\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -73,6 +73,7 @@ function toolEvent(id, tool, input, response, timestamp, meta = {}) {
|
|
|
73
73
|
...meta.turnId ? { turnId: meta.turnId } : {},
|
|
74
74
|
...meta.agentId ? { agentId: meta.agentId } : {},
|
|
75
75
|
...meta.toolState ? { toolState: meta.toolState } : {},
|
|
76
|
+
...meta.estimatedCost ? { estimatedCost: meta.estimatedCost } : {},
|
|
76
77
|
...meta.approval ? { approval: meta.approval } : {},
|
|
77
78
|
pending: meta.pending ?? false,
|
|
78
79
|
...meta.toolCallId ? { toolCallId: meta.toolCallId } : {},
|
|
@@ -233,6 +234,7 @@ function partEvent(part, role, id, meta) {
|
|
|
233
234
|
...part.approval ? { approval: part.approval } : {},
|
|
234
235
|
pending,
|
|
235
236
|
...part.toolCallId ? { toolCallId: part.toolCallId } : {},
|
|
237
|
+
...part.estimatedCost ? { estimatedCost: part.estimatedCost } : {},
|
|
236
238
|
...((_a = part.approval) == null ? void 0 : _a.id) ? { approvalId: part.approval.id } : {},
|
|
237
239
|
...meta.raw !== void 0 ? { raw: meta.raw } : {}
|
|
238
240
|
}
|