@flanksource/clicky-ui 0.3.41 → 0.3.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai.cjs +4 -0
- package/dist/ai.cjs.map +1 -1
- package/dist/ai.js +4 -0
- package/dist/ai.js.map +1 -1
- package/dist/comments/CommentCard.cjs +3 -1
- package/dist/comments/CommentCard.cjs.map +1 -1
- package/dist/comments/CommentCard.d.ts.map +1 -1
- package/dist/comments/CommentCard.js +4 -2
- package/dist/comments/CommentCard.js.map +1 -1
- package/dist/comments/CommentCardParts.cjs +16 -0
- package/dist/comments/CommentCardParts.cjs.map +1 -1
- package/dist/comments/CommentCardParts.d.ts +4 -1
- package/dist/comments/CommentCardParts.d.ts.map +1 -1
- package/dist/comments/CommentCardParts.js +16 -0
- package/dist/comments/CommentCardParts.js.map +1 -1
- package/dist/comments/comment-types.cjs.map +1 -1
- package/dist/comments/comment-types.d.ts +4 -0
- package/dist/comments/comment-types.d.ts.map +1 -1
- package/dist/comments/comment-types.js.map +1 -1
- package/dist/components/Combobox.cjs +54 -8
- package/dist/components/Combobox.cjs.map +1 -1
- package/dist/components/Combobox.d.ts.map +1 -1
- package/dist/components/Combobox.js +56 -10
- package/dist/components/Combobox.js.map +1 -1
- package/dist/components/ComboboxMenu.cjs +139 -113
- package/dist/components/ComboboxMenu.cjs.map +1 -1
- package/dist/components/ComboboxMenu.d.ts +3 -1
- package/dist/components/ComboboxMenu.d.ts.map +1 -1
- package/dist/components/ComboboxMenu.js +139 -113
- package/dist/components/ComboboxMenu.js.map +1 -1
- package/dist/components/ComboboxMenuTrigger.cjs +87 -0
- package/dist/components/ComboboxMenuTrigger.cjs.map +1 -0
- package/dist/components/ComboboxMenuTrigger.d.ts +23 -0
- package/dist/components/ComboboxMenuTrigger.d.ts.map +1 -0
- package/dist/components/ComboboxMenuTrigger.js +87 -0
- package/dist/components/ComboboxMenuTrigger.js.map +1 -0
- package/dist/components/JsonSchemaForm.cjs +30 -7
- package/dist/components/JsonSchemaForm.cjs.map +1 -1
- package/dist/components/JsonSchemaForm.d.ts.map +1 -1
- package/dist/components/JsonSchemaForm.js +30 -7
- package/dist/components/JsonSchemaForm.js.map +1 -1
- package/dist/components/SegmentedControl.cjs +20 -3
- package/dist/components/SegmentedControl.cjs.map +1 -1
- package/dist/components/SegmentedControl.d.ts +11 -0
- package/dist/components/SegmentedControl.d.ts.map +1 -1
- package/dist/components/SegmentedControl.js +21 -4
- package/dist/components/SegmentedControl.js.map +1 -1
- package/dist/components/combobox-types.d.ts +8 -0
- package/dist/components/combobox-types.d.ts.map +1 -1
- package/dist/components/json-schema-form-debug-badge.cjs +108 -0
- package/dist/components/json-schema-form-debug-badge.cjs.map +1 -0
- package/dist/components/json-schema-form-debug-badge.d.ts +10 -0
- package/dist/components/json-schema-form-debug-badge.d.ts.map +1 -0
- package/dist/components/json-schema-form-debug-badge.js +108 -0
- package/dist/components/json-schema-form-debug-badge.js.map +1 -0
- package/dist/components/json-schema-form-debug-glyph-map.cjs +129 -0
- package/dist/components/json-schema-form-debug-glyph-map.cjs.map +1 -0
- package/dist/components/json-schema-form-debug-glyph-map.d.ts +20 -0
- package/dist/components/json-schema-form-debug-glyph-map.d.ts.map +1 -0
- package/dist/components/json-schema-form-debug-glyph-map.js +129 -0
- package/dist/components/json-schema-form-debug-glyph-map.js.map +1 -0
- package/dist/components/json-schema-form-debug-glyph.cjs +13 -0
- package/dist/components/json-schema-form-debug-glyph.cjs.map +1 -0
- package/dist/components/json-schema-form-debug-glyph.d.ts +6 -0
- package/dist/components/json-schema-form-debug-glyph.d.ts.map +1 -0
- package/dist/components/json-schema-form-debug-glyph.js +13 -0
- package/dist/components/json-schema-form-debug-glyph.js.map +1 -0
- package/dist/components/json-schema-form-debug-groups.cjs +56 -0
- package/dist/components/json-schema-form-debug-groups.cjs.map +1 -0
- package/dist/components/json-schema-form-debug-groups.d.ts +8 -0
- package/dist/components/json-schema-form-debug-groups.d.ts.map +1 -0
- package/dist/components/json-schema-form-debug-groups.js +56 -0
- package/dist/components/json-schema-form-debug-groups.js.map +1 -0
- package/dist/components/json-schema-form-debug-keywords.cjs +159 -0
- package/dist/components/json-schema-form-debug-keywords.cjs.map +1 -0
- package/dist/components/json-schema-form-debug-keywords.d.ts +6 -0
- package/dist/components/json-schema-form-debug-keywords.d.ts.map +1 -0
- package/dist/components/json-schema-form-debug-keywords.js +159 -0
- package/dist/components/json-schema-form-debug-keywords.js.map +1 -0
- package/dist/components/json-schema-form-debug-listeners.cjs +102 -0
- package/dist/components/json-schema-form-debug-listeners.cjs.map +1 -0
- package/dist/components/json-schema-form-debug-listeners.d.ts +6 -0
- package/dist/components/json-schema-form-debug-listeners.d.ts.map +1 -0
- package/dist/components/json-schema-form-debug-listeners.js +102 -0
- package/dist/components/json-schema-form-debug-listeners.js.map +1 -0
- package/dist/components/json-schema-form-debug.cjs +31 -0
- package/dist/components/json-schema-form-debug.cjs.map +1 -0
- package/dist/components/json-schema-form-debug.d.ts +11 -0
- package/dist/components/json-schema-form-debug.d.ts.map +1 -0
- package/dist/components/json-schema-form-debug.js +31 -0
- package/dist/components/json-schema-form-debug.js.map +1 -0
- package/dist/components/json-schema-form-enum-choice.cjs +114 -0
- package/dist/components/json-schema-form-enum-choice.cjs.map +1 -0
- package/dist/components/json-schema-form-enum-choice.d.ts +14 -0
- package/dist/components/json-schema-form-enum-choice.d.ts.map +1 -0
- package/dist/components/json-schema-form-enum-choice.js +114 -0
- package/dist/components/json-schema-form-enum-choice.js.map +1 -0
- package/dist/components/json-schema-form-fields.cjs +3 -93
- package/dist/components/json-schema-form-fields.cjs.map +1 -1
- package/dist/components/json-schema-form-fields.d.ts.map +1 -1
- package/dist/components/json-schema-form-fields.js +1 -91
- package/dist/components/json-schema-form-fields.js.map +1 -1
- package/dist/components/json-schema-form-listeners.cjs +7 -1
- package/dist/components/json-schema-form-listeners.cjs.map +1 -1
- package/dist/components/json-schema-form-listeners.d.ts.map +1 -1
- package/dist/components/json-schema-form-listeners.js +7 -1
- package/dist/components/json-schema-form-listeners.js.map +1 -1
- package/dist/components/json-schema-form-preferences.cjs +1 -0
- package/dist/components/json-schema-form-preferences.cjs.map +1 -1
- package/dist/components/json-schema-form-preferences.d.ts +1 -0
- package/dist/components/json-schema-form-preferences.d.ts.map +1 -1
- package/dist/components/json-schema-form-preferences.js +1 -0
- package/dist/components/json-schema-form-preferences.js.map +1 -1
- package/dist/components/json-schema-form-render.cjs +21 -5
- package/dist/components/json-schema-form-render.cjs.map +1 -1
- package/dist/components/json-schema-form-render.d.ts.map +1 -1
- package/dist/components/json-schema-form-render.js +21 -5
- package/dist/components/json-schema-form-render.js.map +1 -1
- package/dist/components/json-schema-form-runtime-types.d.ts +1 -0
- package/dist/components/json-schema-form-runtime-types.d.ts.map +1 -1
- package/dist/components/json-schema-form-tone.cjs +12 -0
- package/dist/components/json-schema-form-tone.cjs.map +1 -1
- package/dist/components/json-schema-form-tone.js +12 -0
- package/dist/components/json-schema-form-tone.js.map +1 -1
- package/dist/components/json-schema-form-types.d.ts +1 -0
- package/dist/components/json-schema-form-types.d.ts.map +1 -1
- package/dist/data/GraphDiagram.cjs +125 -138
- package/dist/data/GraphDiagram.cjs.map +1 -1
- package/dist/data/GraphDiagram.d.ts +30 -23
- package/dist/data/GraphDiagram.d.ts.map +1 -1
- package/dist/data/GraphDiagram.js +128 -141
- package/dist/data/GraphDiagram.js.map +1 -1
- package/dist/data/GraphDiagramEdges.cjs +208 -0
- package/dist/data/GraphDiagramEdges.cjs.map +1 -0
- package/dist/data/GraphDiagramEdges.d.ts +40 -0
- package/dist/data/GraphDiagramEdges.d.ts.map +1 -0
- package/dist/data/GraphDiagramEdges.js +208 -0
- package/dist/data/GraphDiagramEdges.js.map +1 -0
- package/dist/data/GraphDiagramNodes.cjs +142 -0
- package/dist/data/GraphDiagramNodes.cjs.map +1 -0
- package/dist/data/GraphDiagramNodes.d.ts +22 -0
- package/dist/data/GraphDiagramNodes.d.ts.map +1 -0
- package/dist/data/GraphDiagramNodes.js +142 -0
- package/dist/data/GraphDiagramNodes.js.map +1 -0
- package/dist/data/ai/PromptRunEditor/RuntimeRows.cjs +8 -3
- package/dist/data/ai/PromptRunEditor/RuntimeRows.cjs.map +1 -1
- package/dist/data/ai/PromptRunEditor/RuntimeRows.d.ts.map +1 -1
- package/dist/data/ai/PromptRunEditor/RuntimeRows.js +8 -3
- package/dist/data/ai/PromptRunEditor/RuntimeRows.js.map +1 -1
- package/dist/data/ai/PromptRunEditor/index.cjs +37 -43
- package/dist/data/ai/PromptRunEditor/index.cjs.map +1 -1
- package/dist/data/ai/PromptRunEditor/index.d.ts +3 -1
- package/dist/data/ai/PromptRunEditor/index.d.ts.map +1 -1
- package/dist/data/ai/PromptRunEditor/index.js +38 -44
- package/dist/data/ai/PromptRunEditor/index.js.map +1 -1
- package/dist/data/ai/PromptRunEditor/runtimeActions.cjs +16 -5
- package/dist/data/ai/PromptRunEditor/runtimeActions.cjs.map +1 -1
- package/dist/data/ai/PromptRunEditor/runtimeActions.d.ts +4 -1
- package/dist/data/ai/PromptRunEditor/runtimeActions.d.ts.map +1 -1
- package/dist/data/ai/PromptRunEditor/runtimeActions.js +17 -6
- package/dist/data/ai/PromptRunEditor/runtimeActions.js.map +1 -1
- package/dist/data/ai/SessionInspector.approvals-model.cjs +12 -0
- package/dist/data/ai/SessionInspector.approvals-model.cjs.map +1 -1
- package/dist/data/ai/SessionInspector.approvals-model.d.ts +11 -2
- package/dist/data/ai/SessionInspector.approvals-model.d.ts.map +1 -1
- package/dist/data/ai/SessionInspector.approvals-model.js +12 -0
- package/dist/data/ai/SessionInspector.approvals-model.js.map +1 -1
- package/dist/data/ai/SessionInspector.approvals.cjs +25 -1
- package/dist/data/ai/SessionInspector.approvals.cjs.map +1 -1
- package/dist/data/ai/SessionInspector.approvals.d.ts.map +1 -1
- package/dist/data/ai/SessionInspector.approvals.js +26 -2
- package/dist/data/ai/SessionInspector.approvals.js.map +1 -1
- package/dist/data/ai/SessionInspector.summary.cjs +9 -3
- package/dist/data/ai/SessionInspector.summary.cjs.map +1 -1
- package/dist/data/ai/SessionInspector.summary.d.ts.map +1 -1
- package/dist/data/ai/SessionInspector.summary.js +9 -3
- package/dist/data/ai/SessionInspector.summary.js.map +1 -1
- package/dist/data/ai/SessionInspector.transcript.cjs +4 -0
- package/dist/data/ai/SessionInspector.transcript.cjs.map +1 -1
- package/dist/data/ai/SessionInspector.transcript.d.ts.map +1 -1
- package/dist/data/ai/SessionInspector.transcript.js +4 -0
- package/dist/data/ai/SessionInspector.transcript.js.map +1 -1
- package/dist/data/ai/SessionViewer.approval-body.cjs +146 -0
- package/dist/data/ai/SessionViewer.approval-body.cjs.map +1 -0
- package/dist/data/ai/SessionViewer.approval-body.d.ts +11 -0
- package/dist/data/ai/SessionViewer.approval-body.d.ts.map +1 -0
- package/dist/data/ai/SessionViewer.approval-body.js +146 -0
- package/dist/data/ai/SessionViewer.approval-body.js.map +1 -0
- package/dist/data/ai/SessionViewer.approval-forms.cjs +150 -0
- package/dist/data/ai/SessionViewer.approval-forms.cjs.map +1 -0
- package/dist/data/ai/SessionViewer.approval-forms.d.ts +23 -0
- package/dist/data/ai/SessionViewer.approval-forms.d.ts.map +1 -0
- package/dist/data/ai/SessionViewer.approval-forms.js +150 -0
- package/dist/data/ai/SessionViewer.approval-forms.js.map +1 -0
- package/dist/data/ai/SessionViewer.cjs +57 -20
- package/dist/data/ai/SessionViewer.cjs.map +1 -1
- package/dist/data/ai/SessionViewer.d.ts +13 -3
- package/dist/data/ai/SessionViewer.d.ts.map +1 -1
- package/dist/data/ai/SessionViewer.decision-controls.cjs +313 -0
- package/dist/data/ai/SessionViewer.decision-controls.cjs.map +1 -0
- package/dist/data/ai/SessionViewer.decision-controls.d.ts +43 -0
- package/dist/data/ai/SessionViewer.decision-controls.d.ts.map +1 -0
- package/dist/data/ai/SessionViewer.decision-controls.js +313 -0
- package/dist/data/ai/SessionViewer.decision-controls.js.map +1 -0
- package/dist/data/ai/SessionViewer.decision.cjs +21 -0
- package/dist/data/ai/SessionViewer.decision.cjs.map +1 -0
- package/dist/data/ai/SessionViewer.decision.d.ts +12 -0
- package/dist/data/ai/SessionViewer.decision.d.ts.map +1 -0
- package/dist/data/ai/SessionViewer.decision.js +21 -0
- package/dist/data/ai/SessionViewer.decision.js.map +1 -0
- package/dist/data/ai/SessionViewer.input.cjs +14 -0
- package/dist/data/ai/SessionViewer.input.cjs.map +1 -1
- package/dist/data/ai/SessionViewer.input.d.ts +5 -0
- package/dist/data/ai/SessionViewer.input.d.ts.map +1 -1
- package/dist/data/ai/SessionViewer.input.js +14 -0
- package/dist/data/ai/SessionViewer.input.js.map +1 -1
- package/dist/data/ai/SessionViewer.js +58 -21
- package/dist/data/ai/SessionViewer.js.map +1 -1
- package/dist/data/ai/SessionViewer.model.cjs.map +1 -1
- package/dist/data/ai/SessionViewer.model.d.ts +4 -0
- package/dist/data/ai/SessionViewer.model.d.ts.map +1 -1
- package/dist/data/ai/SessionViewer.model.js.map +1 -1
- package/dist/data/ai/SessionViewer.rows.cjs +6 -3
- package/dist/data/ai/SessionViewer.rows.cjs.map +1 -1
- package/dist/data/ai/SessionViewer.rows.d.ts +2 -1
- package/dist/data/ai/SessionViewer.rows.d.ts.map +1 -1
- package/dist/data/ai/SessionViewer.rows.js +6 -3
- package/dist/data/ai/SessionViewer.rows.js.map +1 -1
- package/dist/data/ai/SessionViewer.tool-row.cjs +29 -237
- package/dist/data/ai/SessionViewer.tool-row.cjs.map +1 -1
- package/dist/data/ai/SessionViewer.tool-row.d.ts.map +1 -1
- package/dist/data/ai/SessionViewer.tool-row.js +27 -235
- 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 +8 -2
- package/dist/data/ai/SessionViewerMenu.cjs.map +1 -1
- package/dist/data/ai/SessionViewerMenu.d.ts +4 -1
- package/dist/data/ai/SessionViewerMenu.d.ts.map +1 -1
- package/dist/data/ai/SessionViewerMenu.js +8 -2
- package/dist/data/ai/SessionViewerMenu.js.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/CommitSection.cjs +28 -17
- package/dist/data/ai/SpecRuntimeEditor/CommitSection.cjs.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/CommitSection.d.ts +10 -2
- package/dist/data/ai/SpecRuntimeEditor/CommitSection.d.ts.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/CommitSection.js +29 -18
- package/dist/data/ai/SpecRuntimeEditor/CommitSection.js.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/index.cjs +9 -1
- package/dist/data/ai/SpecRuntimeEditor/index.cjs.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/index.d.ts +9 -2
- package/dist/data/ai/SpecRuntimeEditor/index.d.ts.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/index.js +9 -1
- package/dist/data/ai/SpecRuntimeEditor/index.js.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/permission-mode-visuals.cjs +1 -1
- package/dist/data/ai/SpecRuntimeEditor/permission-mode-visuals.js +1 -1
- package/dist/data/ai/SpecRuntimeEditor/summaries.cjs.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/summaries.d.ts +8 -2
- package/dist/data/ai/SpecRuntimeEditor/summaries.d.ts.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/summaries.js.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/update.cjs +14 -6
- package/dist/data/ai/SpecRuntimeEditor/update.cjs.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/update.d.ts +1 -0
- package/dist/data/ai/SpecRuntimeEditor/update.d.ts.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/update.js +14 -6
- package/dist/data/ai/SpecRuntimeEditor/update.js.map +1 -1
- package/dist/data/ai/approval-request.cjs +75 -0
- package/dist/data/ai/approval-request.cjs.map +1 -0
- package/dist/data/ai/approval-request.d.ts +155 -0
- package/dist/data/ai/approval-request.d.ts.map +1 -0
- package/dist/data/ai/approval-request.js +75 -0
- package/dist/data/ai/approval-request.js.map +1 -0
- package/dist/data/ai/index.d.ts +3 -0
- package/dist/data/ai/index.d.ts.map +1 -1
- package/dist/data/ai/runtime-preset-menu/SavePresetDialog.cjs +125 -0
- package/dist/data/ai/runtime-preset-menu/SavePresetDialog.cjs.map +1 -0
- package/dist/data/ai/runtime-preset-menu/SavePresetDialog.d.ts +11 -0
- package/dist/data/ai/runtime-preset-menu/SavePresetDialog.d.ts.map +1 -0
- package/dist/data/ai/runtime-preset-menu/SavePresetDialog.js +125 -0
- package/dist/data/ai/runtime-preset-menu/SavePresetDialog.js.map +1 -0
- package/dist/data/ai/runtime-preset-menu/index.d.ts +3 -0
- package/dist/data/ai/runtime-preset-menu/index.d.ts.map +1 -0
- package/dist/data/ai/runtime-preset-menu/model.cjs +73 -0
- package/dist/data/ai/runtime-preset-menu/model.cjs.map +1 -0
- package/dist/data/ai/runtime-preset-menu/model.d.ts +13 -0
- package/dist/data/ai/runtime-preset-menu/model.d.ts.map +1 -0
- package/dist/data/ai/runtime-preset-menu/model.js +73 -0
- package/dist/data/ai/runtime-preset-menu/model.js.map +1 -0
- package/dist/data/ai/runtime-preset-menu/use-runtime-preset-menu.cjs +149 -0
- package/dist/data/ai/runtime-preset-menu/use-runtime-preset-menu.cjs.map +1 -0
- package/dist/data/ai/runtime-preset-menu/use-runtime-preset-menu.d.ts +15 -0
- package/dist/data/ai/runtime-preset-menu/use-runtime-preset-menu.d.ts.map +1 -0
- package/dist/data/ai/runtime-preset-menu/use-runtime-preset-menu.js +149 -0
- package/dist/data/ai/runtime-preset-menu/use-runtime-preset-menu.js.map +1 -0
- package/dist/data/ai/runtime-spec-fields.cjs +166 -0
- package/dist/data/ai/runtime-spec-fields.cjs.map +1 -0
- package/dist/data/ai/runtime-spec-fields.d.ts +13 -0
- package/dist/data/ai/runtime-spec-fields.d.ts.map +1 -0
- package/dist/data/ai/runtime-spec-fields.js +166 -0
- package/dist/data/ai/runtime-spec-fields.js.map +1 -0
- package/dist/data/ai/session-categories.cjs +4 -0
- package/dist/data/ai/session-categories.cjs.map +1 -1
- package/dist/data/ai/session-categories.d.ts +1 -0
- package/dist/data/ai/session-categories.d.ts.map +1 -1
- package/dist/data/ai/session-categories.js +4 -0
- package/dist/data/ai/session-categories.js.map +1 -1
- package/dist/data/ai/use-session-scroll.cjs +49 -21
- package/dist/data/ai/use-session-scroll.cjs.map +1 -1
- package/dist/data/ai/use-session-scroll.d.ts +2 -0
- package/dist/data/ai/use-session-scroll.d.ts.map +1 -1
- package/dist/data/ai/use-session-scroll.js +49 -21
- package/dist/data/ai/use-session-scroll.js.map +1 -1
- package/dist/data/chat/Chat.runtime.cjs +1 -1
- package/dist/data/chat/Chat.runtime.cjs.map +1 -1
- package/dist/data/chat/Chat.runtime.d.ts.map +1 -1
- package/dist/data/chat/Chat.runtime.js +1 -1
- package/dist/data/chat/Chat.runtime.js.map +1 -1
- package/dist/data/graph-columns-layout.cjs +216 -0
- package/dist/data/graph-columns-layout.cjs.map +1 -0
- package/dist/data/graph-columns-layout.d.ts +56 -0
- package/dist/data/graph-columns-layout.d.ts.map +1 -0
- package/dist/data/graph-columns-layout.js +216 -0
- package/dist/data/graph-columns-layout.js.map +1 -0
- package/dist/data/graph-diagram-model.cjs +73 -0
- package/dist/data/graph-diagram-model.cjs.map +1 -0
- package/dist/data/graph-diagram-model.d.ts +90 -0
- package/dist/data/graph-diagram-model.d.ts.map +1 -0
- package/dist/data/graph-diagram-model.js +73 -0
- package/dist/data/graph-diagram-model.js.map +1 -0
- package/dist/data/graph-edge-routing.cjs +235 -0
- package/dist/data/graph-edge-routing.cjs.map +1 -0
- package/dist/data/graph-edge-routing.d.ts +73 -0
- package/dist/data/graph-edge-routing.d.ts.map +1 -0
- package/dist/data/graph-edge-routing.js +235 -0
- package/dist/data/graph-edge-routing.js.map +1 -0
- package/dist/data/graph-layout.cjs +0 -82
- package/dist/data/graph-layout.cjs.map +1 -1
- package/dist/data/graph-layout.d.ts +1 -28
- package/dist/data/graph-layout.d.ts.map +1 -1
- package/dist/data/graph-layout.js +1 -83
- package/dist/data/graph-layout.js.map +1 -1
- package/dist/data/har/HarPanel.cjs +129 -33
- package/dist/data/har/HarPanel.cjs.map +1 -1
- package/dist/data/har/HarPanel.d.ts +13 -1
- package/dist/data/har/HarPanel.d.ts.map +1 -1
- package/dist/data/har/HarPanel.js +130 -34
- package/dist/data/har/HarPanel.js.map +1 -1
- package/dist/data/har/fixtures.d.ts +12 -0
- package/dist/data/har/fixtures.d.ts.map +1 -1
- package/dist/data/har/types.d.ts +12 -0
- package/dist/data/har/types.d.ts.map +1 -1
- package/dist/data/runtime/RuntimeBar.cjs +67 -84
- package/dist/data/runtime/RuntimeBar.cjs.map +1 -1
- package/dist/data/runtime/RuntimeBar.d.ts +4 -5
- package/dist/data/runtime/RuntimeBar.d.ts.map +1 -1
- package/dist/data/runtime/RuntimeBar.fields.cjs +170 -0
- package/dist/data/runtime/RuntimeBar.fields.cjs.map +1 -0
- package/dist/data/runtime/RuntimeBar.fields.d.ts +16 -0
- package/dist/data/runtime/RuntimeBar.fields.d.ts.map +1 -0
- package/dist/data/runtime/RuntimeBar.fields.js +170 -0
- package/dist/data/runtime/RuntimeBar.fields.js.map +1 -0
- package/dist/data/runtime/RuntimeBar.js +70 -87
- package/dist/data/runtime/RuntimeBar.js.map +1 -1
- package/dist/data/runtime/RuntimeBar.selection.cjs +56 -0
- package/dist/data/runtime/RuntimeBar.selection.cjs.map +1 -0
- package/dist/data/runtime/RuntimeBar.selection.d.ts +20 -0
- package/dist/data/runtime/RuntimeBar.selection.d.ts.map +1 -0
- package/dist/data/runtime/RuntimeBar.selection.js +56 -0
- package/dist/data/runtime/RuntimeBar.selection.js.map +1 -0
- package/dist/data/runtime/RuntimeBarActions.cjs +10 -6
- package/dist/data/runtime/RuntimeBarActions.cjs.map +1 -1
- package/dist/data/runtime/RuntimeBarActions.d.ts +8 -1
- package/dist/data/runtime/RuntimeBarActions.d.ts.map +1 -1
- package/dist/data/runtime/RuntimeBarActions.js +10 -6
- package/dist/data/runtime/RuntimeBarActions.js.map +1 -1
- package/dist/data/runtime/RuntimeBarIdentity.cjs +166 -0
- package/dist/data/runtime/RuntimeBarIdentity.cjs.map +1 -0
- package/dist/data/runtime/RuntimeBarIdentity.d.ts +25 -0
- package/dist/data/runtime/RuntimeBarIdentity.d.ts.map +1 -0
- package/dist/data/runtime/RuntimeBarIdentity.js +166 -0
- package/dist/data/runtime/RuntimeBarIdentity.js.map +1 -0
- package/dist/data/runtime/RuntimeBarLayout.cjs +95 -0
- package/dist/data/runtime/RuntimeBarLayout.cjs.map +1 -0
- package/dist/data/runtime/RuntimeBarLayout.d.ts +9 -0
- package/dist/data/runtime/RuntimeBarLayout.d.ts.map +1 -0
- package/dist/data/runtime/RuntimeBarLayout.js +95 -0
- package/dist/data/runtime/RuntimeBarLayout.js.map +1 -0
- package/dist/data/runtime/RuntimeBarSegment.cjs +25 -14
- package/dist/data/runtime/RuntimeBarSegment.cjs.map +1 -1
- package/dist/data/runtime/RuntimeBarSegment.d.ts +4 -0
- package/dist/data/runtime/RuntimeBarSegment.d.ts.map +1 -1
- package/dist/data/runtime/RuntimeBarSegment.js +25 -14
- package/dist/data/runtime/RuntimeBarSegment.js.map +1 -1
- package/dist/data/runtime/RuntimeLimitInput.cjs +41 -0
- package/dist/data/runtime/RuntimeLimitInput.cjs.map +1 -0
- package/dist/data/runtime/RuntimeLimitInput.d.ts +9 -0
- package/dist/data/runtime/RuntimeLimitInput.d.ts.map +1 -0
- package/dist/data/runtime/RuntimeLimitInput.js +41 -0
- package/dist/data/runtime/RuntimeLimitInput.js.map +1 -0
- package/dist/data/runtime/use-runtime-bar-overflow.cjs +70 -0
- package/dist/data/runtime/use-runtime-bar-overflow.cjs.map +1 -0
- package/dist/data/runtime/use-runtime-bar-overflow.d.ts +13 -0
- package/dist/data/runtime/use-runtime-bar-overflow.d.ts.map +1 -0
- package/dist/data/runtime/use-runtime-bar-overflow.js +70 -0
- package/dist/data/runtime/use-runtime-bar-overflow.js.map +1 -0
- package/dist/data/use-edge-focus.cjs +20 -0
- package/dist/data/use-edge-focus.cjs.map +1 -0
- package/dist/data/use-edge-focus.d.ts +23 -0
- package/dist/data/use-edge-focus.d.ts.map +1 -0
- package/dist/data/use-edge-focus.js +20 -0
- package/dist/data/use-edge-focus.js.map +1 -0
- package/dist/data/use-pan-zoom.cjs +159 -0
- package/dist/data/use-pan-zoom.cjs.map +1 -0
- package/dist/data/use-pan-zoom.d.ts +79 -0
- package/dist/data/use-pan-zoom.d.ts.map +1 -0
- package/dist/data/use-pan-zoom.js +159 -0
- package/dist/data/use-pan-zoom.js.map +1 -0
- package/dist/data/version-info.cjs +3 -3
- package/dist/data/version-info.js +3 -3
- package/dist/data.cjs +5 -1
- package/dist/data.cjs.map +1 -1
- package/dist/data.d.ts +4 -3
- package/dist/data.d.ts.map +1 -1
- package/dist/data.js +6 -2
- package/dist/data.js.map +1 -1
- package/dist/index.cjs +5 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/dist/overlay/DropdownMenu.cjs +1 -0
- package/dist/overlay/DropdownMenu.cjs.map +1 -1
- package/dist/overlay/DropdownMenu.d.ts +4 -0
- package/dist/overlay/DropdownMenu.d.ts.map +1 -1
- package/dist/overlay/DropdownMenu.js +1 -0
- package/dist/overlay/DropdownMenu.js.map +1 -1
- package/dist/overlay/DropdownMenuSubmenu.cjs +31 -15
- package/dist/overlay/DropdownMenuSubmenu.cjs.map +1 -1
- package/dist/overlay/DropdownMenuSubmenu.d.ts.map +1 -1
- package/dist/overlay/DropdownMenuSubmenu.js +31 -15
- package/dist/overlay/DropdownMenuSubmenu.js.map +1 -1
- package/dist/rpc/OperationCatalog.cjs +3 -1
- package/dist/rpc/OperationCatalog.cjs.map +1 -1
- package/dist/rpc/OperationCatalog.d.ts +3 -1
- package/dist/rpc/OperationCatalog.d.ts.map +1 -1
- package/dist/rpc/OperationCatalog.js +3 -1
- package/dist/rpc/OperationCatalog.js.map +1 -1
- package/dist/rpc/useOperationPages.cjs +6 -1
- package/dist/rpc/useOperationPages.cjs.map +1 -1
- package/dist/rpc/useOperationPages.d.ts +3 -1
- package/dist/rpc/useOperationPages.d.ts.map +1 -1
- package/dist/rpc/useOperationPages.js +6 -1
- package/dist/rpc/useOperationPages.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
- package/schemas/json-schema-form.schema.json +5 -0
- package/dist/data/runtime/RuntimeBarCombo.cjs +0 -423
- package/dist/data/runtime/RuntimeBarCombo.cjs.map +0 -1
- package/dist/data/runtime/RuntimeBarCombo.d.ts +0 -33
- package/dist/data/runtime/RuntimeBarCombo.d.ts.map +0 -1
- package/dist/data/runtime/RuntimeBarCombo.js +0 -423
- package/dist/data/runtime/RuntimeBarCombo.js.map +0 -1
- package/dist/data/runtime/RuntimeBarLimits.cjs +0 -262
- package/dist/data/runtime/RuntimeBarLimits.cjs.map +0 -1
- package/dist/data/runtime/RuntimeBarLimits.d.ts +0 -17
- package/dist/data/runtime/RuntimeBarLimits.d.ts.map +0 -1
- package/dist/data/runtime/RuntimeBarLimits.js +0 -262
- package/dist/data/runtime/RuntimeBarLimits.js.map +0 -1
- package/dist/data/runtime/RuntimeBarSegments.cjs +0 -346
- package/dist/data/runtime/RuntimeBarSegments.cjs.map +0 -1
- package/dist/data/runtime/RuntimeBarSegments.d.ts +0 -37
- package/dist/data/runtime/RuntimeBarSegments.d.ts.map +0 -1
- package/dist/data/runtime/RuntimeBarSegments.js +0 -346
- package/dist/data/runtime/RuntimeBarSegments.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SessionViewer.input.cjs","sources":["../../../src/data/ai/SessionViewer.input.ts"],"sourcesContent":["// Presentation helpers for a tool call's input: the one-line summary, the\n// JetBrains-style inline params, the inline shell command, and the line diff\n// for file-writing tools. Pure functions — the viewer renders their output.\n\nimport { computeLineDiff } from \"../code-diff\";\nimport { languageFromPath } from \"../code-highlight\";\nimport { stripTrailingSlashes } from \"../../lib/string\";\nimport { splitMcpTool, truncate } from \"./SessionViewer.model\";\n\n/** Strip the event's working directory from an absolute file path. */\nexport function relativizePath(path: string, cwd?: string): string {\n if (!cwd) return path;\n const base = stripTrailingSlashes(cwd);\n return path.startsWith(`${base}/`) ? path.slice(base.length + 1) : path;\n}\n\n/** The raw shell command of a shell-execution tool call, if present. Shell rows\n * render this inline as a bash code block instead of the generic label +\n * tool-input JSON. */\nexport function shellCommand(\n tool: string,\n input?: Record<string, unknown>,\n): string | undefined {\n if (tool !== \"Bash\") return undefined;\n const command = input?.[\"command\"];\n return typeof command === \"string\" && command ? command : undefined;\n}\n\nexport interface ToolParam {\n name: string;\n value: string;\n}\n\nexport interface SessionQuestionOption {\n value: string;\n label: string;\n description?: string;\n}\n\nexport interface SessionQuestion {\n id: string;\n text: string;\n context?: string;\n multiSelect?: boolean;\n isOther?: boolean;\n options: SessionQuestionOption[];\n}\n\n// Keys already rendered elsewhere in the row — the file-path heading, the\n// inline shell command, or the diff — so they don't repeat as inline params.\nconst CONSUMED_INPUT_KEYS: Record<string, readonly string[]> = {\n Bash: [\"command\"],\n Read: [\"file_path\", \"notebook_path\", \"path\"],\n Write: [\"file_path\", \"notebook_path\", \"path\", \"content\"],\n Edit: [\"file_path\", \"notebook_path\", \"path\", \"old_string\", \"new_string\"],\n MultiEdit: [\"file_path\", \"notebook_path\", \"path\", \"edits\"],\n NotebookEdit: [\"file_path\", \"notebook_path\", \"path\"],\n AskUserQuestion: [\"questions\", \"question\", \"prompt\", \"text\", \"header\", \"context\", \"description\", \"options\"],\n};\n\n/** Flatten a tool's input into JetBrains-style `name: value` inline params:\n * single-line values, cwd-relativized and truncated so the row never wraps. */\nexport function toolInputParams(\n tool: string,\n input?: Record<string, unknown>,\n cwd?: string,\n): ToolParam[] {\n const consumed = CONSUMED_INPUT_KEYS[tool] ?? [];\n return Object.entries(input ?? {})\n .filter(\n ([name, value]) =>\n !consumed.includes(name) &&\n value !== undefined &&\n value !== null &&\n value !== \"\",\n )\n .map(([name, value]) => ({ name, value: paramValue(value, cwd) }));\n}\n\nfunction paramValue(value: unknown, cwd?: string): string {\n const text =\n typeof value === \"string\"\n ? relativizePath(value, cwd)\n : JSON.stringify(value);\n return truncate(text.replace(/\\s+/g, \" \").trim(), 60);\n}\n\n/** One before/after edit, rendered as a language-aware diff. */\nexport interface DiffSegment {\n original: string;\n modified: string;\n}\n\nexport interface ToolDiff {\n added: number;\n removed: number;\n /** Edits as original→modified pairs (Write has one; MultiEdit has several). */\n segments: DiffSegment[];\n /** Highlighter hint from the file extension, when known. */\n language?: string;\n}\n\n// Added/removed line counts from a real LCS diff — context lines don't count,\n// so a no-op edit reports 0/0 (and yields no diff).\nfunction diffCounts(segments: DiffSegment[]): {\n added: number;\n removed: number;\n} {\n let added = 0;\n let removed = 0;\n for (const { original, modified } of segments) {\n for (const hunk of computeLineDiff(original, modified)) {\n for (const line of hunk.lines) {\n if (line.type === \"add\") added += 1;\n else if (line.type === \"remove\") removed += 1;\n }\n }\n }\n return { added, removed };\n}\n\n/** The content change of a file-writing tool call as before/after segments —\n * Write is one all-additions segment; Edit/MultiEdit pair old and new text. */\nexport function toolDiff(\n tool: string,\n input?: Record<string, unknown>,\n): ToolDiff | undefined {\n if (!input) return undefined;\n const str = (key: string): string =>\n typeof input[key] === \"string\" ? (input[key] as string) : \"\";\n\n const segments = toolDiffSegments(tool, input, str);\n if (!segments || segments.length === 0) return undefined;\n const counts = diffCounts(segments);\n if (counts.added === 0 && counts.removed === 0) return undefined;\n\n const language = languageFromPath(\n str(\"file_path\") || str(\"notebook_path\") || str(\"path\"),\n );\n return { ...counts, segments, ...(language ? { language } : {}) };\n}\n\nfunction toolDiffSegments(\n tool: string,\n input: Record<string, unknown>,\n str: (key: string) => string,\n): DiffSegment[] | undefined {\n if (tool === \"Write\") {\n const content = str(\"content\");\n return content ? [{ original: \"\", modified: content }] : undefined;\n }\n if (tool === \"Edit\" || tool === \"NotebookEdit\") {\n const original = str(\"old_string\");\n const modified = str(\"new_string\") || str(\"new_source\");\n return original || modified ? [{ original, modified }] : undefined;\n }\n if (tool === \"MultiEdit\") {\n const edits = input[\"edits\"];\n if (!Array.isArray(edits)) return undefined;\n return edits\n .filter(\n (edit): edit is Record<string, unknown> =>\n typeof edit === \"object\" && edit !== null,\n )\n .map((edit) => ({\n original:\n typeof edit[\"old_string\"] === \"string\"\n ? (edit[\"old_string\"] as string)\n : \"\",\n modified:\n typeof edit[\"new_string\"] === \"string\"\n ? (edit[\"new_string\"] as string)\n : \"\",\n }))\n .filter((segment) => segment.original !== \"\" || segment.modified !== \"\");\n }\n return undefined;\n}\n\n// summarizeToolInput condenses a tool's input into a one-line preview, ported\n// from captain's history.FormatToolUseSummary so the viewer reads like the CLI.\nexport function summarizeToolInput(\n tool: string,\n input?: Record<string, unknown>,\n cwd?: string,\n): string {\n if (!input) return \"\";\n const str = (key: string): string =>\n typeof input[key] === \"string\" ? (input[key] as string) : \"\";\n const first = (...keys: string[]): string => {\n for (const key of keys) {\n const value = str(key);\n if (value) return value;\n }\n return \"\";\n };\n\n const mcp = splitMcpTool(tool);\n if (mcp) {\n const arg = first(\"url\", \"sql\", \"query\", \"element\", \"method\");\n return arg ? truncate(arg, 80) : \"\";\n }\n\n switch (tool) {\n case \"Bash\":\n case \"browser_type\":\n return str(\"command\") || str(\"text\");\n case \"Read\":\n case \"Write\":\n case \"Edit\":\n case \"MultiEdit\":\n case \"NotebookEdit\":\n return relativizePath(first(\"file_path\", \"notebook_path\", \"path\"), cwd);\n case \"Grep\":\n return [str(\"pattern\"), str(\"path\")].filter(Boolean).join(\" \");\n case \"Glob\":\n return str(\"pattern\");\n case \"Task\":\n case \"Agent\":\n return first(\"description\", \"prompt\");\n case \"Skill\":\n return first(\"skill\", \"command\", \"name\");\n case \"TaskCreate\":\n return first(\"subject\", \"description\");\n case \"TaskUpdate\": {\n const id = first(\"taskId\", \"task_id\", \"id\");\n const status = str(\"status\");\n return status ? `${id} ${status}`.trim() : id;\n }\n case \"TaskGet\":\n case \"TaskOutput\":\n case \"TaskStop\":\n return first(\"task_id\", \"taskId\", \"id\");\n case \"ToolSearch\":\n case \"WebSearch\":\n return str(\"query\");\n case \"WebFetch\":\n case \"browser_navigate\":\n return str(\"url\");\n case \"AskUserQuestion\": {\n const questions = questionsFromToolInput(input);\n const rawQuestions = input[\"questions\"];\n if (questions.length > 1) return `${questions.length} questions`;\n if (questions[0]?.text) return truncate(questions[0].text, 80);\n if (Array.isArray(rawQuestions) && rawQuestions.length > 0) return `${rawQuestions.length} questions`;\n return \"\";\n }\n case \"ExitPlanMode\":\n return str(\"planFilePath\");\n default:\n return \"\";\n }\n}\n\nexport function questionsFromToolInput(input?: Record<string, unknown>): SessionQuestion[] {\n if (!input) return [];\n const rawQuestions = input.questions;\n if (Array.isArray(rawQuestions)) {\n return rawQuestions\n .map((question, index) => questionFromValue(question, index))\n .filter((question): question is SessionQuestion => question !== null);\n }\n\n const text = stringField(input, \"question\") || stringField(input, \"prompt\") || stringField(input, \"text\");\n if (!text) return [];\n return [{\n id: stringField(input, \"id\") || \"1\",\n text,\n ...optionalContext(input),\n multiSelect: booleanField(input, \"multiSelect\") || booleanField(input, \"multi_select\"),\n options: optionList(input.options),\n }];\n}\n\nfunction questionFromValue(value: unknown, index: number): SessionQuestion | null {\n if (typeof value === \"string\") {\n const text = value.trim();\n return text ? { id: String(index + 1), text, options: [] } : null;\n }\n if (!isRecord(value)) return null;\n const text =\n stringField(value, \"question\") ||\n stringField(value, \"text\") ||\n stringField(value, \"prompt\") ||\n stringField(value, \"label\");\n if (!text) return null;\n return {\n id: stringField(value, \"id\") || String(index + 1),\n text,\n ...optionalContext(value),\n multiSelect: booleanField(value, \"multiSelect\") || booleanField(value, \"multi_select\"),\n ...(booleanField(value, \"isOther\") || booleanField(value, \"is_other\") ? { isOther: true } : {}),\n options: optionList(value.options),\n };\n}\n\nfunction optionList(value: unknown): SessionQuestionOption[] {\n if (!Array.isArray(value)) return [];\n return value.flatMap((option, index) => {\n if (typeof option === \"string\") {\n const label = option.trim();\n return label ? [{ value: label, label }] : [];\n }\n if (!isRecord(option)) return [];\n const label =\n stringField(option, \"label\") ||\n stringField(option, \"value\") ||\n stringField(option, \"id\") ||\n stringField(option, \"description\");\n if (!label) return [];\n const value = stringField(option, \"value\") || stringField(option, \"id\") || label;\n const description = stringField(option, \"description\");\n return [{\n value: value || String(index + 1),\n label,\n ...(description && description !== label ? { description } : {}),\n }];\n });\n}\n\nfunction optionalContext(input: Record<string, unknown>): Pick<SessionQuestion, \"context\"> {\n const context = stringField(input, \"header\") || stringField(input, \"context\") || stringField(input, \"description\");\n return context ? { context } : {};\n}\n\nfunction stringField(input: Record<string, unknown>, key: string): string {\n const value = input[key];\n return typeof value === \"string\" ? value.trim() : \"\";\n}\n\nfunction booleanField(input: Record<string, unknown>, key: string): boolean {\n return input[key] === true;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return !!value && typeof value === \"object\" && !Array.isArray(value);\n}\n"],"names":["stripTrailingSlashes","truncate","computeLineDiff","languageFromPath","splitMcpTool","text","label","value"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SessionViewer.input.cjs","sources":["../../../src/data/ai/SessionViewer.input.ts"],"sourcesContent":["// Presentation helpers for a tool call's input: the one-line summary, the\n// JetBrains-style inline params, the inline shell command, and the line diff\n// for file-writing tools. Pure functions — the viewer renders their output.\n\nimport { computeLineDiff } from \"../code-diff\";\nimport { languageFromPath } from \"../code-highlight\";\nimport { stripTrailingSlashes } from \"../../lib/string\";\nimport { splitMcpTool, truncate } from \"./SessionViewer.model\";\nimport type { ApprovalQuestion } from \"./approval-request\";\n\n/** Strip the event's working directory from an absolute file path. */\nexport function relativizePath(path: string, cwd?: string): string {\n if (!cwd) return path;\n const base = stripTrailingSlashes(cwd);\n return path.startsWith(`${base}/`) ? path.slice(base.length + 1) : path;\n}\n\n/** The raw shell command of a shell-execution tool call, if present. Shell rows\n * render this inline as a bash code block instead of the generic label +\n * tool-input JSON. */\nexport function shellCommand(\n tool: string,\n input?: Record<string, unknown>,\n): string | undefined {\n if (tool !== \"Bash\") return undefined;\n const command = input?.[\"command\"];\n return typeof command === \"string\" && command ? command : undefined;\n}\n\nexport interface ToolParam {\n name: string;\n value: string;\n}\n\nexport interface SessionQuestionOption {\n value: string;\n label: string;\n description?: string;\n}\n\nexport interface SessionQuestion {\n id: string;\n text: string;\n context?: string;\n multiSelect?: boolean;\n isOther?: boolean;\n options: SessionQuestionOption[];\n}\n\n// Keys already rendered elsewhere in the row — the file-path heading, the\n// inline shell command, or the diff — so they don't repeat as inline params.\nconst CONSUMED_INPUT_KEYS: Record<string, readonly string[]> = {\n Bash: [\"command\"],\n Read: [\"file_path\", \"notebook_path\", \"path\"],\n Write: [\"file_path\", \"notebook_path\", \"path\", \"content\"],\n Edit: [\"file_path\", \"notebook_path\", \"path\", \"old_string\", \"new_string\"],\n MultiEdit: [\"file_path\", \"notebook_path\", \"path\", \"edits\"],\n NotebookEdit: [\"file_path\", \"notebook_path\", \"path\"],\n AskUserQuestion: [\"questions\", \"question\", \"prompt\", \"text\", \"header\", \"context\", \"description\", \"options\"],\n};\n\n/** Flatten a tool's input into JetBrains-style `name: value` inline params:\n * single-line values, cwd-relativized and truncated so the row never wraps. */\nexport function toolInputParams(\n tool: string,\n input?: Record<string, unknown>,\n cwd?: string,\n): ToolParam[] {\n const consumed = CONSUMED_INPUT_KEYS[tool] ?? [];\n return Object.entries(input ?? {})\n .filter(\n ([name, value]) =>\n !consumed.includes(name) &&\n value !== undefined &&\n value !== null &&\n value !== \"\",\n )\n .map(([name, value]) => ({ name, value: paramValue(value, cwd) }));\n}\n\nfunction paramValue(value: unknown, cwd?: string): string {\n const text =\n typeof value === \"string\"\n ? relativizePath(value, cwd)\n : JSON.stringify(value);\n return truncate(text.replace(/\\s+/g, \" \").trim(), 60);\n}\n\n/** One before/after edit, rendered as a language-aware diff. */\nexport interface DiffSegment {\n original: string;\n modified: string;\n}\n\nexport interface ToolDiff {\n added: number;\n removed: number;\n /** Edits as original→modified pairs (Write has one; MultiEdit has several). */\n segments: DiffSegment[];\n /** Highlighter hint from the file extension, when known. */\n language?: string;\n}\n\n// Added/removed line counts from a real LCS diff — context lines don't count,\n// so a no-op edit reports 0/0 (and yields no diff).\nfunction diffCounts(segments: DiffSegment[]): {\n added: number;\n removed: number;\n} {\n let added = 0;\n let removed = 0;\n for (const { original, modified } of segments) {\n for (const hunk of computeLineDiff(original, modified)) {\n for (const line of hunk.lines) {\n if (line.type === \"add\") added += 1;\n else if (line.type === \"remove\") removed += 1;\n }\n }\n }\n return { added, removed };\n}\n\n/** The content change of a file-writing tool call as before/after segments —\n * Write is one all-additions segment; Edit/MultiEdit pair old and new text. */\nexport function toolDiff(\n tool: string,\n input?: Record<string, unknown>,\n): ToolDiff | undefined {\n if (!input) return undefined;\n const str = (key: string): string =>\n typeof input[key] === \"string\" ? (input[key] as string) : \"\";\n\n const segments = toolDiffSegments(tool, input, str);\n if (!segments || segments.length === 0) return undefined;\n const counts = diffCounts(segments);\n if (counts.added === 0 && counts.removed === 0) return undefined;\n\n const language = languageFromPath(\n str(\"file_path\") || str(\"notebook_path\") || str(\"path\"),\n );\n return { ...counts, segments, ...(language ? { language } : {}) };\n}\n\nfunction toolDiffSegments(\n tool: string,\n input: Record<string, unknown>,\n str: (key: string) => string,\n): DiffSegment[] | undefined {\n if (tool === \"Write\") {\n const content = str(\"content\");\n return content ? [{ original: \"\", modified: content }] : undefined;\n }\n if (tool === \"Edit\" || tool === \"NotebookEdit\") {\n const original = str(\"old_string\");\n const modified = str(\"new_string\") || str(\"new_source\");\n return original || modified ? [{ original, modified }] : undefined;\n }\n if (tool === \"MultiEdit\") {\n const edits = input[\"edits\"];\n if (!Array.isArray(edits)) return undefined;\n return edits\n .filter(\n (edit): edit is Record<string, unknown> =>\n typeof edit === \"object\" && edit !== null,\n )\n .map((edit) => ({\n original:\n typeof edit[\"old_string\"] === \"string\"\n ? (edit[\"old_string\"] as string)\n : \"\",\n modified:\n typeof edit[\"new_string\"] === \"string\"\n ? (edit[\"new_string\"] as string)\n : \"\",\n }))\n .filter((segment) => segment.original !== \"\" || segment.modified !== \"\");\n }\n return undefined;\n}\n\n// summarizeToolInput condenses a tool's input into a one-line preview, ported\n// from captain's history.FormatToolUseSummary so the viewer reads like the CLI.\nexport function summarizeToolInput(\n tool: string,\n input?: Record<string, unknown>,\n cwd?: string,\n): string {\n if (!input) return \"\";\n const str = (key: string): string =>\n typeof input[key] === \"string\" ? (input[key] as string) : \"\";\n const first = (...keys: string[]): string => {\n for (const key of keys) {\n const value = str(key);\n if (value) return value;\n }\n return \"\";\n };\n\n const mcp = splitMcpTool(tool);\n if (mcp) {\n const arg = first(\"url\", \"sql\", \"query\", \"element\", \"method\");\n return arg ? truncate(arg, 80) : \"\";\n }\n\n switch (tool) {\n case \"Bash\":\n case \"browser_type\":\n return str(\"command\") || str(\"text\");\n case \"Read\":\n case \"Write\":\n case \"Edit\":\n case \"MultiEdit\":\n case \"NotebookEdit\":\n return relativizePath(first(\"file_path\", \"notebook_path\", \"path\"), cwd);\n case \"Grep\":\n return [str(\"pattern\"), str(\"path\")].filter(Boolean).join(\" \");\n case \"Glob\":\n return str(\"pattern\");\n case \"Task\":\n case \"Agent\":\n return first(\"description\", \"prompt\");\n case \"Skill\":\n return first(\"skill\", \"command\", \"name\");\n case \"TaskCreate\":\n return first(\"subject\", \"description\");\n case \"TaskUpdate\": {\n const id = first(\"taskId\", \"task_id\", \"id\");\n const status = str(\"status\");\n return status ? `${id} ${status}`.trim() : id;\n }\n case \"TaskGet\":\n case \"TaskOutput\":\n case \"TaskStop\":\n return first(\"task_id\", \"taskId\", \"id\");\n case \"ToolSearch\":\n case \"WebSearch\":\n return str(\"query\");\n case \"WebFetch\":\n case \"browser_navigate\":\n return str(\"url\");\n case \"AskUserQuestion\": {\n const questions = questionsFromToolInput(input);\n const rawQuestions = input[\"questions\"];\n if (questions.length > 1) return `${questions.length} questions`;\n if (questions[0]?.text) return truncate(questions[0].text, 80);\n if (Array.isArray(rawQuestions) && rawQuestions.length > 0) return `${rawQuestions.length} questions`;\n return \"\";\n }\n case \"ExitPlanMode\":\n return str(\"planFilePath\");\n default:\n return \"\";\n }\n}\n\n/** Maps a typed approval's questions (captain `TerminalQuestion`) to the\n * viewer's question shape. Answers are keyed by `id`, or by the question text\n * when the provider gives none, which is how captain reads them back. */\nexport function questionsFromApproval(questions: readonly ApprovalQuestion[]): SessionQuestion[] {\n return questions.map((question) => ({\n id: question.id || question.text,\n text: question.text,\n ...(question.context ? { context: question.context } : {}),\n ...(question.multiSelect ? { multiSelect: true } : {}),\n options: (question.options ?? []).map((option) => {\n const description = question.optionDescriptions?.[option];\n return { value: option, label: option, ...(description ? { description } : {}) };\n }),\n }));\n}\n\nexport function questionsFromToolInput(input?: Record<string, unknown>): SessionQuestion[] {\n if (!input) return [];\n const rawQuestions = input.questions;\n if (Array.isArray(rawQuestions)) {\n return rawQuestions\n .map((question, index) => questionFromValue(question, index))\n .filter((question): question is SessionQuestion => question !== null);\n }\n\n const text = stringField(input, \"question\") || stringField(input, \"prompt\") || stringField(input, \"text\");\n if (!text) return [];\n return [{\n id: stringField(input, \"id\") || \"1\",\n text,\n ...optionalContext(input),\n multiSelect: booleanField(input, \"multiSelect\") || booleanField(input, \"multi_select\"),\n options: optionList(input.options),\n }];\n}\n\nfunction questionFromValue(value: unknown, index: number): SessionQuestion | null {\n if (typeof value === \"string\") {\n const text = value.trim();\n return text ? { id: String(index + 1), text, options: [] } : null;\n }\n if (!isRecord(value)) return null;\n const text =\n stringField(value, \"question\") ||\n stringField(value, \"text\") ||\n stringField(value, \"prompt\") ||\n stringField(value, \"label\");\n if (!text) return null;\n return {\n id: stringField(value, \"id\") || String(index + 1),\n text,\n ...optionalContext(value),\n multiSelect: booleanField(value, \"multiSelect\") || booleanField(value, \"multi_select\"),\n ...(booleanField(value, \"isOther\") || booleanField(value, \"is_other\") ? { isOther: true } : {}),\n options: optionList(value.options),\n };\n}\n\nfunction optionList(value: unknown): SessionQuestionOption[] {\n if (!Array.isArray(value)) return [];\n return value.flatMap((option, index) => {\n if (typeof option === \"string\") {\n const label = option.trim();\n return label ? [{ value: label, label }] : [];\n }\n if (!isRecord(option)) return [];\n const label =\n stringField(option, \"label\") ||\n stringField(option, \"value\") ||\n stringField(option, \"id\") ||\n stringField(option, \"description\");\n if (!label) return [];\n const value = stringField(option, \"value\") || stringField(option, \"id\") || label;\n const description = stringField(option, \"description\");\n return [{\n value: value || String(index + 1),\n label,\n ...(description && description !== label ? { description } : {}),\n }];\n });\n}\n\nfunction optionalContext(input: Record<string, unknown>): Pick<SessionQuestion, \"context\"> {\n const context = stringField(input, \"header\") || stringField(input, \"context\") || stringField(input, \"description\");\n return context ? { context } : {};\n}\n\nfunction stringField(input: Record<string, unknown>, key: string): string {\n const value = input[key];\n return typeof value === \"string\" ? value.trim() : \"\";\n}\n\nfunction booleanField(input: Record<string, unknown>, key: string): boolean {\n return input[key] === true;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return !!value && typeof value === \"object\" && !Array.isArray(value);\n}\n"],"names":["stripTrailingSlashes","truncate","computeLineDiff","languageFromPath","splitMcpTool","text","label","value"],"mappings":"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"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ApprovalQuestion } from './approval-request.js';
|
|
1
2
|
/** Strip the event's working directory from an absolute file path. */
|
|
2
3
|
export declare function relativizePath(path: string, cwd?: string): string;
|
|
3
4
|
/** The raw shell command of a shell-execution tool call, if present. Shell rows
|
|
@@ -41,5 +42,9 @@ export interface ToolDiff {
|
|
|
41
42
|
* Write is one all-additions segment; Edit/MultiEdit pair old and new text. */
|
|
42
43
|
export declare function toolDiff(tool: string, input?: Record<string, unknown>): ToolDiff | undefined;
|
|
43
44
|
export declare function summarizeToolInput(tool: string, input?: Record<string, unknown>, cwd?: string): string;
|
|
45
|
+
/** Maps a typed approval's questions (captain `TerminalQuestion`) to the
|
|
46
|
+
* viewer's question shape. Answers are keyed by `id`, or by the question text
|
|
47
|
+
* when the provider gives none, which is how captain reads them back. */
|
|
48
|
+
export declare function questionsFromApproval(questions: readonly ApprovalQuestion[]): SessionQuestion[];
|
|
44
49
|
export declare function questionsFromToolInput(input?: Record<string, unknown>): SessionQuestion[];
|
|
45
50
|
//# sourceMappingURL=SessionViewer.input.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SessionViewer.input.d.ts","sourceRoot":"","sources":["../../../src/data/ai/SessionViewer.input.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"SessionViewer.input.d.ts","sourceRoot":"","sources":["../../../src/data/ai/SessionViewer.input.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAE3D,sEAAsE;AACtE,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAIjE;AAED;;uBAEuB;AACvB,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM,EACZ,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,MAAM,GAAG,SAAS,CAIpB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,qBAAqB,EAAE,CAAC;CAClC;AAcD;gFACgF;AAChF,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,EACZ,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,GAAG,CAAC,EAAE,MAAM,GACX,SAAS,EAAE,CAWb;AAUD,gEAAgE;AAChE,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,+EAA+E;IAC/E,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAqBD;gFACgF;AAChF,wBAAgB,QAAQ,CACtB,IAAI,EAAE,MAAM,EACZ,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,QAAQ,GAAG,SAAS,CActB;AAyCD,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,EACZ,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,GAAG,CAAC,EAAE,MAAM,GACX,MAAM,CAmER;AAED;;0EAE0E;AAC1E,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,SAAS,gBAAgB,EAAE,GAAG,eAAe,EAAE,CAW/F;AAED,wBAAgB,sBAAsB,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,eAAe,EAAE,CAkBzF"}
|
|
@@ -144,6 +144,19 @@ function summarizeToolInput(tool, input, cwd) {
|
|
|
144
144
|
return "";
|
|
145
145
|
}
|
|
146
146
|
}
|
|
147
|
+
function questionsFromApproval(questions) {
|
|
148
|
+
return questions.map((question) => ({
|
|
149
|
+
id: question.id || question.text,
|
|
150
|
+
text: question.text,
|
|
151
|
+
...question.context ? { context: question.context } : {},
|
|
152
|
+
...question.multiSelect ? { multiSelect: true } : {},
|
|
153
|
+
options: (question.options ?? []).map((option) => {
|
|
154
|
+
var _a;
|
|
155
|
+
const description = (_a = question.optionDescriptions) == null ? void 0 : _a[option];
|
|
156
|
+
return { value: option, label: option, ...description ? { description } : {} };
|
|
157
|
+
})
|
|
158
|
+
}));
|
|
159
|
+
}
|
|
147
160
|
function questionsFromToolInput(input) {
|
|
148
161
|
if (!input) return [];
|
|
149
162
|
const rawQuestions = input.questions;
|
|
@@ -211,6 +224,7 @@ function isRecord(value) {
|
|
|
211
224
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
212
225
|
}
|
|
213
226
|
export {
|
|
227
|
+
questionsFromApproval,
|
|
214
228
|
questionsFromToolInput,
|
|
215
229
|
relativizePath,
|
|
216
230
|
shellCommand,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SessionViewer.input.js","sources":["../../../src/data/ai/SessionViewer.input.ts"],"sourcesContent":["// Presentation helpers for a tool call's input: the one-line summary, the\n// JetBrains-style inline params, the inline shell command, and the line diff\n// for file-writing tools. Pure functions — the viewer renders their output.\n\nimport { computeLineDiff } from \"../code-diff\";\nimport { languageFromPath } from \"../code-highlight\";\nimport { stripTrailingSlashes } from \"../../lib/string\";\nimport { splitMcpTool, truncate } from \"./SessionViewer.model\";\n\n/** Strip the event's working directory from an absolute file path. */\nexport function relativizePath(path: string, cwd?: string): string {\n if (!cwd) return path;\n const base = stripTrailingSlashes(cwd);\n return path.startsWith(`${base}/`) ? path.slice(base.length + 1) : path;\n}\n\n/** The raw shell command of a shell-execution tool call, if present. Shell rows\n * render this inline as a bash code block instead of the generic label +\n * tool-input JSON. */\nexport function shellCommand(\n tool: string,\n input?: Record<string, unknown>,\n): string | undefined {\n if (tool !== \"Bash\") return undefined;\n const command = input?.[\"command\"];\n return typeof command === \"string\" && command ? command : undefined;\n}\n\nexport interface ToolParam {\n name: string;\n value: string;\n}\n\nexport interface SessionQuestionOption {\n value: string;\n label: string;\n description?: string;\n}\n\nexport interface SessionQuestion {\n id: string;\n text: string;\n context?: string;\n multiSelect?: boolean;\n isOther?: boolean;\n options: SessionQuestionOption[];\n}\n\n// Keys already rendered elsewhere in the row — the file-path heading, the\n// inline shell command, or the diff — so they don't repeat as inline params.\nconst CONSUMED_INPUT_KEYS: Record<string, readonly string[]> = {\n Bash: [\"command\"],\n Read: [\"file_path\", \"notebook_path\", \"path\"],\n Write: [\"file_path\", \"notebook_path\", \"path\", \"content\"],\n Edit: [\"file_path\", \"notebook_path\", \"path\", \"old_string\", \"new_string\"],\n MultiEdit: [\"file_path\", \"notebook_path\", \"path\", \"edits\"],\n NotebookEdit: [\"file_path\", \"notebook_path\", \"path\"],\n AskUserQuestion: [\"questions\", \"question\", \"prompt\", \"text\", \"header\", \"context\", \"description\", \"options\"],\n};\n\n/** Flatten a tool's input into JetBrains-style `name: value` inline params:\n * single-line values, cwd-relativized and truncated so the row never wraps. */\nexport function toolInputParams(\n tool: string,\n input?: Record<string, unknown>,\n cwd?: string,\n): ToolParam[] {\n const consumed = CONSUMED_INPUT_KEYS[tool] ?? [];\n return Object.entries(input ?? {})\n .filter(\n ([name, value]) =>\n !consumed.includes(name) &&\n value !== undefined &&\n value !== null &&\n value !== \"\",\n )\n .map(([name, value]) => ({ name, value: paramValue(value, cwd) }));\n}\n\nfunction paramValue(value: unknown, cwd?: string): string {\n const text =\n typeof value === \"string\"\n ? relativizePath(value, cwd)\n : JSON.stringify(value);\n return truncate(text.replace(/\\s+/g, \" \").trim(), 60);\n}\n\n/** One before/after edit, rendered as a language-aware diff. */\nexport interface DiffSegment {\n original: string;\n modified: string;\n}\n\nexport interface ToolDiff {\n added: number;\n removed: number;\n /** Edits as original→modified pairs (Write has one; MultiEdit has several). */\n segments: DiffSegment[];\n /** Highlighter hint from the file extension, when known. */\n language?: string;\n}\n\n// Added/removed line counts from a real LCS diff — context lines don't count,\n// so a no-op edit reports 0/0 (and yields no diff).\nfunction diffCounts(segments: DiffSegment[]): {\n added: number;\n removed: number;\n} {\n let added = 0;\n let removed = 0;\n for (const { original, modified } of segments) {\n for (const hunk of computeLineDiff(original, modified)) {\n for (const line of hunk.lines) {\n if (line.type === \"add\") added += 1;\n else if (line.type === \"remove\") removed += 1;\n }\n }\n }\n return { added, removed };\n}\n\n/** The content change of a file-writing tool call as before/after segments —\n * Write is one all-additions segment; Edit/MultiEdit pair old and new text. */\nexport function toolDiff(\n tool: string,\n input?: Record<string, unknown>,\n): ToolDiff | undefined {\n if (!input) return undefined;\n const str = (key: string): string =>\n typeof input[key] === \"string\" ? (input[key] as string) : \"\";\n\n const segments = toolDiffSegments(tool, input, str);\n if (!segments || segments.length === 0) return undefined;\n const counts = diffCounts(segments);\n if (counts.added === 0 && counts.removed === 0) return undefined;\n\n const language = languageFromPath(\n str(\"file_path\") || str(\"notebook_path\") || str(\"path\"),\n );\n return { ...counts, segments, ...(language ? { language } : {}) };\n}\n\nfunction toolDiffSegments(\n tool: string,\n input: Record<string, unknown>,\n str: (key: string) => string,\n): DiffSegment[] | undefined {\n if (tool === \"Write\") {\n const content = str(\"content\");\n return content ? [{ original: \"\", modified: content }] : undefined;\n }\n if (tool === \"Edit\" || tool === \"NotebookEdit\") {\n const original = str(\"old_string\");\n const modified = str(\"new_string\") || str(\"new_source\");\n return original || modified ? [{ original, modified }] : undefined;\n }\n if (tool === \"MultiEdit\") {\n const edits = input[\"edits\"];\n if (!Array.isArray(edits)) return undefined;\n return edits\n .filter(\n (edit): edit is Record<string, unknown> =>\n typeof edit === \"object\" && edit !== null,\n )\n .map((edit) => ({\n original:\n typeof edit[\"old_string\"] === \"string\"\n ? (edit[\"old_string\"] as string)\n : \"\",\n modified:\n typeof edit[\"new_string\"] === \"string\"\n ? (edit[\"new_string\"] as string)\n : \"\",\n }))\n .filter((segment) => segment.original !== \"\" || segment.modified !== \"\");\n }\n return undefined;\n}\n\n// summarizeToolInput condenses a tool's input into a one-line preview, ported\n// from captain's history.FormatToolUseSummary so the viewer reads like the CLI.\nexport function summarizeToolInput(\n tool: string,\n input?: Record<string, unknown>,\n cwd?: string,\n): string {\n if (!input) return \"\";\n const str = (key: string): string =>\n typeof input[key] === \"string\" ? (input[key] as string) : \"\";\n const first = (...keys: string[]): string => {\n for (const key of keys) {\n const value = str(key);\n if (value) return value;\n }\n return \"\";\n };\n\n const mcp = splitMcpTool(tool);\n if (mcp) {\n const arg = first(\"url\", \"sql\", \"query\", \"element\", \"method\");\n return arg ? truncate(arg, 80) : \"\";\n }\n\n switch (tool) {\n case \"Bash\":\n case \"browser_type\":\n return str(\"command\") || str(\"text\");\n case \"Read\":\n case \"Write\":\n case \"Edit\":\n case \"MultiEdit\":\n case \"NotebookEdit\":\n return relativizePath(first(\"file_path\", \"notebook_path\", \"path\"), cwd);\n case \"Grep\":\n return [str(\"pattern\"), str(\"path\")].filter(Boolean).join(\" \");\n case \"Glob\":\n return str(\"pattern\");\n case \"Task\":\n case \"Agent\":\n return first(\"description\", \"prompt\");\n case \"Skill\":\n return first(\"skill\", \"command\", \"name\");\n case \"TaskCreate\":\n return first(\"subject\", \"description\");\n case \"TaskUpdate\": {\n const id = first(\"taskId\", \"task_id\", \"id\");\n const status = str(\"status\");\n return status ? `${id} ${status}`.trim() : id;\n }\n case \"TaskGet\":\n case \"TaskOutput\":\n case \"TaskStop\":\n return first(\"task_id\", \"taskId\", \"id\");\n case \"ToolSearch\":\n case \"WebSearch\":\n return str(\"query\");\n case \"WebFetch\":\n case \"browser_navigate\":\n return str(\"url\");\n case \"AskUserQuestion\": {\n const questions = questionsFromToolInput(input);\n const rawQuestions = input[\"questions\"];\n if (questions.length > 1) return `${questions.length} questions`;\n if (questions[0]?.text) return truncate(questions[0].text, 80);\n if (Array.isArray(rawQuestions) && rawQuestions.length > 0) return `${rawQuestions.length} questions`;\n return \"\";\n }\n case \"ExitPlanMode\":\n return str(\"planFilePath\");\n default:\n return \"\";\n }\n}\n\nexport function questionsFromToolInput(input?: Record<string, unknown>): SessionQuestion[] {\n if (!input) return [];\n const rawQuestions = input.questions;\n if (Array.isArray(rawQuestions)) {\n return rawQuestions\n .map((question, index) => questionFromValue(question, index))\n .filter((question): question is SessionQuestion => question !== null);\n }\n\n const text = stringField(input, \"question\") || stringField(input, \"prompt\") || stringField(input, \"text\");\n if (!text) return [];\n return [{\n id: stringField(input, \"id\") || \"1\",\n text,\n ...optionalContext(input),\n multiSelect: booleanField(input, \"multiSelect\") || booleanField(input, \"multi_select\"),\n options: optionList(input.options),\n }];\n}\n\nfunction questionFromValue(value: unknown, index: number): SessionQuestion | null {\n if (typeof value === \"string\") {\n const text = value.trim();\n return text ? { id: String(index + 1), text, options: [] } : null;\n }\n if (!isRecord(value)) return null;\n const text =\n stringField(value, \"question\") ||\n stringField(value, \"text\") ||\n stringField(value, \"prompt\") ||\n stringField(value, \"label\");\n if (!text) return null;\n return {\n id: stringField(value, \"id\") || String(index + 1),\n text,\n ...optionalContext(value),\n multiSelect: booleanField(value, \"multiSelect\") || booleanField(value, \"multi_select\"),\n ...(booleanField(value, \"isOther\") || booleanField(value, \"is_other\") ? { isOther: true } : {}),\n options: optionList(value.options),\n };\n}\n\nfunction optionList(value: unknown): SessionQuestionOption[] {\n if (!Array.isArray(value)) return [];\n return value.flatMap((option, index) => {\n if (typeof option === \"string\") {\n const label = option.trim();\n return label ? [{ value: label, label }] : [];\n }\n if (!isRecord(option)) return [];\n const label =\n stringField(option, \"label\") ||\n stringField(option, \"value\") ||\n stringField(option, \"id\") ||\n stringField(option, \"description\");\n if (!label) return [];\n const value = stringField(option, \"value\") || stringField(option, \"id\") || label;\n const description = stringField(option, \"description\");\n return [{\n value: value || String(index + 1),\n label,\n ...(description && description !== label ? { description } : {}),\n }];\n });\n}\n\nfunction optionalContext(input: Record<string, unknown>): Pick<SessionQuestion, \"context\"> {\n const context = stringField(input, \"header\") || stringField(input, \"context\") || stringField(input, \"description\");\n return context ? { context } : {};\n}\n\nfunction stringField(input: Record<string, unknown>, key: string): string {\n const value = input[key];\n return typeof value === \"string\" ? value.trim() : \"\";\n}\n\nfunction booleanField(input: Record<string, unknown>, key: string): boolean {\n return input[key] === true;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return !!value && typeof value === \"object\" && !Array.isArray(value);\n}\n"],"names":["text","label","value"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SessionViewer.input.js","sources":["../../../src/data/ai/SessionViewer.input.ts"],"sourcesContent":["// Presentation helpers for a tool call's input: the one-line summary, the\n// JetBrains-style inline params, the inline shell command, and the line diff\n// for file-writing tools. Pure functions — the viewer renders their output.\n\nimport { computeLineDiff } from \"../code-diff\";\nimport { languageFromPath } from \"../code-highlight\";\nimport { stripTrailingSlashes } from \"../../lib/string\";\nimport { splitMcpTool, truncate } from \"./SessionViewer.model\";\nimport type { ApprovalQuestion } from \"./approval-request\";\n\n/** Strip the event's working directory from an absolute file path. */\nexport function relativizePath(path: string, cwd?: string): string {\n if (!cwd) return path;\n const base = stripTrailingSlashes(cwd);\n return path.startsWith(`${base}/`) ? path.slice(base.length + 1) : path;\n}\n\n/** The raw shell command of a shell-execution tool call, if present. Shell rows\n * render this inline as a bash code block instead of the generic label +\n * tool-input JSON. */\nexport function shellCommand(\n tool: string,\n input?: Record<string, unknown>,\n): string | undefined {\n if (tool !== \"Bash\") return undefined;\n const command = input?.[\"command\"];\n return typeof command === \"string\" && command ? command : undefined;\n}\n\nexport interface ToolParam {\n name: string;\n value: string;\n}\n\nexport interface SessionQuestionOption {\n value: string;\n label: string;\n description?: string;\n}\n\nexport interface SessionQuestion {\n id: string;\n text: string;\n context?: string;\n multiSelect?: boolean;\n isOther?: boolean;\n options: SessionQuestionOption[];\n}\n\n// Keys already rendered elsewhere in the row — the file-path heading, the\n// inline shell command, or the diff — so they don't repeat as inline params.\nconst CONSUMED_INPUT_KEYS: Record<string, readonly string[]> = {\n Bash: [\"command\"],\n Read: [\"file_path\", \"notebook_path\", \"path\"],\n Write: [\"file_path\", \"notebook_path\", \"path\", \"content\"],\n Edit: [\"file_path\", \"notebook_path\", \"path\", \"old_string\", \"new_string\"],\n MultiEdit: [\"file_path\", \"notebook_path\", \"path\", \"edits\"],\n NotebookEdit: [\"file_path\", \"notebook_path\", \"path\"],\n AskUserQuestion: [\"questions\", \"question\", \"prompt\", \"text\", \"header\", \"context\", \"description\", \"options\"],\n};\n\n/** Flatten a tool's input into JetBrains-style `name: value` inline params:\n * single-line values, cwd-relativized and truncated so the row never wraps. */\nexport function toolInputParams(\n tool: string,\n input?: Record<string, unknown>,\n cwd?: string,\n): ToolParam[] {\n const consumed = CONSUMED_INPUT_KEYS[tool] ?? [];\n return Object.entries(input ?? {})\n .filter(\n ([name, value]) =>\n !consumed.includes(name) &&\n value !== undefined &&\n value !== null &&\n value !== \"\",\n )\n .map(([name, value]) => ({ name, value: paramValue(value, cwd) }));\n}\n\nfunction paramValue(value: unknown, cwd?: string): string {\n const text =\n typeof value === \"string\"\n ? relativizePath(value, cwd)\n : JSON.stringify(value);\n return truncate(text.replace(/\\s+/g, \" \").trim(), 60);\n}\n\n/** One before/after edit, rendered as a language-aware diff. */\nexport interface DiffSegment {\n original: string;\n modified: string;\n}\n\nexport interface ToolDiff {\n added: number;\n removed: number;\n /** Edits as original→modified pairs (Write has one; MultiEdit has several). */\n segments: DiffSegment[];\n /** Highlighter hint from the file extension, when known. */\n language?: string;\n}\n\n// Added/removed line counts from a real LCS diff — context lines don't count,\n// so a no-op edit reports 0/0 (and yields no diff).\nfunction diffCounts(segments: DiffSegment[]): {\n added: number;\n removed: number;\n} {\n let added = 0;\n let removed = 0;\n for (const { original, modified } of segments) {\n for (const hunk of computeLineDiff(original, modified)) {\n for (const line of hunk.lines) {\n if (line.type === \"add\") added += 1;\n else if (line.type === \"remove\") removed += 1;\n }\n }\n }\n return { added, removed };\n}\n\n/** The content change of a file-writing tool call as before/after segments —\n * Write is one all-additions segment; Edit/MultiEdit pair old and new text. */\nexport function toolDiff(\n tool: string,\n input?: Record<string, unknown>,\n): ToolDiff | undefined {\n if (!input) return undefined;\n const str = (key: string): string =>\n typeof input[key] === \"string\" ? (input[key] as string) : \"\";\n\n const segments = toolDiffSegments(tool, input, str);\n if (!segments || segments.length === 0) return undefined;\n const counts = diffCounts(segments);\n if (counts.added === 0 && counts.removed === 0) return undefined;\n\n const language = languageFromPath(\n str(\"file_path\") || str(\"notebook_path\") || str(\"path\"),\n );\n return { ...counts, segments, ...(language ? { language } : {}) };\n}\n\nfunction toolDiffSegments(\n tool: string,\n input: Record<string, unknown>,\n str: (key: string) => string,\n): DiffSegment[] | undefined {\n if (tool === \"Write\") {\n const content = str(\"content\");\n return content ? [{ original: \"\", modified: content }] : undefined;\n }\n if (tool === \"Edit\" || tool === \"NotebookEdit\") {\n const original = str(\"old_string\");\n const modified = str(\"new_string\") || str(\"new_source\");\n return original || modified ? [{ original, modified }] : undefined;\n }\n if (tool === \"MultiEdit\") {\n const edits = input[\"edits\"];\n if (!Array.isArray(edits)) return undefined;\n return edits\n .filter(\n (edit): edit is Record<string, unknown> =>\n typeof edit === \"object\" && edit !== null,\n )\n .map((edit) => ({\n original:\n typeof edit[\"old_string\"] === \"string\"\n ? (edit[\"old_string\"] as string)\n : \"\",\n modified:\n typeof edit[\"new_string\"] === \"string\"\n ? (edit[\"new_string\"] as string)\n : \"\",\n }))\n .filter((segment) => segment.original !== \"\" || segment.modified !== \"\");\n }\n return undefined;\n}\n\n// summarizeToolInput condenses a tool's input into a one-line preview, ported\n// from captain's history.FormatToolUseSummary so the viewer reads like the CLI.\nexport function summarizeToolInput(\n tool: string,\n input?: Record<string, unknown>,\n cwd?: string,\n): string {\n if (!input) return \"\";\n const str = (key: string): string =>\n typeof input[key] === \"string\" ? (input[key] as string) : \"\";\n const first = (...keys: string[]): string => {\n for (const key of keys) {\n const value = str(key);\n if (value) return value;\n }\n return \"\";\n };\n\n const mcp = splitMcpTool(tool);\n if (mcp) {\n const arg = first(\"url\", \"sql\", \"query\", \"element\", \"method\");\n return arg ? truncate(arg, 80) : \"\";\n }\n\n switch (tool) {\n case \"Bash\":\n case \"browser_type\":\n return str(\"command\") || str(\"text\");\n case \"Read\":\n case \"Write\":\n case \"Edit\":\n case \"MultiEdit\":\n case \"NotebookEdit\":\n return relativizePath(first(\"file_path\", \"notebook_path\", \"path\"), cwd);\n case \"Grep\":\n return [str(\"pattern\"), str(\"path\")].filter(Boolean).join(\" \");\n case \"Glob\":\n return str(\"pattern\");\n case \"Task\":\n case \"Agent\":\n return first(\"description\", \"prompt\");\n case \"Skill\":\n return first(\"skill\", \"command\", \"name\");\n case \"TaskCreate\":\n return first(\"subject\", \"description\");\n case \"TaskUpdate\": {\n const id = first(\"taskId\", \"task_id\", \"id\");\n const status = str(\"status\");\n return status ? `${id} ${status}`.trim() : id;\n }\n case \"TaskGet\":\n case \"TaskOutput\":\n case \"TaskStop\":\n return first(\"task_id\", \"taskId\", \"id\");\n case \"ToolSearch\":\n case \"WebSearch\":\n return str(\"query\");\n case \"WebFetch\":\n case \"browser_navigate\":\n return str(\"url\");\n case \"AskUserQuestion\": {\n const questions = questionsFromToolInput(input);\n const rawQuestions = input[\"questions\"];\n if (questions.length > 1) return `${questions.length} questions`;\n if (questions[0]?.text) return truncate(questions[0].text, 80);\n if (Array.isArray(rawQuestions) && rawQuestions.length > 0) return `${rawQuestions.length} questions`;\n return \"\";\n }\n case \"ExitPlanMode\":\n return str(\"planFilePath\");\n default:\n return \"\";\n }\n}\n\n/** Maps a typed approval's questions (captain `TerminalQuestion`) to the\n * viewer's question shape. Answers are keyed by `id`, or by the question text\n * when the provider gives none, which is how captain reads them back. */\nexport function questionsFromApproval(questions: readonly ApprovalQuestion[]): SessionQuestion[] {\n return questions.map((question) => ({\n id: question.id || question.text,\n text: question.text,\n ...(question.context ? { context: question.context } : {}),\n ...(question.multiSelect ? { multiSelect: true } : {}),\n options: (question.options ?? []).map((option) => {\n const description = question.optionDescriptions?.[option];\n return { value: option, label: option, ...(description ? { description } : {}) };\n }),\n }));\n}\n\nexport function questionsFromToolInput(input?: Record<string, unknown>): SessionQuestion[] {\n if (!input) return [];\n const rawQuestions = input.questions;\n if (Array.isArray(rawQuestions)) {\n return rawQuestions\n .map((question, index) => questionFromValue(question, index))\n .filter((question): question is SessionQuestion => question !== null);\n }\n\n const text = stringField(input, \"question\") || stringField(input, \"prompt\") || stringField(input, \"text\");\n if (!text) return [];\n return [{\n id: stringField(input, \"id\") || \"1\",\n text,\n ...optionalContext(input),\n multiSelect: booleanField(input, \"multiSelect\") || booleanField(input, \"multi_select\"),\n options: optionList(input.options),\n }];\n}\n\nfunction questionFromValue(value: unknown, index: number): SessionQuestion | null {\n if (typeof value === \"string\") {\n const text = value.trim();\n return text ? { id: String(index + 1), text, options: [] } : null;\n }\n if (!isRecord(value)) return null;\n const text =\n stringField(value, \"question\") ||\n stringField(value, \"text\") ||\n stringField(value, \"prompt\") ||\n stringField(value, \"label\");\n if (!text) return null;\n return {\n id: stringField(value, \"id\") || String(index + 1),\n text,\n ...optionalContext(value),\n multiSelect: booleanField(value, \"multiSelect\") || booleanField(value, \"multi_select\"),\n ...(booleanField(value, \"isOther\") || booleanField(value, \"is_other\") ? { isOther: true } : {}),\n options: optionList(value.options),\n };\n}\n\nfunction optionList(value: unknown): SessionQuestionOption[] {\n if (!Array.isArray(value)) return [];\n return value.flatMap((option, index) => {\n if (typeof option === \"string\") {\n const label = option.trim();\n return label ? [{ value: label, label }] : [];\n }\n if (!isRecord(option)) return [];\n const label =\n stringField(option, \"label\") ||\n stringField(option, \"value\") ||\n stringField(option, \"id\") ||\n stringField(option, \"description\");\n if (!label) return [];\n const value = stringField(option, \"value\") || stringField(option, \"id\") || label;\n const description = stringField(option, \"description\");\n return [{\n value: value || String(index + 1),\n label,\n ...(description && description !== label ? { description } : {}),\n }];\n });\n}\n\nfunction optionalContext(input: Record<string, unknown>): Pick<SessionQuestion, \"context\"> {\n const context = stringField(input, \"header\") || stringField(input, \"context\") || stringField(input, \"description\");\n return context ? { context } : {};\n}\n\nfunction stringField(input: Record<string, unknown>, key: string): string {\n const value = input[key];\n return typeof value === \"string\" ? value.trim() : \"\";\n}\n\nfunction booleanField(input: Record<string, unknown>, key: string): boolean {\n return input[key] === true;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return !!value && typeof value === \"object\" && !Array.isArray(value);\n}\n"],"names":["text","label","value"],"mappings":"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"}
|
|
@@ -3,16 +3,18 @@ import { useMemo, useState } from "react";
|
|
|
3
3
|
import { createPortal } from "react-dom";
|
|
4
4
|
import { cn } from "../../lib/utils.js";
|
|
5
5
|
import { Icon } from "../Icon.js";
|
|
6
|
+
import { Button } from "../../components/button.js";
|
|
6
7
|
import { useDensityValue } from "../../hooks/use-density.js";
|
|
7
8
|
import { DensityValueProvider } from "../../hooks/density-provider.js";
|
|
8
9
|
import { normalizeSession, getSessionMetadata, summarizeSession } from "./SessionViewer.model.js";
|
|
9
10
|
import { collapseWaitRuns, isSessionEventGroup } from "./SessionViewer.grouping.js";
|
|
10
11
|
import { WaitGroupRow, SessionRow } from "./SessionViewer.rows.js";
|
|
11
12
|
import { SessionMetadataBadges } from "./SessionViewer.header.js";
|
|
12
|
-
import { collectSessionFilters, isEventVisible } from "./session-categories.js";
|
|
13
|
+
import { collectSessionFilters, isEncryptedReasoning, isEventVisible } from "./session-categories.js";
|
|
13
14
|
import { SessionViewerMenu } from "./SessionViewerMenu.js";
|
|
14
15
|
import { useSessionScroll } from "./use-session-scroll.js";
|
|
15
16
|
import { UiRobotAi } from "../../icons/components/UiRobotAi.js";
|
|
17
|
+
import { UiArrowDown } from "../../icons/components/UiArrowDown.js";
|
|
16
18
|
function toggleInSet(set, value) {
|
|
17
19
|
const next = new Set(set);
|
|
18
20
|
if (next.has(value)) next.delete(value);
|
|
@@ -35,13 +37,14 @@ function SessionViewer({
|
|
|
35
37
|
scrollable = false,
|
|
36
38
|
windowSize = 60,
|
|
37
39
|
batchSize = 40,
|
|
40
|
+
scrollResetKey,
|
|
38
41
|
showRowMetadata = false,
|
|
39
42
|
showRaw = false,
|
|
40
43
|
renderMessageBadge,
|
|
41
44
|
pendingTools = [],
|
|
42
45
|
onPendingToolDecision
|
|
43
46
|
}) {
|
|
44
|
-
var _a;
|
|
47
|
+
var _a, _b;
|
|
45
48
|
const allEvents = useMemo(
|
|
46
49
|
() => mergePendingTools(normalizeSession(session), pendingTools),
|
|
47
50
|
[session, pendingTools]
|
|
@@ -62,25 +65,29 @@ function SessionViewer({
|
|
|
62
65
|
);
|
|
63
66
|
const [showThinkingOverride, setShowThinkingOverride] = useState(void 0);
|
|
64
67
|
const effectiveShowThinking = showThinkingOverride ?? showThinking;
|
|
68
|
+
const [showEncryptedReasoning, setShowEncryptedReasoning] = useState(false);
|
|
65
69
|
const filters = useMemo(() => collectSessionFilters(allEvents), [allEvents]);
|
|
66
70
|
const hasThinking = useMemo(
|
|
67
71
|
() => allEvents.some((e) => e.kind === "thinking"),
|
|
68
72
|
[allEvents]
|
|
69
73
|
);
|
|
74
|
+
const hasEncryptedReasoning = useMemo(
|
|
75
|
+
() => allEvents.some(isEncryptedReasoning),
|
|
76
|
+
[allEvents]
|
|
77
|
+
);
|
|
70
78
|
const visibility = {
|
|
71
79
|
hiddenCategories,
|
|
72
80
|
hiddenTools,
|
|
73
81
|
hiddenSources,
|
|
74
82
|
showThinking: effectiveShowThinking
|
|
75
83
|
};
|
|
76
|
-
const items = displayItems.filter(
|
|
77
|
-
(item)
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
);
|
|
82
|
-
const
|
|
83
|
-
const { scrollRef, contentRef, startIndex } = useSessionScroll({
|
|
84
|
+
const items = displayItems.filter((item) => {
|
|
85
|
+
const event = isSessionEventGroup(item) ? item.representative : item;
|
|
86
|
+
return (showEncryptedReasoning || !isEncryptedReasoning(event)) && isEventVisible(event, visibility);
|
|
87
|
+
});
|
|
88
|
+
const firstUserEventId = (_a = allEvents.find((event) => event.kind === "user")) == null ? void 0 : _a.id;
|
|
89
|
+
const resetKey = scrollResetKey ?? ((_b = allEvents[0]) == null ? void 0 : _b.id) ?? "";
|
|
90
|
+
const { scrollRef, contentRef, startIndex, following, resumeFollowing } = useSessionScroll({
|
|
84
91
|
total: items.length,
|
|
85
92
|
enabled: scrollable,
|
|
86
93
|
windowSize,
|
|
@@ -122,7 +129,10 @@ function SessionViewer({
|
|
|
122
129
|
onToggleSource: (source) => setHiddenSources((set) => toggleInSet(set, source)),
|
|
123
130
|
showThinking: effectiveShowThinking,
|
|
124
131
|
onToggleThinking: () => setShowThinkingOverride(!effectiveShowThinking),
|
|
125
|
-
hasThinking
|
|
132
|
+
hasThinking,
|
|
133
|
+
hasEncryptedReasoning,
|
|
134
|
+
showEncryptedReasoning,
|
|
135
|
+
onToggleEncryptedReasoning: () => setShowEncryptedReasoning((shown) => !shown)
|
|
126
136
|
}
|
|
127
137
|
) : null;
|
|
128
138
|
const inlineMenu = menu && !menuContainer;
|
|
@@ -147,6 +157,7 @@ function SessionViewer({
|
|
|
147
157
|
SessionRow,
|
|
148
158
|
{
|
|
149
159
|
event: item,
|
|
160
|
+
initialPrompt: item.id === firstUserEventId,
|
|
150
161
|
last,
|
|
151
162
|
defaultExpanded,
|
|
152
163
|
showRowMetadata,
|
|
@@ -214,15 +225,31 @@ function SessionViewer({
|
|
|
214
225
|
]
|
|
215
226
|
}
|
|
216
227
|
),
|
|
217
|
-
scrollable ? /* @__PURE__ */
|
|
218
|
-
"div",
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
228
|
+
scrollable ? /* @__PURE__ */ jsxs("div", { className: "relative min-h-0 flex-1", children: [
|
|
229
|
+
/* @__PURE__ */ jsx("div", { ref: scrollRef, className: "h-full overflow-y-auto", children: /* @__PURE__ */ jsx(
|
|
230
|
+
"div",
|
|
231
|
+
{
|
|
232
|
+
ref: contentRef,
|
|
233
|
+
"data-session-viewer-content": true,
|
|
234
|
+
className: "p-density-3 @min-[48rem]/session-viewer:p-density-4",
|
|
235
|
+
children: list
|
|
236
|
+
}
|
|
237
|
+
) }),
|
|
238
|
+
!following && /* @__PURE__ */ jsxs(
|
|
239
|
+
Button,
|
|
240
|
+
{
|
|
241
|
+
type: "button",
|
|
242
|
+
variant: "secondary",
|
|
243
|
+
size: "sm",
|
|
244
|
+
onClick: resumeFollowing,
|
|
245
|
+
className: "absolute bottom-density-3 left-1/2 -translate-x-1/2 shadow-md",
|
|
246
|
+
children: [
|
|
247
|
+
/* @__PURE__ */ jsx(Icon, { icon: UiArrowDown, className: "size-4" }),
|
|
248
|
+
"Scroll to bottom"
|
|
249
|
+
]
|
|
250
|
+
}
|
|
251
|
+
)
|
|
252
|
+
] }) : list
|
|
226
253
|
] })
|
|
227
254
|
}
|
|
228
255
|
);
|
|
@@ -240,7 +267,8 @@ function mergePendingTools(events, pendingTools) {
|
|
|
240
267
|
toolInput: pending.input ?? match.toolInput,
|
|
241
268
|
toolCallId: pending.toolCallId ?? match.toolCallId,
|
|
242
269
|
approvalId: pending.approvalId ?? match.approvalId,
|
|
243
|
-
sessionId: pending.sessionId ?? match.sessionId
|
|
270
|
+
sessionId: pending.sessionId ?? match.sessionId,
|
|
271
|
+
...approvalFields(pending)
|
|
244
272
|
});
|
|
245
273
|
} else {
|
|
246
274
|
merged.push({
|
|
@@ -251,12 +279,21 @@ function mergePendingTools(events, pendingTools) {
|
|
|
251
279
|
...pending.toolCallId ? { toolCallId: pending.toolCallId } : {},
|
|
252
280
|
...pending.approvalId ? { approvalId: pending.approvalId } : {},
|
|
253
281
|
...pending.sessionId ? { sessionId: pending.sessionId } : {},
|
|
282
|
+
...approvalFields(pending),
|
|
254
283
|
pending: true
|
|
255
284
|
});
|
|
256
285
|
}
|
|
257
286
|
}
|
|
258
287
|
return merged;
|
|
259
288
|
}
|
|
289
|
+
function approvalFields(pending) {
|
|
290
|
+
var _a;
|
|
291
|
+
const kind = pending.kind ?? ((_a = pending.request) == null ? void 0 : _a.kind);
|
|
292
|
+
return {
|
|
293
|
+
...kind ? { approvalKind: kind } : {},
|
|
294
|
+
...pending.request ? { approvalRequest: pending.request } : {}
|
|
295
|
+
};
|
|
296
|
+
}
|
|
260
297
|
export {
|
|
261
298
|
SessionViewer
|
|
262
299
|
};
|
|
@@ -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 { useDensityValue, type Density } from \"../../hooks/use-density\";\nimport { DensityValueProvider } from \"../../hooks/density-provider\";\nimport { 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 isEventVisible,\n type SessionCategory,\n} from \"./session-categories\";\nimport {\n SessionViewerMenu,\n type SessionThemeOverride,\n} from \"./SessionViewerMenu\";\nimport { useSessionScroll } from \"./use-session-scroll\";\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}\n\nexport interface SessionToolDecision {\n event: SessionEvent;\n allow: boolean;\n message?: string;\n answers?: Record<string, string | 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 /** 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 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\n const filters = useMemo(() => collectSessionFilters(allEvents), [allEvents]);\n const hasThinking = useMemo(\n () => allEvents.some((e) => e.kind === \"thinking\"),\n [allEvents],\n );\n\n const visibility = {\n hiddenCategories,\n hiddenTools,\n hiddenSources,\n showThinking: effectiveShowThinking,\n };\n const items = displayItems.filter((item) =>\n isEventVisible(\n isSessionEventGroup(item) ? item.representative : item,\n visibility,\n ),\n );\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 = `${allEvents.length}:${allEvents[0]?.id ?? \"\"}`;\n const { scrollRef, contentRef, startIndex } = 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 />\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 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 ref={scrollRef} className=\"min-h-0 flex-1 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 ) : (\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 });\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 pending: true,\n });\n }\n }\n return merged;\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\";\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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"}
|