@deepseek-harness-tui/dsh-tui 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +74 -21
- package/bin/dsh-tui.js +115 -25
- package/cordis.patch.yml +69 -17
- package/cordis.yml +50 -12
- package/lib/types/activityPrefs.d.ts +1 -1
- package/lib/types/activityPrefs.js +3 -3
- package/lib/types/cc/figures.d.ts +27 -20
- package/lib/types/cc/figures.d.ts.map +1 -1
- package/lib/types/cc/figures.js +43 -34
- package/lib/types/cc/format.d.ts +18 -9
- package/lib/types/cc/format.d.ts.map +1 -1
- package/lib/types/cc/format.js +26 -18
- package/lib/types/cc/markdown.d.ts +31 -16
- package/lib/types/cc/markdown.d.ts.map +1 -1
- package/lib/types/cc/markdown.js +283 -260
- package/lib/types/cc/terminal.d.ts +10 -7
- package/lib/types/cc/terminal.d.ts.map +1 -1
- package/lib/types/cc/terminal.js +62 -50
- package/lib/types/command-trees.d.ts +3 -0
- package/lib/types/command-trees.d.ts.map +1 -0
- package/lib/types/command-trees.js +4 -0
- package/lib/types/commands.d.ts +37 -1
- package/lib/types/commands.d.ts.map +1 -1
- package/lib/types/commands.js +68 -3
- package/lib/types/components/ActivityLine.d.ts +1 -1
- package/lib/types/components/ActivityLine.d.ts.map +1 -1
- package/lib/types/components/ActivityPicker.d.ts.map +1 -1
- package/lib/types/components/ActivityPicker.js +3 -4
- package/lib/types/components/BtwPanel.d.ts +16 -0
- package/lib/types/components/BtwPanel.d.ts.map +1 -0
- package/lib/types/components/BtwPanel.js +47 -0
- package/lib/types/components/CommandSuggestions.d.ts +4 -2
- package/lib/types/components/CommandSuggestions.d.ts.map +1 -1
- package/lib/types/components/CommandSuggestions.js +2 -2
- package/lib/types/components/EffortSlider.d.ts +15 -0
- package/lib/types/components/EffortSlider.d.ts.map +1 -0
- package/lib/types/components/EffortSlider.js +17 -0
- package/lib/types/components/GoalTodoPanel.d.ts +1 -1
- package/lib/types/components/GoalTodoPanel.d.ts.map +1 -1
- package/lib/types/components/HelpMenu.d.ts +5 -2
- package/lib/types/components/HelpMenu.d.ts.map +1 -1
- package/lib/types/components/HelpMenu.js +8 -3
- package/lib/types/components/HistorySearchDialog.d.ts +1 -1
- package/lib/types/components/HistorySearchDialog.d.ts.map +1 -1
- package/lib/types/components/HistorySearchDialog.js +21 -10
- package/lib/types/components/InterruptedByUser.d.ts +2 -2
- package/lib/types/components/InterruptedByUser.d.ts.map +1 -1
- package/lib/types/components/InterruptedByUser.js +4 -3
- package/lib/types/components/LoadedContextPanel.d.ts +1 -1
- package/lib/types/components/LoadedContextPanel.d.ts.map +1 -1
- package/lib/types/components/LogoV2.d.ts.map +1 -1
- package/lib/types/components/LogoV2.js +2 -1
- package/lib/types/components/Markdown.d.ts +11 -11
- package/lib/types/components/Markdown.d.ts.map +1 -1
- package/lib/types/components/Markdown.js +63 -57
- package/lib/types/components/MarkdownTable.d.ts +1 -1
- package/lib/types/components/MarkdownTable.js +2 -2
- package/lib/types/components/MessageList.d.ts +10 -2
- package/lib/types/components/MessageList.d.ts.map +1 -1
- package/lib/types/components/MessageList.js +17 -10
- package/lib/types/components/ModelPicker.d.ts +4 -1
- package/lib/types/components/ModelPicker.d.ts.map +1 -1
- package/lib/types/components/ModelPicker.js +16 -4
- package/lib/types/components/OverlayAbove.d.ts +20 -0
- package/lib/types/components/OverlayAbove.d.ts.map +1 -0
- package/lib/types/components/OverlayAbove.js +18 -0
- package/lib/types/components/PresetPicker.d.ts +1 -1
- package/lib/types/components/PresetPicker.d.ts.map +1 -1
- package/lib/types/components/PresetPicker.js +2 -3
- package/lib/types/components/PromptInput.d.ts +5 -4
- package/lib/types/components/PromptInput.d.ts.map +1 -1
- package/lib/types/components/PromptInput.js +186 -39
- package/lib/types/components/ResumePicker.d.ts +15 -4
- package/lib/types/components/ResumePicker.d.ts.map +1 -1
- package/lib/types/components/ResumePicker.js +25 -9
- package/lib/types/components/RewindPicker.d.ts +1 -1
- package/lib/types/components/RewindPicker.d.ts.map +1 -1
- package/lib/types/components/RewindPicker.js +14 -5
- package/lib/types/components/SearchBox.d.ts +1 -1
- package/lib/types/components/SearchBox.js +1 -1
- package/lib/types/components/Spinner/GlimmerMessage.d.ts +1 -2
- package/lib/types/components/Spinner/GlimmerMessage.d.ts.map +1 -1
- package/lib/types/components/Spinner/GlimmerMessage.js +1 -2
- package/lib/types/components/Spinner/SpinnerAnimationRow.d.ts +1 -1
- package/lib/types/components/Spinner/SpinnerAnimationRow.js +2 -2
- package/lib/types/components/Spinner/SpinnerGlyph.d.ts +1 -1
- package/lib/types/components/Spinner/SpinnerGlyph.js +1 -1
- package/lib/types/components/Spinner/spinnerUtils.d.ts +13 -18
- package/lib/types/components/Spinner/spinnerUtils.d.ts.map +1 -1
- package/lib/types/components/Spinner/spinnerUtils.js +67 -71
- package/lib/types/components/Spinner/useStalledAnimation.d.ts +1 -2
- package/lib/types/components/Spinner/useStalledAnimation.d.ts.map +1 -1
- package/lib/types/components/Spinner/useStalledAnimation.js +1 -2
- package/lib/types/components/StreamingMarkdown.d.ts +1 -1
- package/lib/types/components/StreamingMarkdown.js +1 -1
- package/lib/types/components/ThemePicker.d.ts +13 -9
- package/lib/types/components/ThemePicker.d.ts.map +1 -1
- package/lib/types/components/ThemePicker.js +21 -15
- package/lib/types/components/ThinkingToggle.d.ts +1 -1
- package/lib/types/components/ThinkingToggle.d.ts.map +1 -1
- package/lib/types/components/ThinkingToggle.js +8 -8
- package/lib/types/components/ToolUseLoader.d.ts +1 -1
- package/lib/types/components/ToolUseLoader.js +1 -1
- package/lib/types/components/WorkingSpinner.d.ts +2 -2
- package/lib/types/components/WorkingSpinner.js +2 -2
- package/lib/types/components/WorkspaceFlowPicker.d.ts +15 -0
- package/lib/types/components/WorkspaceFlowPicker.d.ts.map +1 -0
- package/lib/types/components/WorkspaceFlowPicker.js +19 -0
- package/lib/types/components/WorkspacePicker.d.ts +9 -0
- package/lib/types/components/WorkspacePicker.d.ts.map +1 -0
- package/lib/types/components/WorkspacePicker.js +13 -0
- package/lib/types/components/approvals/ApprovalPanel.d.ts +1 -1
- package/lib/types/components/approvals/ApprovalPanel.d.ts.map +1 -1
- package/lib/types/components/approvals/ApprovalPanel.js +2 -1
- package/lib/types/components/design-system/Byline.d.ts +1 -1
- package/lib/types/components/design-system/Byline.js +1 -1
- package/lib/types/components/design-system/Divider.d.ts +1 -1
- package/lib/types/components/design-system/Divider.js +1 -1
- package/lib/types/components/design-system/HintLine.d.ts +12 -0
- package/lib/types/components/design-system/HintLine.d.ts.map +1 -0
- package/lib/types/components/design-system/HintLine.js +15 -0
- package/lib/types/components/design-system/KeyboardShortcutHint.d.ts +1 -1
- package/lib/types/components/design-system/KeyboardShortcutHint.js +1 -1
- package/lib/types/components/design-system/ListItem.d.ts +2 -2
- package/lib/types/components/design-system/ListItem.d.ts.map +1 -1
- package/lib/types/components/design-system/ListItem.js +35 -3
- package/lib/types/components/design-system/LoadingState.d.ts +1 -2
- package/lib/types/components/design-system/LoadingState.d.ts.map +1 -1
- package/lib/types/components/design-system/LoadingState.js +1 -2
- package/lib/types/components/design-system/Pane.d.ts +2 -2
- package/lib/types/components/design-system/Pane.js +2 -2
- package/lib/types/components/design-system/ProgressBar.d.ts +1 -2
- package/lib/types/components/design-system/ProgressBar.d.ts.map +1 -1
- package/lib/types/components/design-system/ProgressBar.js +1 -2
- package/lib/types/components/design-system/StatusIcon.d.ts +2 -2
- package/lib/types/components/design-system/StatusIcon.js +2 -2
- package/lib/types/components/design-system/ThemeProvider.d.ts +1 -1
- package/lib/types/components/design-system/ThemeProvider.d.ts.map +1 -1
- package/lib/types/components/design-system/ThemeProvider.js +87 -26
- package/lib/types/components/design-system/ThemedBox.d.ts +1 -1
- package/lib/types/components/design-system/ThemedBox.js +1 -1
- package/lib/types/components/design-system/ThemedText.d.ts +2 -2
- package/lib/types/components/design-system/ThemedText.js +2 -2
- package/lib/types/components/listWindow.d.ts +26 -0
- package/lib/types/components/listWindow.d.ts.map +1 -0
- package/lib/types/components/listWindow.js +47 -0
- package/lib/types/components/messages/AssistantTextMessage.d.ts +1 -2
- package/lib/types/components/messages/AssistantTextMessage.d.ts.map +1 -1
- package/lib/types/components/messages/AssistantTextMessage.js +1 -2
- package/lib/types/components/messages/AssistantThinkingMessage.d.ts +2 -2
- package/lib/types/components/messages/AssistantThinkingMessage.d.ts.map +1 -1
- package/lib/types/components/messages/AssistantThinkingMessage.js +6 -6
- package/lib/types/components/messages/AssistantToolUseMessage.d.ts +12 -4
- package/lib/types/components/messages/AssistantToolUseMessage.d.ts.map +1 -1
- package/lib/types/components/messages/AssistantToolUseMessage.js +9 -5
- package/lib/types/components/messages/MessageMetadata.d.ts +1 -1
- package/lib/types/components/messages/MessageMetadata.js +1 -1
- package/lib/types/components/messages/UserPromptMessage.d.ts +1 -1
- package/lib/types/components/messages/UserPromptMessage.js +1 -1
- package/lib/types/components/questions/AskUserQuestionPanel.d.ts +5 -1
- package/lib/types/components/questions/AskUserQuestionPanel.d.ts.map +1 -1
- package/lib/types/components/questions/AskUserQuestionPanel.js +11 -9
- package/lib/types/components/questions/PlanReviewPanel.d.ts +1 -1
- package/lib/types/components/questions/PlanReviewPanel.d.ts.map +1 -1
- package/lib/types/components/questions/PlanReviewPanel.js +3 -2
- package/lib/types/components/trajectory/HotspotView.d.ts +14 -0
- package/lib/types/components/trajectory/HotspotView.d.ts.map +1 -0
- package/lib/types/components/trajectory/HotspotView.js +83 -0
- package/lib/types/components/trajectory/Inspector.d.ts +31 -0
- package/lib/types/components/trajectory/Inspector.d.ts.map +1 -0
- package/lib/types/components/trajectory/Inspector.js +67 -0
- package/lib/types/components/trajectory/Ledger.d.ts +20 -0
- package/lib/types/components/trajectory/Ledger.d.ts.map +1 -0
- package/lib/types/components/trajectory/Ledger.js +112 -0
- package/lib/types/components/trajectory/MiniWake.d.ts +24 -0
- package/lib/types/components/trajectory/MiniWake.d.ts.map +1 -0
- package/lib/types/components/trajectory/MiniWake.js +99 -0
- package/lib/types/components/trajectory/WaveBand.d.ts +33 -0
- package/lib/types/components/trajectory/WaveBand.d.ts.map +1 -0
- package/lib/types/components/trajectory/WaveBand.js +145 -0
- package/lib/types/customTheme.d.ts +6 -6
- package/lib/types/customTheme.d.ts.map +1 -1
- package/lib/types/customTheme.js +15 -12
- package/lib/types/dsh-adapter/approvals.d.ts.map +1 -0
- package/lib/types/{channel.d.ts → dsh-adapter/channel.d.ts} +184 -43
- package/lib/types/dsh-adapter/channel.d.ts.map +1 -0
- package/lib/types/{channel.js → dsh-adapter/channel.js} +972 -201
- package/lib/types/dsh-adapter/childStderr.d.ts.map +1 -0
- package/lib/types/{childStderr.js → dsh-adapter/childStderr.js} +1 -1
- package/lib/types/dsh-adapter/command-trees.d.ts +27 -0
- package/lib/types/dsh-adapter/command-trees.d.ts.map +1 -0
- package/lib/types/dsh-adapter/command-trees.js +42 -0
- package/lib/types/dsh-adapter/compat/index.d.ts +22 -0
- package/lib/types/dsh-adapter/compat/index.d.ts.map +1 -0
- package/lib/types/{compat → dsh-adapter/compat}/index.js +7 -4
- package/lib/types/dsh-adapter/compat/sessionLog.d.ts +86 -0
- package/lib/types/dsh-adapter/compat/sessionLog.d.ts.map +1 -0
- package/lib/types/dsh-adapter/compat/sessionLog.js +347 -0
- package/lib/types/dsh-adapter/contract.d.ts +20 -0
- package/lib/types/dsh-adapter/contract.d.ts.map +1 -0
- package/lib/types/dsh-adapter/contract.js +109 -0
- package/lib/types/dsh-adapter/index.d.ts +80 -0
- package/lib/types/dsh-adapter/index.d.ts.map +1 -0
- package/lib/types/dsh-adapter/index.js +45 -0
- package/lib/types/dsh-adapter/invariant.d.ts.map +1 -0
- package/lib/types/dsh-adapter/packaged-skills.d.ts.map +1 -0
- package/lib/types/{plugin.d.ts → dsh-adapter/plugin.d.ts} +17 -0
- package/lib/types/dsh-adapter/plugin.d.ts.map +1 -0
- package/lib/types/{plugin.js → dsh-adapter/plugin.js} +280 -80
- package/lib/types/dsh-adapter/presets.d.ts.map +1 -0
- package/lib/types/dsh-adapter/providerWizard.d.ts +91 -0
- package/lib/types/dsh-adapter/providerWizard.d.ts.map +1 -0
- package/lib/types/dsh-adapter/providerWizard.js +332 -0
- package/lib/types/{questions.d.ts → dsh-adapter/questions.d.ts} +7 -2
- package/lib/types/dsh-adapter/questions.d.ts.map +1 -0
- package/lib/types/{questions.js → dsh-adapter/questions.js} +15 -7
- package/lib/types/dsh-adapter/sideQuestion.d.ts +38 -0
- package/lib/types/dsh-adapter/sideQuestion.d.ts.map +1 -0
- package/lib/types/dsh-adapter/sideQuestion.js +69 -0
- package/lib/types/dsh-adapter/trajectory/aggregate.d.ts +46 -0
- package/lib/types/dsh-adapter/trajectory/aggregate.d.ts.map +1 -0
- package/lib/types/dsh-adapter/trajectory/aggregate.js +207 -0
- package/lib/types/dsh-adapter/trajectory/guards.d.ts +177 -0
- package/lib/types/dsh-adapter/trajectory/guards.d.ts.map +1 -0
- package/lib/types/dsh-adapter/trajectory/guards.js +235 -0
- package/lib/types/dsh-adapter/trajectory/index.d.ts +16 -0
- package/lib/types/dsh-adapter/trajectory/index.d.ts.map +1 -0
- package/lib/types/dsh-adapter/trajectory/index.js +15 -0
- package/lib/types/dsh-adapter/trajectory/inspect.d.ts +40 -0
- package/lib/types/dsh-adapter/trajectory/inspect.d.ts.map +1 -0
- package/lib/types/dsh-adapter/trajectory/inspect.js +160 -0
- package/lib/types/dsh-adapter/trajectory/projection.d.ts +128 -0
- package/lib/types/dsh-adapter/trajectory/projection.d.ts.map +1 -0
- package/lib/types/dsh-adapter/trajectory/projection.js +653 -0
- package/lib/types/dsh-adapter/trajectory/types.d.ts +232 -0
- package/lib/types/dsh-adapter/trajectory/types.d.ts.map +1 -0
- package/lib/types/dsh-adapter/trajectory/types.js +70 -0
- package/lib/types/dsh-adapter/trajectory/wave.d.ts +45 -0
- package/lib/types/dsh-adapter/trajectory/wave.d.ts.map +1 -0
- package/lib/types/dsh-adapter/trajectory/wave.js +210 -0
- package/lib/types/dsh-adapter/types.d.ts +23 -0
- package/lib/types/dsh-adapter/types.d.ts.map +1 -0
- package/lib/types/dsh-adapter/types.js +1 -0
- package/lib/types/dsh-adapter/workspace.d.ts +22 -0
- package/lib/types/dsh-adapter/workspace.d.ts.map +1 -0
- package/lib/types/dsh-adapter/workspace.js +16 -0
- package/lib/types/dsh-adapter/workspaces.d.ts +118 -0
- package/lib/types/dsh-adapter/workspaces.d.ts.map +1 -0
- package/lib/types/dsh-adapter/workspaces.js +290 -0
- package/lib/types/effortPrefs.d.ts +1 -1
- package/lib/types/effortPrefs.js +3 -3
- package/lib/types/history.js +2 -2
- package/lib/types/hooks/useBlink.d.ts +1 -1
- package/lib/types/hooks/useBlink.js +1 -1
- package/lib/types/i18n.d.ts +977 -36
- package/lib/types/i18n.d.ts.map +1 -1
- package/lib/types/i18n.js +307 -30
- package/lib/types/index.d.ts +1 -69
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/index.js +3 -31
- package/lib/types/ink/components/App.d.ts.map +1 -1
- package/lib/types/ink/components/App.js +33 -19
- package/lib/types/ink/dom.d.ts +15 -0
- package/lib/types/ink/dom.d.ts.map +1 -1
- package/lib/types/ink/dom.js +32 -0
- package/lib/types/ink/hooks/use-input.d.ts.map +1 -1
- package/lib/types/ink/hooks/use-input.js +8 -0
- package/lib/types/ink/hooks/use-terminal-size.d.ts +1 -1
- package/lib/types/ink/hooks/use-terminal-size.js +1 -1
- package/lib/types/ink/ink.d.ts.map +1 -1
- package/lib/types/ink/ink.js +109 -28
- package/lib/types/ink/input-suppression.d.ts +20 -0
- package/lib/types/ink/input-suppression.d.ts.map +1 -0
- package/lib/types/ink/input-suppression.js +26 -0
- package/lib/types/ink/log-update.js +21 -6
- package/lib/types/ink/parse-keypress.d.ts +31 -0
- package/lib/types/ink/parse-keypress.d.ts.map +1 -1
- package/lib/types/ink/parse-keypress.js +442 -8
- package/lib/types/ink/terminal-querier.d.ts +5 -1
- package/lib/types/ink/terminal-querier.d.ts.map +1 -1
- package/lib/types/ink/terminal-querier.js +27 -3
- package/lib/types/ink/terminal.d.ts +18 -0
- package/lib/types/ink/terminal.d.ts.map +1 -1
- package/lib/types/ink/terminal.js +32 -4
- package/lib/types/ink/termio/csi.d.ts +10 -0
- package/lib/types/ink/termio/csi.d.ts.map +1 -1
- package/lib/types/ink/termio/csi.js +20 -0
- package/lib/types/ink/termio/tokenize.js +10 -0
- package/lib/types/modelPrefs.d.ts +1 -1
- package/lib/types/modelPrefs.js +3 -3
- package/lib/types/presetPrefs.d.ts +1 -1
- package/lib/types/presetPrefs.js +3 -3
- package/lib/types/screens/Chat.d.ts +20 -4
- package/lib/types/screens/Chat.d.ts.map +1 -1
- package/lib/types/screens/Chat.js +655 -55
- package/lib/types/screens/StatusLine.d.ts +17 -2
- package/lib/types/screens/StatusLine.d.ts.map +1 -1
- package/lib/types/screens/StatusLine.js +12 -4
- package/lib/types/screens/TrajectoryScene.d.ts +16 -0
- package/lib/types/screens/TrajectoryScene.d.ts.map +1 -0
- package/lib/types/screens/TrajectoryScene.js +305 -0
- package/lib/types/sessionHistory.d.ts +9 -1
- package/lib/types/sessionHistory.d.ts.map +1 -1
- package/lib/types/sessionHistory.js +56 -16
- package/lib/types/sessionModes.d.ts +29 -0
- package/lib/types/sessionModes.d.ts.map +1 -0
- package/lib/types/sessionModes.js +45 -0
- package/lib/types/theme.d.ts +27 -3
- package/lib/types/theme.d.ts.map +1 -1
- package/lib/types/theme.js +48 -4
- package/lib/types/themePrefs.d.ts +3 -3
- package/lib/types/themePrefs.js +5 -5
- package/lib/types/trajectory/format.d.ts +100 -0
- package/lib/types/trajectory/format.d.ts.map +1 -0
- package/lib/types/trajectory/format.js +213 -0
- package/lib/types/trajectory/motion.d.ts +99 -0
- package/lib/types/trajectory/motion.d.ts.map +1 -0
- package/lib/types/trajectory/motion.js +143 -0
- package/lib/types/trajectory/query.d.ts +83 -0
- package/lib/types/trajectory/query.d.ts.map +1 -0
- package/lib/types/trajectory/query.js +187 -0
- package/lib/types/trajectoryPrefs.d.ts +36 -0
- package/lib/types/trajectoryPrefs.d.ts.map +1 -0
- package/lib/types/trajectoryPrefs.js +65 -0
- package/lib/types/update.d.ts +3 -3
- package/lib/types/update.d.ts.map +1 -1
- package/lib/types/update.js +18 -7
- package/lib/types/utils/clipboard.d.ts +101 -29
- package/lib/types/utils/clipboard.d.ts.map +1 -1
- package/lib/types/utils/clipboard.js +533 -55
- package/lib/types/utils/debug.d.ts +1 -1
- package/lib/types/utils/debug.js +2 -2
- package/lib/types/utils/execFileNoThrow.d.ts.map +1 -1
- package/lib/types/utils/execFileNoThrow.js +16 -6
- package/lib/types/utils/externalEditor.d.ts +115 -0
- package/lib/types/utils/externalEditor.d.ts.map +1 -0
- package/lib/types/utils/externalEditor.js +270 -0
- package/lib/types/utils/fullscreen.d.ts +2 -2
- package/lib/types/utils/fullscreen.js +3 -3
- package/lib/types/utils/loaded-context.d.ts +1 -1
- package/lib/types/utils/loaded-context.d.ts.map +1 -1
- package/lib/types/utils/modifiers.d.ts +24 -0
- package/lib/types/utils/modifiers.d.ts.map +1 -1
- package/lib/types/utils/modifiers.js +27 -0
- package/lib/types/utils/paths.d.ts +45 -0
- package/lib/types/utils/paths.d.ts.map +1 -0
- package/lib/types/utils/paths.js +69 -0
- package/lib/types/utils/shellQuote.d.ts +14 -0
- package/lib/types/utils/shellQuote.d.ts.map +1 -0
- package/lib/types/utils/shellQuote.js +39 -0
- package/lib/types/utils/workspaceRoot.d.ts +21 -0
- package/lib/types/utils/workspaceRoot.d.ts.map +1 -0
- package/lib/types/utils/workspaceRoot.js +47 -0
- package/lib/types/workspaces.d.ts +3 -0
- package/lib/types/workspaces.d.ts.map +1 -0
- package/lib/types/workspaces.js +4 -0
- package/package.json +26 -8
- package/lib/types/approvals.d.ts.map +0 -1
- package/lib/types/channel.d.ts.map +0 -1
- package/lib/types/childStderr.d.ts.map +0 -1
- package/lib/types/compat/index.d.ts +0 -20
- package/lib/types/compat/index.d.ts.map +0 -1
- package/lib/types/compat/sessionLog.d.ts +0 -40
- package/lib/types/compat/sessionLog.d.ts.map +0 -1
- package/lib/types/compat/sessionLog.js +0 -226
- package/lib/types/invariant.d.ts.map +0 -1
- package/lib/types/packaged-skills.d.ts.map +0 -1
- package/lib/types/plugin.d.ts.map +0 -1
- package/lib/types/presets.d.ts.map +0 -1
- package/lib/types/questions.d.ts.map +0 -1
- /package/lib/types/{approvals.d.ts → dsh-adapter/approvals.d.ts} +0 -0
- /package/lib/types/{approvals.js → dsh-adapter/approvals.js} +0 -0
- /package/lib/types/{childStderr.d.ts → dsh-adapter/childStderr.d.ts} +0 -0
- /package/lib/types/{invariant.d.ts → dsh-adapter/invariant.d.ts} +0 -0
- /package/lib/types/{invariant.js → dsh-adapter/invariant.js} +0 -0
- /package/lib/types/{packaged-skills.d.ts → dsh-adapter/packaged-skills.d.ts} +0 -0
- /package/lib/types/{packaged-skills.js → dsh-adapter/packaged-skills.js} +0 -0
- /package/lib/types/{presets.d.ts → dsh-adapter/presets.d.ts} +0 -0
- /package/lib/types/{presets.js → dsh-adapter/presets.js} +0 -0
|
@@ -0,0 +1,653 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trajectory projection — folding the session event log into ledger nodes.
|
|
3
|
+
*
|
|
4
|
+
* ## What this is
|
|
5
|
+
*
|
|
6
|
+
* The DSH session log is an append-only stream of ~44 event types. This
|
|
7
|
+
* module folds it into the flat, turn-annotated node list the trajectory
|
|
8
|
+
* scene renders, pairing every bracket (`tool/call` ↔ `tool/result`,
|
|
9
|
+
* `step/start` ↔ `step/end`, `llm/retry` ↔ `llm/retry-started`,
|
|
10
|
+
* `approval/asked` ↔ `approval/decided`, `compaction/start` ↔
|
|
11
|
+
* `compaction/end`, `tool/code-dispatch-start` ↔ `tool/code-dispatch`) so a
|
|
12
|
+
* row can show its own wall-clock duration and outcome.
|
|
13
|
+
*
|
|
14
|
+
* ## Incrementality
|
|
15
|
+
*
|
|
16
|
+
* `agent.session.events` is an immutable snapshot whose element objects are
|
|
17
|
+
* frozen at append and REUSED until the next append. {@link extendTrajectory}
|
|
18
|
+
* exploits exactly that: when the incoming snapshot prefix-extends the one the
|
|
19
|
+
* previous build consumed — proven by *object identity* at the previous last
|
|
20
|
+
* index, never by `seq` arithmetic, which a fork can rewind — only the new
|
|
21
|
+
* tail is folded. Any other relationship (agent swap on `/resume`, `/rewind`,
|
|
22
|
+
* `/new`) rebuilds from scratch. A long session therefore never pays an O(n)
|
|
23
|
+
* refold per frame, and `verify-trace-projection` asserts that the incremental
|
|
24
|
+
* and from-scratch results are field-for-field identical at every split point.
|
|
25
|
+
*
|
|
26
|
+
* ## What it deliberately does not do
|
|
27
|
+
*
|
|
28
|
+
* No node holds derived text. `detail`/`outcome` are references into strings
|
|
29
|
+
* the log already owns, and the view flattens only the rows it paints (see
|
|
30
|
+
* {@link previewText}). Full content is not held at all — `seq`/`endSeq`
|
|
31
|
+
* address the owning events for the inspector to re-read on demand.
|
|
32
|
+
*
|
|
33
|
+
* Storage-level chunk packing (`text-chunks`, `reasoning-chunks`,
|
|
34
|
+
* `tool-call-chunks`) is a durable *encoding*, not an event vocabulary: the
|
|
35
|
+
* persistence reader expands those rows back into `assistant/chunk` events
|
|
36
|
+
* before they reach `Session.events`, so this fold only ever sees the
|
|
37
|
+
* expanded form.
|
|
38
|
+
*/
|
|
39
|
+
import { asRawEvents, isApprovalDenied, readApprovalAsked, readApprovalDecided, readCommandRun, readCompaction, readDispatch, readHook, readModeValue, readRequestHeader, readRetry, readRetryStarted, readSubagent, readTodos, } from './guards.js';
|
|
40
|
+
import { BURST_MIN } from './types.js';
|
|
41
|
+
/** Fresh, empty fold state. */
|
|
42
|
+
function newState() {
|
|
43
|
+
return {
|
|
44
|
+
counts: { rows: 0, errors: 0, retries: 0 },
|
|
45
|
+
tools: new Map(),
|
|
46
|
+
subtools: new Map(),
|
|
47
|
+
steps: new Map(),
|
|
48
|
+
turns: new Map(),
|
|
49
|
+
retries: new Map(),
|
|
50
|
+
approvals: new Map(),
|
|
51
|
+
hooks: new Map(),
|
|
52
|
+
compactions: [],
|
|
53
|
+
turn: 0,
|
|
54
|
+
step: undefined,
|
|
55
|
+
seeding: true,
|
|
56
|
+
runKey: undefined,
|
|
57
|
+
runCount: 0,
|
|
58
|
+
runStart: -1,
|
|
59
|
+
runMembers: [],
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Clone the fold state for a continuation.
|
|
64
|
+
*
|
|
65
|
+
* The bracket maps are copied so a continuation does not mutate its input's
|
|
66
|
+
* bookkeeping — but `runMembers` is deliberately SHARED, not copied: once a
|
|
67
|
+
* run reaches {@link BURST_MIN} the synthetic burst node holds that very
|
|
68
|
+
* array, and a run that spans an incremental boundary must keep growing the
|
|
69
|
+
* array the node already references. Copying it here would silently freeze
|
|
70
|
+
* every burst at the length it had when the append arrived.
|
|
71
|
+
*
|
|
72
|
+
* Like the node list itself, a build is consumed once — extending the same
|
|
73
|
+
* `previous` twice with different tails is not supported (and matches the
|
|
74
|
+
* pre-existing trace fold's contract).
|
|
75
|
+
*/
|
|
76
|
+
function cloneState(previous) {
|
|
77
|
+
return {
|
|
78
|
+
// Counters are shared, not copied: like `nodes`, they belong to the build
|
|
79
|
+
// being extended, and a continuation must keep incrementing the same
|
|
80
|
+
// object the caller already holds.
|
|
81
|
+
counts: previous.counts,
|
|
82
|
+
tools: new Map(previous.tools),
|
|
83
|
+
subtools: new Map(previous.subtools),
|
|
84
|
+
steps: new Map(previous.steps),
|
|
85
|
+
turns: new Map(previous.turns),
|
|
86
|
+
retries: new Map(previous.retries),
|
|
87
|
+
approvals: new Map(previous.approvals),
|
|
88
|
+
hooks: new Map(previous.hooks),
|
|
89
|
+
compactions: [...previous.compactions],
|
|
90
|
+
turn: previous.turn,
|
|
91
|
+
step: previous.step,
|
|
92
|
+
seeding: previous.seeding,
|
|
93
|
+
runKey: previous.runKey,
|
|
94
|
+
runCount: previous.runCount,
|
|
95
|
+
runStart: previous.runStart,
|
|
96
|
+
runMembers: previous.runMembers,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
/** Read the first text block of a model-message content array. */
|
|
100
|
+
function firstText(content) {
|
|
101
|
+
if (!Array.isArray(content))
|
|
102
|
+
return undefined;
|
|
103
|
+
for (const block of content) {
|
|
104
|
+
if (typeof block !== 'object' || block === null)
|
|
105
|
+
continue;
|
|
106
|
+
const record = block;
|
|
107
|
+
if (record.type === 'text' && typeof record.text === 'string')
|
|
108
|
+
return record.text;
|
|
109
|
+
}
|
|
110
|
+
return undefined;
|
|
111
|
+
}
|
|
112
|
+
/** Read token accounting off an `assistant/message` payload. */
|
|
113
|
+
function readTokens(usage) {
|
|
114
|
+
if (typeof usage !== 'object' || usage === null)
|
|
115
|
+
return undefined;
|
|
116
|
+
const record = usage;
|
|
117
|
+
const pick = (key) => {
|
|
118
|
+
const value = record[key];
|
|
119
|
+
return typeof value === 'number' && Number.isFinite(value) ? value : 0;
|
|
120
|
+
};
|
|
121
|
+
const tokens = {
|
|
122
|
+
input: pick('input'),
|
|
123
|
+
output: pick('output'),
|
|
124
|
+
// The reasoning-token field has varied by adapter generation; accept both
|
|
125
|
+
// spellings and fall back to zero rather than dropping the whole usage.
|
|
126
|
+
think: pick('think') || pick('reasoning'),
|
|
127
|
+
cacheRead: pick('cacheRead'),
|
|
128
|
+
cacheWrite: pick('cacheWrite'),
|
|
129
|
+
};
|
|
130
|
+
const total = tokens.input + tokens.output + tokens.think + tokens.cacheRead + tokens.cacheWrite;
|
|
131
|
+
return total > 0 ? tokens : undefined;
|
|
132
|
+
}
|
|
133
|
+
/** Close a bracket node with its own duration and outcome. */
|
|
134
|
+
function close(state, node, event, status, errorCode) {
|
|
135
|
+
if (node === undefined)
|
|
136
|
+
return;
|
|
137
|
+
if (status === 'error' && node.status !== 'error')
|
|
138
|
+
state.counts.errors += 1;
|
|
139
|
+
node.endSeq = event.seq;
|
|
140
|
+
node.durationMs = Math.max(0, event.time - node.time);
|
|
141
|
+
node.status = status;
|
|
142
|
+
if (errorCode !== undefined)
|
|
143
|
+
node.errorCode = errorCode;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Append a node, folding runs of >= {@link BURST_MIN} consecutive same-name
|
|
147
|
+
* tool/subtool calls into one synthetic burst row.
|
|
148
|
+
*
|
|
149
|
+
* The run's members stay live: the pairing maps still hold the very objects
|
|
150
|
+
* `close(state, )` mutates when their results land, and the burst reads its totals
|
|
151
|
+
* off them on demand. Nothing needs re-visiting when a folded member closes.
|
|
152
|
+
*/
|
|
153
|
+
function push(state, nodes, node) {
|
|
154
|
+
const foldable = node.kind === 'tool' || node.kind === 'subtool';
|
|
155
|
+
const key = foldable ? `${node.kind}:${node.label}` : undefined;
|
|
156
|
+
if (key !== undefined && key === state.runKey) {
|
|
157
|
+
state.runCount += 1;
|
|
158
|
+
state.runMembers.push(node);
|
|
159
|
+
if (state.runCount < BURST_MIN) {
|
|
160
|
+
// Below the fold threshold the run is still shown call by call; the
|
|
161
|
+
// rows only merge once the run proves long enough to be noise.
|
|
162
|
+
nodes.push(node);
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
if (state.runCount === BURST_MIN) {
|
|
166
|
+
// Replace the run's rows with one synthetic burst node. The head's
|
|
167
|
+
// position is reused so surrounding order is untouched; rows after it
|
|
168
|
+
// cannot exist, because a run is by definition the ledger's tail.
|
|
169
|
+
const head = state.runMembers[0];
|
|
170
|
+
nodes.length = state.runStart;
|
|
171
|
+
nodes.push({
|
|
172
|
+
seq: head.seq,
|
|
173
|
+
time: head.time,
|
|
174
|
+
kind: head.kind,
|
|
175
|
+
turn: head.turn,
|
|
176
|
+
step: head.step,
|
|
177
|
+
label: head.label,
|
|
178
|
+
callId: head.callId,
|
|
179
|
+
subCallId: head.subCallId,
|
|
180
|
+
seed: head.seed,
|
|
181
|
+
burst: { name: head.label, members: state.runMembers },
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
// Beyond BURST_MIN the burst node already references `runMembers`, which
|
|
185
|
+
// was appended to above — nothing further to do.
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
state.runKey = key;
|
|
189
|
+
state.runCount = key === undefined ? 0 : 1;
|
|
190
|
+
state.runStart = nodes.length;
|
|
191
|
+
state.runMembers = key === undefined ? [] : [node];
|
|
192
|
+
nodes.push(node);
|
|
193
|
+
}
|
|
194
|
+
/** Row count after burst folding — the ledger's own length. */
|
|
195
|
+
function syncRowCount(state, nodes) {
|
|
196
|
+
state.counts.rows = nodes.length;
|
|
197
|
+
}
|
|
198
|
+
/** Fold one event into the working build. */
|
|
199
|
+
function consume(state, nodes, timing, event) {
|
|
200
|
+
const data = event.data;
|
|
201
|
+
const base = { seq: event.seq, time: event.time, seed: state.seeding || undefined };
|
|
202
|
+
switch (event.type) {
|
|
203
|
+
case 'session/end-seed': {
|
|
204
|
+
// Everything folded so far came from a replayed seed. Re-mark rather
|
|
205
|
+
// than trusting the first occurrence: a re-seeded log carries more than
|
|
206
|
+
// one, and only the LAST one bounds the inherited history.
|
|
207
|
+
for (const node of nodes)
|
|
208
|
+
node.seed = true;
|
|
209
|
+
state.seeding = false;
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
case 'turn/start': {
|
|
213
|
+
const turn = typeof data?.turn === 'number' ? data.turn : state.turn + 1;
|
|
214
|
+
state.turn = turn;
|
|
215
|
+
state.step = undefined;
|
|
216
|
+
const node = { ...base, kind: 'turn', turn, label: `turn ${turn}`, status: 'running' };
|
|
217
|
+
state.turns.set(turn, node);
|
|
218
|
+
push(state, nodes, node);
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
case 'turn/end': {
|
|
222
|
+
const turn = typeof data?.turn === 'number' ? data.turn : state.turn;
|
|
223
|
+
const open = state.turns.get(turn);
|
|
224
|
+
const reason = data?.reason;
|
|
225
|
+
const kind = typeof reason === 'object' && reason !== null
|
|
226
|
+
? reason.kind
|
|
227
|
+
: undefined;
|
|
228
|
+
close(state, open, event, kind === 'completed' ? 'ok' : 'error', typeof kind === 'string' && kind !== 'completed' ? kind : undefined);
|
|
229
|
+
state.turns.delete(turn);
|
|
230
|
+
state.step = undefined;
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
case 'step/start': {
|
|
234
|
+
const turn = typeof data?.turn === 'number' ? data.turn : state.turn;
|
|
235
|
+
const step = typeof data?.step === 'number' ? data.step : 0;
|
|
236
|
+
state.turn = turn;
|
|
237
|
+
state.step = step;
|
|
238
|
+
timing.set(`${turn}:${step}`, { startTime: event.time });
|
|
239
|
+
const node = { ...base, kind: 'step', turn, step, label: `step ${step}`, status: 'running' };
|
|
240
|
+
state.steps.set(`${turn}:${step}`, node);
|
|
241
|
+
push(state, nodes, node);
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
case 'step/end': {
|
|
245
|
+
const turn = typeof data?.turn === 'number' ? data.turn : state.turn;
|
|
246
|
+
const step = typeof data?.step === 'number' ? data.step : (state.step ?? 0);
|
|
247
|
+
const key = `${turn}:${step}`;
|
|
248
|
+
close(state, state.steps.get(key), event, 'ok');
|
|
249
|
+
state.steps.delete(key);
|
|
250
|
+
const slot = timing.get(key);
|
|
251
|
+
if (slot !== undefined)
|
|
252
|
+
slot.endTime = event.time;
|
|
253
|
+
state.step = undefined;
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
case 'assistant/chunk': {
|
|
257
|
+
// Chunks never become rows; they contribute only the two timestamps
|
|
258
|
+
// that separate time-to-first-token from decode throughput.
|
|
259
|
+
const turn = typeof data?.turn === 'number' ? data.turn : state.turn;
|
|
260
|
+
const step = typeof data?.step === 'number' ? data.step : (state.step ?? 0);
|
|
261
|
+
const slot = timing.get(`${turn}:${step}`);
|
|
262
|
+
if (slot === undefined)
|
|
263
|
+
return;
|
|
264
|
+
slot.firstChunk ??= event.time;
|
|
265
|
+
slot.lastChunk = event.time;
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
case 'user/message': {
|
|
269
|
+
const source = data?.source;
|
|
270
|
+
const sourceKind = typeof source === 'object' && source !== null
|
|
271
|
+
? source.kind
|
|
272
|
+
: undefined;
|
|
273
|
+
const text = firstText(data?.content);
|
|
274
|
+
if (text === undefined || text.trim() === '')
|
|
275
|
+
return;
|
|
276
|
+
// A direct human prompt is a USER row; everything else on the user-role
|
|
277
|
+
// surface (skill bodies, file-change notices, goal continuations) is an
|
|
278
|
+
// injected CONTEXT row — same distinction the official ledger draws.
|
|
279
|
+
const isHuman = sourceKind === 'user';
|
|
280
|
+
const sourceName = typeof source === 'object' && source !== null
|
|
281
|
+
? source.name
|
|
282
|
+
: undefined;
|
|
283
|
+
push(state, nodes, {
|
|
284
|
+
...base,
|
|
285
|
+
kind: isHuman ? 'user' : 'context',
|
|
286
|
+
turn: state.turn,
|
|
287
|
+
step: state.step,
|
|
288
|
+
label: isHuman ? '' : (sourceName ?? (typeof sourceKind === 'string' ? sourceKind : 'context')),
|
|
289
|
+
detail: text,
|
|
290
|
+
});
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
case 'assistant/message': {
|
|
294
|
+
const turn = typeof data?.turn === 'number' ? data.turn : state.turn;
|
|
295
|
+
const step = typeof data?.step === 'number' ? data.step : state.step;
|
|
296
|
+
const message = data?.message;
|
|
297
|
+
const content = typeof message === 'object' && message !== null
|
|
298
|
+
? message.content
|
|
299
|
+
: undefined;
|
|
300
|
+
const tokens = readTokens(data?.usage);
|
|
301
|
+
let first = true;
|
|
302
|
+
if (Array.isArray(content)) {
|
|
303
|
+
for (const block of content) {
|
|
304
|
+
if (typeof block !== 'object' || block === null)
|
|
305
|
+
continue;
|
|
306
|
+
const record = block;
|
|
307
|
+
const text = typeof record.text === 'string' ? record.text : '';
|
|
308
|
+
if (text.trim() === '')
|
|
309
|
+
continue;
|
|
310
|
+
const kind = record.type === 'reasoning' ? 'thinking' : record.type === 'text' ? 'assistant' : 'assistant';
|
|
311
|
+
if (record.type !== 'reasoning' && record.type !== 'text')
|
|
312
|
+
continue;
|
|
313
|
+
push(state, nodes, {
|
|
314
|
+
...base,
|
|
315
|
+
kind,
|
|
316
|
+
turn,
|
|
317
|
+
step,
|
|
318
|
+
label: '',
|
|
319
|
+
detail: text,
|
|
320
|
+
// Usage belongs to the step, not to each block: attach it to the
|
|
321
|
+
// first row so the hotspot aggregate counts it exactly once.
|
|
322
|
+
tokens: first ? tokens : undefined,
|
|
323
|
+
});
|
|
324
|
+
first = false;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
case 'tool/call': {
|
|
330
|
+
const callId = typeof data?.callId === 'string' ? data.callId : undefined;
|
|
331
|
+
const name = typeof data?.name === 'string' ? data.name : 'tool';
|
|
332
|
+
const args = typeof data?.arguments === 'string' ? data.arguments : undefined;
|
|
333
|
+
const node = {
|
|
334
|
+
...base,
|
|
335
|
+
kind: 'tool',
|
|
336
|
+
turn: typeof data?.turn === 'number' ? data.turn : state.turn,
|
|
337
|
+
step: typeof data?.step === 'number' ? data.step : state.step,
|
|
338
|
+
label: name,
|
|
339
|
+
detail: args,
|
|
340
|
+
callId,
|
|
341
|
+
status: 'running',
|
|
342
|
+
};
|
|
343
|
+
if (callId !== undefined)
|
|
344
|
+
state.tools.set(callId, node);
|
|
345
|
+
push(state, nodes, node);
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
case 'tool/result': {
|
|
349
|
+
const message = data?.message;
|
|
350
|
+
const source = typeof message === 'object' && message !== null
|
|
351
|
+
? message.source
|
|
352
|
+
: undefined;
|
|
353
|
+
const callId = typeof source === 'object' && source !== null
|
|
354
|
+
? source.callId
|
|
355
|
+
: undefined;
|
|
356
|
+
if (callId === undefined)
|
|
357
|
+
return;
|
|
358
|
+
const open = state.tools.get(callId);
|
|
359
|
+
if (open === undefined)
|
|
360
|
+
return;
|
|
361
|
+
const error = data?.error;
|
|
362
|
+
const code = typeof error === 'object' && error !== null
|
|
363
|
+
? error.code
|
|
364
|
+
: undefined;
|
|
365
|
+
open.outcome = firstText(typeof message === 'object' && message !== null
|
|
366
|
+
? message.content
|
|
367
|
+
: undefined);
|
|
368
|
+
close(state, open, event, error === undefined ? 'ok' : 'error', code);
|
|
369
|
+
state.tools.delete(callId);
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
case 'tool/code-dispatch-start': {
|
|
373
|
+
const payload = readDispatch(event.data);
|
|
374
|
+
if (payload === undefined)
|
|
375
|
+
return;
|
|
376
|
+
const node = {
|
|
377
|
+
...base,
|
|
378
|
+
kind: 'subtool',
|
|
379
|
+
turn: state.turn,
|
|
380
|
+
step: state.step,
|
|
381
|
+
label: payload.name,
|
|
382
|
+
detail: payload.args,
|
|
383
|
+
callId: payload.rootCallId,
|
|
384
|
+
subCallId: payload.subCallId,
|
|
385
|
+
status: 'running',
|
|
386
|
+
};
|
|
387
|
+
state.subtools.set(payload.subCallId, node);
|
|
388
|
+
push(state, nodes, node);
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
case 'tool/code-dispatch': {
|
|
392
|
+
const payload = readDispatch(event.data);
|
|
393
|
+
if (payload === undefined)
|
|
394
|
+
return;
|
|
395
|
+
const open = state.subtools.get(payload.subCallId);
|
|
396
|
+
if (open === undefined)
|
|
397
|
+
return;
|
|
398
|
+
close(state, open, event, payload.isError === true ? 'error' : 'ok');
|
|
399
|
+
state.subtools.delete(payload.subCallId);
|
|
400
|
+
return;
|
|
401
|
+
}
|
|
402
|
+
case 'llm/retry': {
|
|
403
|
+
const payload = readRetry(event.data);
|
|
404
|
+
if (payload === undefined)
|
|
405
|
+
return;
|
|
406
|
+
const existing = state.retries.get(payload.retryId);
|
|
407
|
+
if (existing !== undefined) {
|
|
408
|
+
// Same retry sequence, next attempt: keep one row and accumulate.
|
|
409
|
+
existing.attempts = (existing.attempts ?? 1) + 1;
|
|
410
|
+
existing.durationMs = (existing.durationMs ?? 0) + payload.delayMs;
|
|
411
|
+
state.counts.retries += 1;
|
|
412
|
+
return;
|
|
413
|
+
}
|
|
414
|
+
const node = {
|
|
415
|
+
...base,
|
|
416
|
+
kind: 'retry',
|
|
417
|
+
turn: payload.turn ?? state.turn,
|
|
418
|
+
step: payload.step ?? state.step,
|
|
419
|
+
label: payload.code ?? 'retry',
|
|
420
|
+
detail: payload.message,
|
|
421
|
+
status: 'running',
|
|
422
|
+
errorCode: payload.code,
|
|
423
|
+
attempts: 1,
|
|
424
|
+
durationMs: payload.delayMs,
|
|
425
|
+
};
|
|
426
|
+
state.retries.set(payload.retryId, node);
|
|
427
|
+
state.counts.retries += 1;
|
|
428
|
+
state.counts.errors += 1;
|
|
429
|
+
push(state, nodes, node);
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
case 'llm/retry-started': {
|
|
433
|
+
const retryId = readRetryStarted(event.data);
|
|
434
|
+
if (retryId === undefined)
|
|
435
|
+
return;
|
|
436
|
+
const open = state.retries.get(retryId);
|
|
437
|
+
if (open === undefined)
|
|
438
|
+
return;
|
|
439
|
+
// The bracket closes when the retried request starts; the accumulated
|
|
440
|
+
// backoff is the row's own duration, so `close(state, )` must not overwrite it.
|
|
441
|
+
open.endSeq = event.seq;
|
|
442
|
+
open.status = 'ok';
|
|
443
|
+
state.retries.delete(retryId);
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
446
|
+
case 'approval/asked': {
|
|
447
|
+
const payload = readApprovalAsked(event.data);
|
|
448
|
+
if (payload === undefined)
|
|
449
|
+
return;
|
|
450
|
+
const node = {
|
|
451
|
+
...base,
|
|
452
|
+
kind: 'approval',
|
|
453
|
+
turn: state.turn,
|
|
454
|
+
step: state.step,
|
|
455
|
+
label: payload.toolName ?? 'approval',
|
|
456
|
+
detail: payload.reason,
|
|
457
|
+
callId: payload.callId,
|
|
458
|
+
status: 'running',
|
|
459
|
+
};
|
|
460
|
+
state.approvals.set(payload.id, node);
|
|
461
|
+
push(state, nodes, node);
|
|
462
|
+
return;
|
|
463
|
+
}
|
|
464
|
+
case 'approval/decided': {
|
|
465
|
+
const payload = readApprovalDecided(event.data);
|
|
466
|
+
if (payload === undefined)
|
|
467
|
+
return;
|
|
468
|
+
const open = state.approvals.get(payload.id);
|
|
469
|
+
if (open === undefined)
|
|
470
|
+
return;
|
|
471
|
+
open.outcome = payload.outcome;
|
|
472
|
+
close(state, open, event, isApprovalDenied(payload.outcome) ? 'error' : 'ok');
|
|
473
|
+
state.approvals.delete(payload.id);
|
|
474
|
+
return;
|
|
475
|
+
}
|
|
476
|
+
case 'hook/invoked': {
|
|
477
|
+
const payload = readHook(event.data);
|
|
478
|
+
if (payload === undefined)
|
|
479
|
+
return;
|
|
480
|
+
const node = {
|
|
481
|
+
...base,
|
|
482
|
+
kind: 'system',
|
|
483
|
+
turn: state.turn,
|
|
484
|
+
step: state.step,
|
|
485
|
+
label: `hook ${payload.name}`,
|
|
486
|
+
detail: payload.event,
|
|
487
|
+
status: 'running',
|
|
488
|
+
};
|
|
489
|
+
if (payload.id !== undefined)
|
|
490
|
+
state.hooks.set(payload.id, node);
|
|
491
|
+
push(state, nodes, node);
|
|
492
|
+
return;
|
|
493
|
+
}
|
|
494
|
+
case 'hook/result': {
|
|
495
|
+
const payload = readHook(event.data);
|
|
496
|
+
const open = payload?.id === undefined ? undefined : state.hooks.get(payload.id);
|
|
497
|
+
if (open === undefined)
|
|
498
|
+
return;
|
|
499
|
+
close(state, open, event, 'ok');
|
|
500
|
+
state.hooks.delete(payload.id);
|
|
501
|
+
return;
|
|
502
|
+
}
|
|
503
|
+
case 'compaction/start': {
|
|
504
|
+
const payload = readCompaction(event.data);
|
|
505
|
+
const node = {
|
|
506
|
+
...base,
|
|
507
|
+
kind: 'compaction',
|
|
508
|
+
turn: state.turn,
|
|
509
|
+
step: state.step,
|
|
510
|
+
label: 'compaction',
|
|
511
|
+
detail: payload.reason,
|
|
512
|
+
status: 'running',
|
|
513
|
+
};
|
|
514
|
+
state.compactions.push(node);
|
|
515
|
+
push(state, nodes, node);
|
|
516
|
+
return;
|
|
517
|
+
}
|
|
518
|
+
case 'compaction/end': {
|
|
519
|
+
const open = state.compactions.pop();
|
|
520
|
+
const payload = readCompaction(event.data);
|
|
521
|
+
if (open !== undefined && payload.removed !== undefined) {
|
|
522
|
+
open.outcome = `-${payload.removed}`;
|
|
523
|
+
}
|
|
524
|
+
close(state, open, event, 'ok');
|
|
525
|
+
return;
|
|
526
|
+
}
|
|
527
|
+
case 'request/header': {
|
|
528
|
+
const payload = readRequestHeader(event.data);
|
|
529
|
+
// Only a *change* is a row: 'initial' and 'resume' restate the route
|
|
530
|
+
// the header line already shows, and would add one noise row per turn.
|
|
531
|
+
if (payload === undefined || payload.reason !== 'change')
|
|
532
|
+
return;
|
|
533
|
+
push(state, nodes, {
|
|
534
|
+
...base,
|
|
535
|
+
kind: 'system',
|
|
536
|
+
turn: state.turn,
|
|
537
|
+
step: state.step,
|
|
538
|
+
label: payload.model ?? 'route',
|
|
539
|
+
detail: payload.effort === undefined ? undefined : `effort=${payload.effort}`,
|
|
540
|
+
});
|
|
541
|
+
return;
|
|
542
|
+
}
|
|
543
|
+
case 'subagent/descriptor': {
|
|
544
|
+
const payload = readSubagent(event.data);
|
|
545
|
+
if (payload === undefined)
|
|
546
|
+
return;
|
|
547
|
+
push(state, nodes, {
|
|
548
|
+
...base,
|
|
549
|
+
kind: 'context',
|
|
550
|
+
turn: state.turn,
|
|
551
|
+
step: state.step,
|
|
552
|
+
label: 'subagent',
|
|
553
|
+
detail: [payload.label, payload.model].filter(Boolean).join(' · ') || undefined,
|
|
554
|
+
});
|
|
555
|
+
return;
|
|
556
|
+
}
|
|
557
|
+
case 'sandbox/mode':
|
|
558
|
+
case 'plan/mode':
|
|
559
|
+
case 'approval/policy':
|
|
560
|
+
case 'permission/preset':
|
|
561
|
+
case 'agent-preset/selected': {
|
|
562
|
+
const value = readModeValue(event.data);
|
|
563
|
+
if (value === undefined)
|
|
564
|
+
return;
|
|
565
|
+
push(state, nodes, {
|
|
566
|
+
...base,
|
|
567
|
+
kind: 'system',
|
|
568
|
+
turn: state.turn,
|
|
569
|
+
step: state.step,
|
|
570
|
+
label: event.type.split('/')[1] ?? event.type,
|
|
571
|
+
detail: value,
|
|
572
|
+
});
|
|
573
|
+
return;
|
|
574
|
+
}
|
|
575
|
+
case 'command/run': {
|
|
576
|
+
const payload = readCommandRun(event.data);
|
|
577
|
+
if (payload === undefined)
|
|
578
|
+
return;
|
|
579
|
+
push(state, nodes, {
|
|
580
|
+
...base,
|
|
581
|
+
kind: 'system',
|
|
582
|
+
turn: state.turn,
|
|
583
|
+
step: state.step,
|
|
584
|
+
label: `/${payload.name}`,
|
|
585
|
+
detail: payload.args?.trim() === '' ? undefined : payload.args,
|
|
586
|
+
});
|
|
587
|
+
return;
|
|
588
|
+
}
|
|
589
|
+
case 'todo/write': {
|
|
590
|
+
const payload = readTodos(event.data);
|
|
591
|
+
if (payload === undefined)
|
|
592
|
+
return;
|
|
593
|
+
push(state, nodes, {
|
|
594
|
+
...base,
|
|
595
|
+
kind: 'todo',
|
|
596
|
+
turn: state.turn,
|
|
597
|
+
step: state.step,
|
|
598
|
+
label: `${payload.done}/${payload.total}`,
|
|
599
|
+
detail: payload.current,
|
|
600
|
+
});
|
|
601
|
+
return;
|
|
602
|
+
}
|
|
603
|
+
default:
|
|
604
|
+
// Unknown or deliberately silent (request/context, session/title,
|
|
605
|
+
// agent/inbox/spliced, command/done, …): no ledger row. Forward
|
|
606
|
+
// compatibility is the default, not an error path.
|
|
607
|
+
return;
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
/** An empty build, used as the identity element and for empty sessions. */
|
|
611
|
+
export function emptyTrajectory() {
|
|
612
|
+
const state = newState();
|
|
613
|
+
return { source: [], nodes: [], timing: new Map(), counts: state.counts, state };
|
|
614
|
+
}
|
|
615
|
+
/**
|
|
616
|
+
* Extend a previous projection with the session's current event snapshot.
|
|
617
|
+
*
|
|
618
|
+
* @param previous - The prior build, or `null` to fold from scratch.
|
|
619
|
+
* @param events - The session's current immutable event snapshot.
|
|
620
|
+
* @returns A build over `events`; `previous` itself when nothing was appended.
|
|
621
|
+
*/
|
|
622
|
+
export function extendTrajectory(previous, events) {
|
|
623
|
+
const raw = asRawEvents(events);
|
|
624
|
+
if (previous !== null &&
|
|
625
|
+
raw.length >= previous.source.length &&
|
|
626
|
+
(previous.source.length === 0 ||
|
|
627
|
+
raw[previous.source.length - 1] === previous.source[previous.source.length - 1])) {
|
|
628
|
+
if (raw.length === previous.source.length)
|
|
629
|
+
return previous;
|
|
630
|
+
const nodes = previous.nodes;
|
|
631
|
+
const timing = previous.timing;
|
|
632
|
+
const state = cloneState(previous.state);
|
|
633
|
+
for (let index = previous.source.length; index < raw.length; index++) {
|
|
634
|
+
consume(state, nodes, timing, raw[index]);
|
|
635
|
+
}
|
|
636
|
+
syncRowCount(state, nodes);
|
|
637
|
+
return { source: raw, nodes, timing, counts: state.counts, state };
|
|
638
|
+
}
|
|
639
|
+
const nodes = [];
|
|
640
|
+
const timing = new Map();
|
|
641
|
+
const state = newState();
|
|
642
|
+
for (const event of raw)
|
|
643
|
+
consume(state, nodes, timing, event);
|
|
644
|
+
syncRowCount(state, nodes);
|
|
645
|
+
return { source: raw, nodes, timing, counts: state.counts, state };
|
|
646
|
+
}
|
|
647
|
+
/**
|
|
648
|
+
* Fold from scratch — the one-shot form used by tests and by consumers that
|
|
649
|
+
* hold no previous build.
|
|
650
|
+
*/
|
|
651
|
+
export function buildTrajectory(events) {
|
|
652
|
+
return extendTrajectory(null, events);
|
|
653
|
+
}
|