@deepseek-harness-tui/dsh-tui 0.6.1 → 0.7.1
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 +77 -23
- package/bin/dsh-tui.js +132 -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} +198 -43
- package/lib/types/dsh-adapter/channel.d.ts.map +1 -0
- package/lib/types/{channel.js → dsh-adapter/channel.js} +1129 -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} +294 -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 +981 -36
- package/lib/types/i18n.d.ts.map +1 -1
- package/lib/types/i18n.js +308 -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 +31 -10
- package/lib/invariant.js +0 -28
- 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
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import type { Channel } from '../channel.js';
|
|
2
|
+
import type { Channel } from '../dsh-adapter/channel.js';
|
|
3
|
+
import type { WaveBand } from '../dsh-adapter/types.js';
|
|
3
4
|
/**
|
|
4
5
|
* The footer under the prompt input, in Claude Code's PromptInputFooter
|
|
5
6
|
* layout: the segmented context progress bar on its own first line, the
|
|
@@ -8,9 +9,23 @@ import type { Channel } from '../channel.js';
|
|
|
8
9
|
* mode/hint line last. The right side of the footer shows the latest
|
|
9
10
|
* transient notification (errors in red, warnings in amber — CC style).
|
|
10
11
|
*/
|
|
11
|
-
export declare function StatusLine({ channel, selectionActive, helpOpen, }: {
|
|
12
|
+
export declare function StatusLine({ channel, selectionActive, helpOpen, wake, }: {
|
|
12
13
|
channel: Channel;
|
|
13
14
|
selectionActive?: boolean;
|
|
14
15
|
helpOpen?: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* The session projected onto the status line's few columns, plus the
|
|
18
|
+
* animation tick and the self-retiring key hint.
|
|
19
|
+
*
|
|
20
|
+
* A strip that shows the session's shape keeps earning its space in a way a
|
|
21
|
+
* static label cannot, and it carries the failure signal in position rather
|
|
22
|
+
* than as a count in the corner. Absent in headless embeds, where nothing
|
|
23
|
+
* folds the event log.
|
|
24
|
+
*/
|
|
25
|
+
wake?: {
|
|
26
|
+
band: WaveBand;
|
|
27
|
+
hint?: string;
|
|
28
|
+
tick: number;
|
|
29
|
+
};
|
|
15
30
|
}): React.JSX.Element;
|
|
16
31
|
//# sourceMappingURL=StatusLine.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StatusLine.d.ts","sourceRoot":"","sources":["../../../src/screens/StatusLine.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"StatusLine.d.ts","sourceRoot":"","sources":["../../../src/screens/StatusLine.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAOzB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAA;AAGxD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAQvD;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,EACzB,OAAO,EACP,eAAuB,EACvB,QAAgB,EAChB,IAAI,GACL,EAAE;IACD,OAAO,EAAE,OAAO,CAAA;IAChB,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;;;;;;;OAQG;IACH,IAAI,CAAC,EAAE;QAAE,IAAI,EAAE,QAAQ,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;CACvD,qBA2MA"}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Box, Text, useTerminalSize, useTheme } from '../ui.js';
|
|
3
3
|
import { formatTokens } from '../cc/format.js';
|
|
4
|
+
import { t } from '../i18n.js';
|
|
4
5
|
import { Byline } from '../components/design-system/Byline.js';
|
|
5
6
|
import { ActivityLine, contextPressurePct } from '../components/ActivityLine.js';
|
|
7
|
+
import { modeDisplayName } from '../sessionModes.js';
|
|
8
|
+
import { MiniWake } from '../components/trajectory/MiniWake.js';
|
|
6
9
|
import { renderContextBar, renderTpsGauge, renderTpsSparkline, speedColor, } from './StatusMetrics.js';
|
|
7
10
|
/**
|
|
8
11
|
* The footer under the prompt input, in Claude Code's PromptInputFooter
|
|
@@ -12,11 +15,16 @@ import { renderContextBar, renderTpsGauge, renderTpsSparkline, speedColor, } fro
|
|
|
12
15
|
* mode/hint line last. The right side of the footer shows the latest
|
|
13
16
|
* transient notification (errors in red, warnings in amber — CC style).
|
|
14
17
|
*/
|
|
15
|
-
export function StatusLine({ channel, selectionActive = false, helpOpen = false, }) {
|
|
18
|
+
export function StatusLine({ channel, selectionActive = false, helpOpen = false, wake, }) {
|
|
16
19
|
const { columns } = useTerminalSize();
|
|
17
20
|
const [themeName] = useTheme();
|
|
18
21
|
const usage = channel.lastUsage;
|
|
19
22
|
const contextParts = [];
|
|
23
|
+
// Session-mode marker (Shift+Tab cycle): hidden on the unmarked base
|
|
24
|
+
// mode (index 0); sage while a plan-declaring mode is in force.
|
|
25
|
+
if (channel.modeIndex > 0) {
|
|
26
|
+
contextParts.push(_jsx(Text, { color: channel.mode.plan === true ? 'planMode' : 'warning', children: modeDisplayName(channel.mode) }, "mode"));
|
|
27
|
+
}
|
|
20
28
|
if (channel.reasoningEffort !== undefined) {
|
|
21
29
|
contextParts.push(_jsx(Text, { color: "inactiveShimmer", children: channel.reasoningEffort }, "effort"));
|
|
22
30
|
}
|
|
@@ -26,7 +34,7 @@ export function StatusLine({ channel, selectionActive = false, helpOpen = false,
|
|
|
26
34
|
// segment, the rate is the glanceable health signal.
|
|
27
35
|
const total = usage.input + usage.cacheRead + usage.cacheWrite;
|
|
28
36
|
const rate = total > 0 ? (usage.cacheRead / total) * 100 : 0;
|
|
29
|
-
contextParts.push(_jsxs(Text, { children: [_jsx(Text, { dimColor: true, children:
|
|
37
|
+
contextParts.push(_jsxs(Text, { children: [_jsx(Text, { dimColor: true, children: t('status-cache-label') }), _jsxs(Text, { color: "inactiveShimmer", children: [rate.toFixed(1), "%"] })] }, "cache"));
|
|
30
38
|
}
|
|
31
39
|
// TPS readout sits right after the model so a crowded footer truncates
|
|
32
40
|
// the trailing fields (tokens/think/cache), never the speedometer. One
|
|
@@ -63,7 +71,7 @@ export function StatusLine({ channel, selectionActive = false, helpOpen = false,
|
|
|
63
71
|
_jsx(Text, { color: "professionalBlue", children: channel.gitBranch }, "git"),
|
|
64
72
|
]
|
|
65
73
|
: []),
|
|
66
|
-
_jsx(Text, { color: "inactiveShimmer", children: basename(channel.
|
|
74
|
+
_jsx(Text, { color: "inactiveShimmer", children: basename(channel.displayCwd) }, "cwd"),
|
|
67
75
|
...(channel.sessionTitle
|
|
68
76
|
? [
|
|
69
77
|
_jsx(Text, { dimColor: true, children: channel.sessionTitle }, "title"),
|
|
@@ -97,7 +105,7 @@ export function StatusLine({ channel, selectionActive = false, helpOpen = false,
|
|
|
97
105
|
if (channel.contextBarEnabled && barWidth >= 14 && channel.contextWindow !== undefined) {
|
|
98
106
|
bar = renderContextBar(channel.contextSegments, usage !== undefined ? usage.input + usage.cacheRead + usage.cacheWrite : 0, channel.contextWindow, barWidth, barColors);
|
|
99
107
|
}
|
|
100
|
-
return (_jsx(Box, { paddingX: 2, children: _jsxs(Box, { flexDirection: "column", width: "100%", children: [bar ? _jsx(Text, { children: bar }) : null, _jsxs(Box, { flexDirection: "row", justifyContent: "space-between", gap: 2, children: [_jsx(Text, { wrap: "truncate", children: _jsx(Byline, { children: leftParts }) }), _jsx(Box, { justifyContent: "flex-end", flexShrink: 2, children: _jsx(Text, { wrap: "truncate", children: _jsx(Byline, { children: rightParts }) }) })] }), _jsxs(Box, { height: 1, overflow: "hidden", flexDirection: "row", justifyContent: "space-between", gap: 2, children: [showActivity && activity !== undefined ? (_jsx(ActivityLine, { activity: activity, activityFrames: channel.activityFrames, warnPct: contextPressurePct(usage, channel.contextWindow), warnDanger: (contextPressurePct(usage, channel.contextWindow) ?? 0) >= 95 })) : hint ? (_jsx(Text, { color: "inactiveShimmer", children: hint })) : null, showActivity && hint ? (_jsx(Text, { color: "inactiveShimmer", wrap: "truncate", children: hint })) : null] })] }) }));
|
|
108
|
+
return (_jsx(Box, { paddingX: 2, width: columns, flexShrink: 0, children: _jsxs(Box, { flexDirection: "column", width: "100%", children: [bar ? _jsx(Text, { children: bar }) : null, _jsxs(Box, { flexDirection: "row", justifyContent: "space-between", gap: 2, children: [_jsx(Text, { wrap: "truncate", children: _jsx(Byline, { children: leftParts }) }), _jsx(Box, { justifyContent: "flex-end", flexShrink: 2, children: _jsx(Text, { wrap: "truncate", children: _jsx(Byline, { children: rightParts }) }) })] }), _jsxs(Box, { height: 1, overflow: "hidden", flexDirection: "row", justifyContent: "space-between", gap: 2, children: [showActivity && activity !== undefined ? (_jsx(ActivityLine, { activity: activity, activityFrames: channel.activityFrames, warnPct: contextPressurePct(usage, channel.contextWindow), warnDanger: (contextPressurePct(usage, channel.contextWindow) ?? 0) >= 95 })) : hint ? (_jsx(Text, { color: "inactiveShimmer", children: hint })) : null, showActivity && hint ? (_jsx(Text, { color: "inactiveShimmer", wrap: "truncate", children: hint })) : null, wake !== undefined ? (_jsx(MiniWake, { band: wake.band, hint: wake.hint, tick: wake.tick })) : null] })] }) }));
|
|
101
109
|
}
|
|
102
110
|
function basename(path) {
|
|
103
111
|
const parts = path.split(/[\\/]/);
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { type TrajBuild } from '../dsh-adapter/trajectory/index.js';
|
|
3
|
+
import type { Channel } from '../dsh-adapter/channel.js';
|
|
4
|
+
export type TrajectoryView = 'timeline' | 'hotspot';
|
|
5
|
+
export declare function TrajectoryScene({ channel, build, onClose, }: {
|
|
6
|
+
channel: Channel;
|
|
7
|
+
/**
|
|
8
|
+
* The session projection, folded by the host. Passing it in rather than
|
|
9
|
+
* folding here means the chat chrome and the scene share one build, so
|
|
10
|
+
* opening the scene costs no work at all.
|
|
11
|
+
*/
|
|
12
|
+
build: TrajBuild;
|
|
13
|
+
/** Leave the scene and return to the conversation. */
|
|
14
|
+
onClose: () => void;
|
|
15
|
+
}): React.ReactNode;
|
|
16
|
+
//# sourceMappingURL=TrajectoryScene.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TrajectoryScene.d.ts","sourceRoot":"","sources":["../../../src/screens/TrajectoryScene.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAczB,OAAO,EAML,KAAK,SAAS,EACf,MAAM,oCAAoC,CAAA;AAE3C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAA;AA+BxD,MAAM,MAAM,cAAc,GAAG,UAAU,GAAG,SAAS,CAAA;AAEnD,wBAAgB,eAAe,CAAC,EAC9B,OAAO,EACP,KAAK,EACL,OAAO,GACR,EAAE;IACD,OAAO,EAAE,OAAO,CAAA;IAChB;;;;OAIG;IACH,KAAK,EAAE,SAAS,CAAA;IAChB,sDAAsD;IACtD,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB,GAAG,KAAK,CAAC,SAAS,CAuYlB"}
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { Box, Text, useInput, useTerminalSize } from '../ui.js';
|
|
4
|
+
import { useAnimationFrame } from '../ink/hooks/use-animation-frame.js';
|
|
5
|
+
import { Divider } from '../components/design-system/Divider.js';
|
|
6
|
+
import { HintLine } from '../components/design-system/HintLine.js';
|
|
7
|
+
import { WaveBand } from '../components/trajectory/WaveBand.js';
|
|
8
|
+
import { Ledger } from '../components/trajectory/Ledger.js';
|
|
9
|
+
import { Inspector } from '../components/trajectory/Inspector.js';
|
|
10
|
+
import { HotspotView, hotspotRows } from '../components/trajectory/HotspotView.js';
|
|
11
|
+
import { applyQuery, parseQuery } from '../trajectory/query.js';
|
|
12
|
+
import { MOTION_TICK_MS } from '../trajectory/motion.js';
|
|
13
|
+
import { formatDuration, formatTokens, truncateWidth } from '../trajectory/format.js';
|
|
14
|
+
import { stringWidth } from '../ink/stringWidth.js';
|
|
15
|
+
import { t } from '../i18n.js';
|
|
16
|
+
import { aggregate, burstErrors, columnOfIndex, inspectNode, projectWave, } from '../dsh-adapter/trajectory/index.js';
|
|
17
|
+
import { HOTSPOT_SORTS, WAVE_PROJECTIONS } from '../dsh-adapter/trajectory/index.js';
|
|
18
|
+
/**
|
|
19
|
+
* The trajectory scene — the session's own screen.
|
|
20
|
+
*
|
|
21
|
+
* Rather than carving a panel out of the conversation, the trajectory takes
|
|
22
|
+
* the whole terminal the way `less`, `fzf` and `lazygit` do, and gives it back
|
|
23
|
+
* untouched on exit. That is not only a layout choice: the alternate screen
|
|
24
|
+
* has no scrollback, so none of the frame churn this view generates can reach
|
|
25
|
+
* the transcript — the inline shrink-frame path that once deposited UI copies
|
|
26
|
+
* into scrollback (issues #38/#39/#19/#10) is structurally out of reach here.
|
|
27
|
+
*
|
|
28
|
+
* Four regions, top to bottom: the header, the wake (whole session as one
|
|
29
|
+
* band), the ledger, and the inspector. Every region except the ledger has a
|
|
30
|
+
* fixed height, so moving the cursor never resizes the frame.
|
|
31
|
+
*/
|
|
32
|
+
/** Inspector height in the default (unexpanded) layout. */
|
|
33
|
+
const INSPECTOR_ROWS = 6;
|
|
34
|
+
/**
|
|
35
|
+
* Rows the ledger does not get: header, tabs, the wake's two rows, one blank
|
|
36
|
+
* line under the wake, the hint line, and one blank line above it.
|
|
37
|
+
*
|
|
38
|
+
* The two blank lines are deliberate. A view that fills every row edge to edge
|
|
39
|
+
* reads as pressure regardless of how good the individual rows are; giving the
|
|
40
|
+
* chrome and the content a line of ground between them costs two rows out of
|
|
41
|
+
* thirty and buys the whole screen room to breathe.
|
|
42
|
+
*/
|
|
43
|
+
const CHROME_ROWS = 2 + 2 + 1 + 1 + 1;
|
|
44
|
+
export function TrajectoryScene({ channel, build, onClose, }) {
|
|
45
|
+
const { columns, rows } = useTerminalSize();
|
|
46
|
+
const [ref, time] = useAnimationFrame(MOTION_TICK_MS);
|
|
47
|
+
const tick = Math.floor(time / MOTION_TICK_MS);
|
|
48
|
+
const [view, setView] = React.useState('timeline');
|
|
49
|
+
const [cursor, setCursor] = React.useState(0);
|
|
50
|
+
const [hotCursor, setHotCursor] = React.useState(0);
|
|
51
|
+
const [queryOpen, setQueryOpen] = React.useState(false);
|
|
52
|
+
const [queryText, setQueryText] = React.useState('');
|
|
53
|
+
// Compressed wall-clock is the default: it reads as a session profile — busy
|
|
54
|
+
// stretches are wide AND tall, idle gaps collapse to a thin flat run — while
|
|
55
|
+
// the pure sequence axis is the specialist view for scanning what happened.
|
|
56
|
+
const [projection, setProjection] = React.useState('compressed');
|
|
57
|
+
const [sort, setSort] = React.useState('duration');
|
|
58
|
+
const [expanded, setExpanded] = React.useState(false);
|
|
59
|
+
const [inspectScroll, setInspectScroll] = React.useState(0);
|
|
60
|
+
/** Ticks at which one-shot motion verbs were triggered. */
|
|
61
|
+
const [switchTick, setSwitchTick] = React.useState(0);
|
|
62
|
+
const [alertTick, setAlertTick] = React.useState(0);
|
|
63
|
+
const [arrivalTick, setArrivalTick] = React.useState(0);
|
|
64
|
+
const [arrivalFrom, setArrivalFrom] = React.useState(Number.MAX_SAFE_INTEGER);
|
|
65
|
+
/** Cursor pinned to the tail until the user scrolls away from it. */
|
|
66
|
+
const [follow, setFollow] = React.useState(true);
|
|
67
|
+
// ── projection ───────────────────────────────────────────────────────────
|
|
68
|
+
const nodes = build.nodes;
|
|
69
|
+
const query = React.useMemo(() => parseQuery(queryText), [queryText]);
|
|
70
|
+
const { rows: filtered, indexes } = React.useMemo(() => applyQuery(nodes, query),
|
|
71
|
+
// `nodes` is mutated in place by the incremental fold, so its length is
|
|
72
|
+
// the honest dependency — the array identity never changes.
|
|
73
|
+
// oxlint-disable-next-line react-hooks/exhaustive-deps
|
|
74
|
+
[nodes, nodes.length, query]);
|
|
75
|
+
const agg = React.useMemo(
|
|
76
|
+
// oxlint-disable-next-line react-hooks/exhaustive-deps
|
|
77
|
+
() => aggregate(build, sort), [build, nodes.length, sort]);
|
|
78
|
+
// ── arrival + alert detection ────────────────────────────────────────────
|
|
79
|
+
const seenRef = React.useRef(0);
|
|
80
|
+
const errorsRef = React.useRef(0);
|
|
81
|
+
React.useEffect(() => {
|
|
82
|
+
if (nodes.length > seenRef.current) {
|
|
83
|
+
setArrivalFrom(seenRef.current);
|
|
84
|
+
setArrivalTick(tick);
|
|
85
|
+
seenRef.current = nodes.length;
|
|
86
|
+
if (follow)
|
|
87
|
+
setCursor(Math.max(0, filtered.length - 1));
|
|
88
|
+
}
|
|
89
|
+
if (agg.totals.errors > errorsRef.current) {
|
|
90
|
+
errorsRef.current = agg.totals.errors;
|
|
91
|
+
setAlertTick(tick);
|
|
92
|
+
}
|
|
93
|
+
}, [nodes.length, agg.totals.errors, tick, follow, filtered.length]);
|
|
94
|
+
// ── geometry ─────────────────────────────────────────────────────────────
|
|
95
|
+
const inspectorRows = expanded ? Math.max(4, rows - CHROME_ROWS - 3) : INSPECTOR_ROWS;
|
|
96
|
+
const ledgerRows = Math.max(1, rows - CHROME_ROWS - inspectorRows - 1);
|
|
97
|
+
const bandWidth = Math.max(1, columns - 4);
|
|
98
|
+
const clampedCursor = filtered.length === 0 ? 0 : Math.min(cursor, filtered.length - 1);
|
|
99
|
+
const windowStart = Math.max(0, Math.min(clampedCursor - Math.floor(ledgerRows / 2), filtered.length - ledgerRows));
|
|
100
|
+
const band = React.useMemo(
|
|
101
|
+
// oxlint-disable-next-line react-hooks/exhaustive-deps
|
|
102
|
+
() => projectWave(nodes, bandWidth, projection), [nodes, nodes.length, bandWidth, projection]);
|
|
103
|
+
const matchColumns = React.useMemo(() => {
|
|
104
|
+
if (query.empty)
|
|
105
|
+
return undefined;
|
|
106
|
+
const set = new Set();
|
|
107
|
+
for (const index of indexes)
|
|
108
|
+
set.add(columnOfIndex(band, index));
|
|
109
|
+
return set;
|
|
110
|
+
}, [band, indexes, query.empty]);
|
|
111
|
+
const focused = filtered[clampedCursor];
|
|
112
|
+
const detail = React.useMemo(() => (focused === undefined ? undefined : inspectNode(focused, channel.traceEvents())), [focused, channel]);
|
|
113
|
+
// ── navigation helpers ───────────────────────────────────────────────────
|
|
114
|
+
const move = React.useCallback((delta) => {
|
|
115
|
+
setExpanded(false);
|
|
116
|
+
setInspectScroll(0);
|
|
117
|
+
setCursor(previous => {
|
|
118
|
+
const next = Math.max(0, Math.min(filtered.length - 1, previous + delta));
|
|
119
|
+
setFollow(next >= filtered.length - 1);
|
|
120
|
+
return next;
|
|
121
|
+
});
|
|
122
|
+
}, [filtered.length]);
|
|
123
|
+
const seek = React.useCallback((predicate, forward) => {
|
|
124
|
+
const from = clampedCursor;
|
|
125
|
+
const limit = filtered.length;
|
|
126
|
+
for (let step = 1; step <= limit; step++) {
|
|
127
|
+
const index = forward ? from + step : from - step;
|
|
128
|
+
if (index < 0 || index >= limit)
|
|
129
|
+
continue;
|
|
130
|
+
if (predicate(index)) {
|
|
131
|
+
setExpanded(false);
|
|
132
|
+
setInspectScroll(0);
|
|
133
|
+
setCursor(index);
|
|
134
|
+
setFollow(index >= limit - 1);
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}, [clampedCursor, filtered.length]);
|
|
139
|
+
const isFailure = React.useCallback((index) => {
|
|
140
|
+
const node = filtered[index];
|
|
141
|
+
return (node !== undefined &&
|
|
142
|
+
(node.status === 'error' || node.kind === 'retry' || (node.burst !== undefined && burstErrors(node.burst) > 0)));
|
|
143
|
+
}, [filtered]);
|
|
144
|
+
const switchView = React.useCallback((next) => {
|
|
145
|
+
setView(next);
|
|
146
|
+
setSwitchTick(tick);
|
|
147
|
+
setExpanded(false);
|
|
148
|
+
setInspectScroll(0);
|
|
149
|
+
}, [tick]);
|
|
150
|
+
// ── keys ─────────────────────────────────────────────────────────────────
|
|
151
|
+
useInput((input, key) => {
|
|
152
|
+
// The query line owns the keyboard while open, so a `q` typed into a
|
|
153
|
+
// search does not close the scene.
|
|
154
|
+
if (queryOpen) {
|
|
155
|
+
if (key.escape) {
|
|
156
|
+
setQueryOpen(false);
|
|
157
|
+
setQueryText('');
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
if (key.return) {
|
|
161
|
+
setQueryOpen(false);
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
if (key.backspace || key.delete) {
|
|
165
|
+
setQueryText(previous => previous.slice(0, -1));
|
|
166
|
+
setCursor(0);
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
if (input && !key.ctrl && !key.meta) {
|
|
170
|
+
setQueryText(previous => previous + input);
|
|
171
|
+
setCursor(0);
|
|
172
|
+
}
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
if (key.escape || input === 'q') {
|
|
176
|
+
if (expanded) {
|
|
177
|
+
setExpanded(false);
|
|
178
|
+
setInspectScroll(0);
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
if (!query.empty) {
|
|
182
|
+
setQueryText('');
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
onClose();
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
if (key.leftArrow)
|
|
189
|
+
return switchView('timeline');
|
|
190
|
+
if (key.rightArrow)
|
|
191
|
+
return switchView('hotspot');
|
|
192
|
+
if (input === 'h')
|
|
193
|
+
return switchView(view === 'hotspot' ? 'timeline' : 'hotspot');
|
|
194
|
+
if (input === '/') {
|
|
195
|
+
setQueryOpen(true);
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
if (view === 'hotspot') {
|
|
199
|
+
const total = hotspotRows(agg).length;
|
|
200
|
+
if (key.upArrow)
|
|
201
|
+
return setHotCursor(previous => Math.max(0, previous - 1));
|
|
202
|
+
if (key.downArrow)
|
|
203
|
+
return setHotCursor(previous => Math.min(total - 1, previous + 1));
|
|
204
|
+
if (input === 't') {
|
|
205
|
+
setSort(previous => HOTSPOT_SORTS[(HOTSPOT_SORTS.indexOf(previous) + 1) % HOTSPOT_SORTS.length]);
|
|
206
|
+
setSwitchTick(tick);
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
if (key.return) {
|
|
210
|
+
// Jump back to the timeline, positioned on the group's first member.
|
|
211
|
+
const row = hotspotRows(agg)[hotCursor];
|
|
212
|
+
switchView('timeline');
|
|
213
|
+
if (row !== undefined) {
|
|
214
|
+
const target = indexes.indexOf(row.firstIndex);
|
|
215
|
+
setCursor(target >= 0 ? target : 0);
|
|
216
|
+
setFollow(false);
|
|
217
|
+
}
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
if (key.upArrow)
|
|
223
|
+
return move(-1);
|
|
224
|
+
if (key.downArrow)
|
|
225
|
+
return move(1);
|
|
226
|
+
if (key.pageUp)
|
|
227
|
+
return move(-ledgerRows);
|
|
228
|
+
if (key.pageDown)
|
|
229
|
+
return move(ledgerRows);
|
|
230
|
+
if (input === 'g') {
|
|
231
|
+
setCursor(0);
|
|
232
|
+
setFollow(false);
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
if (input === 'G') {
|
|
236
|
+
setCursor(Math.max(0, filtered.length - 1));
|
|
237
|
+
setFollow(true);
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
if (input === '[')
|
|
241
|
+
return seek(isFailure, false);
|
|
242
|
+
if (input === ']')
|
|
243
|
+
return seek(isFailure, true);
|
|
244
|
+
if (input === '{')
|
|
245
|
+
return seek(index => filtered[index]?.kind === 'turn', false);
|
|
246
|
+
if (input === '}')
|
|
247
|
+
return seek(index => filtered[index]?.kind === 'turn', true);
|
|
248
|
+
if (input === 'm') {
|
|
249
|
+
setProjection(previous => WAVE_PROJECTIONS[(WAVE_PROJECTIONS.indexOf(previous) + 1) % WAVE_PROJECTIONS.length]);
|
|
250
|
+
setSwitchTick(tick);
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
if (key.return) {
|
|
254
|
+
setExpanded(previous => !previous);
|
|
255
|
+
setInspectScroll(0);
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
if (expanded && (input === 'j' || input === 'k')) {
|
|
259
|
+
setInspectScroll(previous => Math.max(0, previous + (input === 'j' ? inspectorRows - 2 : -(inspectorRows - 2))));
|
|
260
|
+
}
|
|
261
|
+
});
|
|
262
|
+
// ── header ───────────────────────────────────────────────────────────────
|
|
263
|
+
//
|
|
264
|
+
// Both chrome rows are composed as ONE pre-measured line each rather than as
|
|
265
|
+
// a flex row of groups. Flex plus `wrap="truncate"` proved unreliable here:
|
|
266
|
+
// a right-hand group laid out at its natural width lost its last character,
|
|
267
|
+
// and under other splits the overflow reflowed onto the row below — which
|
|
268
|
+
// pushes every region beneath it down and breaks the fixed geometry the
|
|
269
|
+
// whole scene depends on. Padding to an exact column count is deterministic,
|
|
270
|
+
// CJK-aware, and cheap (two strings per frame).
|
|
271
|
+
const { totals } = agg;
|
|
272
|
+
/** Left text, a computed gap, right text — clipped to `width` columns. */
|
|
273
|
+
const spread = (left, right, width) => {
|
|
274
|
+
const rightText = truncateWidth(right, Math.max(0, width - 4));
|
|
275
|
+
const room = width - stringWidth(rightText);
|
|
276
|
+
const leftText = truncateWidth(left, Math.max(0, room - 1));
|
|
277
|
+
return {
|
|
278
|
+
left: leftText,
|
|
279
|
+
gap: ' '.repeat(Math.max(1, room - stringWidth(leftText))),
|
|
280
|
+
right: rightText,
|
|
281
|
+
};
|
|
282
|
+
};
|
|
283
|
+
const totalsText = t('traj-totals', { turns: totals.turns, steps: totals.rows }) +
|
|
284
|
+
(totals.errors > 0 ? ` \u00b7 ${t('traj-errors', { n: totals.errors })}` : '') +
|
|
285
|
+
(totals.retries > 0 ? ` \u00b7 ${t('traj-retries', { n: totals.retries })}` : '') +
|
|
286
|
+
` \u00b7 ${formatDuration(totals.spanMs)}`;
|
|
287
|
+
const headerLine = spread(`\u2726 ${t('traj-title')} ${channel.sessionTitle ?? channel.cwd}`, totalsText, bandWidth);
|
|
288
|
+
const header = (_jsx(Box, { width: "100%", height: 1, flexShrink: 0, children: _jsxs(Text, { children: [_jsx(Text, { color: "claude", bold: true, children: `\u2726 ${t('traj-title')}` }), _jsx(Text, { color: "subtle", children: headerLine.left.slice((`\u2726 ${t('traj-title')}`).length) }), _jsx(Text, { children: headerLine.gap }), _jsx(Text, { color: totals.errors > 0 ? 'error' : 'subtle', children: headerLine.right })] }) }));
|
|
289
|
+
const axisLabel = view === 'hotspot' ? t(`traj-sort-${sort}`) : t(`traj-proj-${projection}`);
|
|
290
|
+
const tabsLeft = `${view === 'timeline' ? '\u25cf' : '\u25cb'} ${t('traj-tab-timeline')} ` +
|
|
291
|
+
`${view === 'hotspot' ? '\u25cf' : '\u25cb'} ${t('traj-tab-hotspot')}`;
|
|
292
|
+
const queryText_ = queryOpen || !query.empty
|
|
293
|
+
? ` / ${queryText}${queryOpen ? '\u258c' : ''} ${t('traj-matches', { n: filtered.length, total: nodes.length })}`
|
|
294
|
+
: '';
|
|
295
|
+
const tabsLine = spread(tabsLeft + queryText_, axisLabel, bandWidth);
|
|
296
|
+
const tabs = (_jsx(Box, { width: "100%", height: 1, flexShrink: 0, children: _jsxs(Text, { children: [_jsx(Text, { color: view === 'timeline' ? 'permission' : 'subtle', bold: view === 'timeline', children: tabsLine.left.slice(0, tabsLeft.length) }), _jsx(Text, { color: "suggestion", children: tabsLine.left.slice(tabsLeft.length) }), _jsx(Text, { children: tabsLine.gap }), _jsx(Text, { color: "subtle", children: tabsLine.right })] }) }));
|
|
297
|
+
const hints = view === 'hotspot'
|
|
298
|
+
? t('traj-hint-hotspot')
|
|
299
|
+
: queryOpen
|
|
300
|
+
? t('traj-hint-query')
|
|
301
|
+
: expanded
|
|
302
|
+
? t('traj-hint-expanded')
|
|
303
|
+
: t('traj-hint-timeline');
|
|
304
|
+
return (_jsxs(Box, { ref: ref, flexDirection: "column", width: "100%", paddingX: 1, children: [header, tabs, _jsx(WaveBand, { band: band, width: bandWidth, cursorColumn: columnOfIndex(band, indexes[clampedCursor] ?? 0), viewportStart: columnOfIndex(band, indexes[windowStart] ?? 0), viewportEnd: columnOfIndex(band, indexes[Math.min(filtered.length - 1, windowStart + ledgerRows - 1)] ?? 0), matches: matchColumns, tick: tick, alertTick: alertTick }), _jsx(Box, { height: 1, flexShrink: 0, children: _jsx(Text, { children: " " }) }), view === 'timeline' ? (_jsxs(_Fragment, { children: [_jsx(Ledger, { rows: filtered, start: windowStart, height: ledgerRows, cursor: clampedCursor, width: columns - 4, tick: tick, arrivalTick: arrivalTick, arrivalFrom: arrivalFrom }), _jsx(Divider, { color: "permission", width: bandWidth }), _jsx(Inspector, { node: focused, detail: detail, height: inspectorRows, width: columns - 4, expanded: expanded, scroll: inspectScroll })] })) : (_jsx(HotspotView, { agg: agg, sort: sort, width: columns - 4, height: ledgerRows + inspectorRows + 1, cursor: hotCursor, tick: tick, switchTick: switchTick })), _jsx(Box, { height: 1, flexShrink: 0, children: _jsx(Text, { children: " " }) }), _jsx(Box, { width: "100%", height: 1, flexShrink: 0, children: _jsxs(Text, { dimColor: true, italic: true, wrap: "truncate", children: [_jsx(HintLine, { text: hints }), totals.tokens.input > 0 ? (_jsx(Text, { color: "subtle", children: ` ${formatTokens(totals.tokens.input)}→${formatTokens(totals.tokens.output)}` })) : ('')] }) })] }));
|
|
305
|
+
}
|
|
@@ -8,13 +8,15 @@ export interface SessionRecord {
|
|
|
8
8
|
}
|
|
9
9
|
/**
|
|
10
10
|
* Store the session to resume and report the launcher invocation.
|
|
11
|
+
* Dual-writes the legacy path for pre-rename launchers (see header).
|
|
11
12
|
* @param sessionId - Session id for `dsh-tui --resume` on the next launch.
|
|
12
13
|
*/
|
|
13
14
|
export declare function writeResumeTarget(sessionId: string): void;
|
|
14
15
|
/** Forget the resume marker (`/new` starts a fresh conversation). */
|
|
15
16
|
export declare function clearResumeTarget(): void;
|
|
16
17
|
/**
|
|
17
|
-
* The session id requested by `dsh-tui --resume`, if any.
|
|
18
|
+
* The session id requested by `dsh-tui --resume`, if any. The new path
|
|
19
|
+
* wins; the legacy path is the fallback for pre-rename launchers.
|
|
18
20
|
* @returns The stored session id, or undefined when none is set.
|
|
19
21
|
*/
|
|
20
22
|
export declare function readResumeTarget(): string | undefined;
|
|
@@ -29,4 +31,10 @@ export declare function readLastUsed(): Readonly<Record<string, number>>;
|
|
|
29
31
|
* @param sessionId - Session id to touch.
|
|
30
32
|
*/
|
|
31
33
|
export declare function touchSession(sessionId: string): void;
|
|
34
|
+
/**
|
|
35
|
+
* Drop a session's last-used entry (`/resume` picker delete) so the MRU map
|
|
36
|
+
* never accumulates ids whose logs are gone. Best effort — never throws.
|
|
37
|
+
* @param sessionId - Session id to forget.
|
|
38
|
+
*/
|
|
39
|
+
export declare function forgetSession(sessionId: string): void;
|
|
32
40
|
//# sourceMappingURL=sessionHistory.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sessionHistory.d.ts","sourceRoot":"","sources":["../../src/sessionHistory.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"sessionHistory.d.ts","sourceRoot":"","sources":["../../src/sessionHistory.ts"],"names":[],"mappings":"AAoBA,8DAA8D;AAC9D,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,GAAG,EAAE,MAAM,CAAA;IACX,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;CAClB;AAWD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CASzD;AAED,qEAAqE;AACrE,wBAAgB,iBAAiB,IAAI,IAAI,CAQxC;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,GAAG,SAAS,CAUrD;AAED;;;GAGG;AACH,wBAAgB,YAAY,IAAI,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAiB/D;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAQpD;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAUrD"}
|
|
@@ -1,51 +1,73 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Launcher contract for `dsh-tui --resume`: the TUI writes the chosen session
|
|
3
|
-
* id to `~/.dsh-
|
|
4
|
-
* `
|
|
3
|
+
* id to `~/.dsh-tui/resume.txt`, and the launcher feeds it back as
|
|
4
|
+
* `DSH_TUI_RESUME_SESSION`. Session *records* live in DSH's own persistence
|
|
5
5
|
* backend (dsh-session-persistence-jsonl) — `/resume` lists those via
|
|
6
6
|
* `sessionPersistence.list()`, this file only carries the id across
|
|
7
7
|
* processes. It also keeps a small `last-used.json` of session-id → epoch-ms
|
|
8
8
|
* touches so `/resume` can sort most-recently-used first (DSH session
|
|
9
9
|
* headers carry only `createdAt`).
|
|
10
|
+
*
|
|
11
|
+
* Rename transition (issue #120): the global bin and the profile's TUI
|
|
12
|
+
* package may run different versions, so `resume.txt` is DUAL-WRITTEN to the
|
|
13
|
+
* legacy `~/.dsh-cc/resume.txt` as well (old launchers read only that path)
|
|
14
|
+
* and reads fall back to it. TODO: drop the legacy path once pre-rename
|
|
15
|
+
* launchers have aged out.
|
|
10
16
|
*/
|
|
11
|
-
import { homedir } from 'node:os';
|
|
12
17
|
import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
13
18
|
import { join } from 'node:path';
|
|
14
|
-
|
|
19
|
+
import { DATA_DIR, LEGACY_DATA_DIR } from './utils/paths.js';
|
|
20
|
+
const DIR = DATA_DIR;
|
|
15
21
|
const RESUME_FILE = join(DIR, 'resume.txt');
|
|
22
|
+
const LEGACY_RESUME_FILE = join(LEGACY_DATA_DIR, 'resume.txt');
|
|
16
23
|
const LAST_USED_FILE = join(DIR, 'last-used.json');
|
|
17
24
|
function ensureDir() {
|
|
18
25
|
mkdirSync(DIR, { recursive: true });
|
|
19
26
|
}
|
|
20
27
|
/**
|
|
21
28
|
* Store the session to resume and report the launcher invocation.
|
|
29
|
+
* Dual-writes the legacy path for pre-rename launchers (see header).
|
|
22
30
|
* @param sessionId - Session id for `dsh-tui --resume` on the next launch.
|
|
23
31
|
*/
|
|
24
32
|
export function writeResumeTarget(sessionId) {
|
|
25
33
|
ensureDir();
|
|
26
34
|
writeFileSync(RESUME_FILE, sessionId);
|
|
27
|
-
}
|
|
28
|
-
/** Forget the resume marker (`/new` starts a fresh conversation). */
|
|
29
|
-
export function clearResumeTarget() {
|
|
30
35
|
try {
|
|
31
|
-
|
|
36
|
+
mkdirSync(LEGACY_DATA_DIR, { recursive: true });
|
|
37
|
+
writeFileSync(LEGACY_RESUME_FILE, sessionId);
|
|
32
38
|
}
|
|
33
39
|
catch {
|
|
34
|
-
// Best effort — the
|
|
40
|
+
// Best effort — the legacy mirror only serves old launchers.
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/** Forget the resume marker (`/new` starts a fresh conversation). */
|
|
44
|
+
export function clearResumeTarget() {
|
|
45
|
+
for (const file of [RESUME_FILE, LEGACY_RESUME_FILE]) {
|
|
46
|
+
try {
|
|
47
|
+
writeFileSync(file, '');
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
// Best effort — the marker is a launcher nicety.
|
|
51
|
+
}
|
|
35
52
|
}
|
|
36
53
|
}
|
|
37
54
|
/**
|
|
38
|
-
* The session id requested by `dsh-tui --resume`, if any.
|
|
55
|
+
* The session id requested by `dsh-tui --resume`, if any. The new path
|
|
56
|
+
* wins; the legacy path is the fallback for pre-rename launchers.
|
|
39
57
|
* @returns The stored session id, or undefined when none is set.
|
|
40
58
|
*/
|
|
41
59
|
export function readResumeTarget() {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
60
|
+
for (const file of [RESUME_FILE, LEGACY_RESUME_FILE]) {
|
|
61
|
+
try {
|
|
62
|
+
const value = readFileSync(file, 'utf8').trim();
|
|
63
|
+
if (value)
|
|
64
|
+
return value;
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
// Try the next candidate.
|
|
68
|
+
}
|
|
48
69
|
}
|
|
70
|
+
return undefined;
|
|
49
71
|
}
|
|
50
72
|
/**
|
|
51
73
|
* Session-id → last-used epoch ms map for MRU ordering.
|
|
@@ -85,3 +107,21 @@ export function touchSession(sessionId) {
|
|
|
85
107
|
// Best effort — MRU ordering is a nicety.
|
|
86
108
|
}
|
|
87
109
|
}
|
|
110
|
+
/**
|
|
111
|
+
* Drop a session's last-used entry (`/resume` picker delete) so the MRU map
|
|
112
|
+
* never accumulates ids whose logs are gone. Best effort — never throws.
|
|
113
|
+
* @param sessionId - Session id to forget.
|
|
114
|
+
*/
|
|
115
|
+
export function forgetSession(sessionId) {
|
|
116
|
+
try {
|
|
117
|
+
const lastUsed = { ...readLastUsed() };
|
|
118
|
+
if (!(sessionId in lastUsed))
|
|
119
|
+
return;
|
|
120
|
+
delete lastUsed[sessionId];
|
|
121
|
+
ensureDir();
|
|
122
|
+
writeFileSync(LAST_USED_FILE, JSON.stringify(lastUsed));
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
// Best effort — a stale entry only skews sort order.
|
|
126
|
+
}
|
|
127
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export interface SessionModeSpec {
|
|
2
|
+
/** Stable id; also the display name unless `label` is set or the id is a
|
|
3
|
+
* localized built-in (`default`/`plan`/`full`). */
|
|
4
|
+
id: string;
|
|
5
|
+
/** Optional display label; wins over the built-in i18n name. */
|
|
6
|
+
label?: string;
|
|
7
|
+
/** Plan mode on/off (dsh-plan-mode `/plan`). */
|
|
8
|
+
plan?: boolean;
|
|
9
|
+
/** Sandbox mode override (dsh-sandbox-policy `sandbox/mode`). */
|
|
10
|
+
sandbox?: 'read-only' | 'workspace-write' | 'danger-full-access';
|
|
11
|
+
/** Approval policy override (dsh-user-approval `approval/policy`). */
|
|
12
|
+
approval?: 'ask' | 'never';
|
|
13
|
+
}
|
|
14
|
+
/** The shipped cycle when cordis.yml pins no `modes` — array order IS the
|
|
15
|
+
* Shift+Tab cycle order; index 0 is the unmarked base mode. */
|
|
16
|
+
export declare const DEFAULT_SESSION_MODES: readonly SessionModeSpec[];
|
|
17
|
+
/** Config → cycle list: undefined/empty → DEFAULT_SESSION_MODES; entries
|
|
18
|
+
* declaring no atom at all are dropped (their ids are returned for the
|
|
19
|
+
* caller to warn about); if nothing survives, DEFAULT_SESSION_MODES. Atom
|
|
20
|
+
* vocabularies are already enforced by the plugin Schema at load, so no
|
|
21
|
+
* value validation happens here. */
|
|
22
|
+
export declare function resolveSessionModes(raw: readonly SessionModeSpec[] | undefined): {
|
|
23
|
+
modes: readonly SessionModeSpec[];
|
|
24
|
+
dropped: readonly string[];
|
|
25
|
+
};
|
|
26
|
+
/** Display name: explicit `label` > built-in i18n (`mode-default`/
|
|
27
|
+
* `mode-plan`/`mode-full` for those ids) > the raw id. */
|
|
28
|
+
export declare function modeDisplayName(spec: SessionModeSpec): string;
|
|
29
|
+
//# sourceMappingURL=sessionModes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessionModes.d.ts","sourceRoot":"","sources":["../../src/sessionModes.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,eAAe;IAC9B;wDACoD;IACpD,EAAE,EAAE,MAAM,CAAA;IACV,gEAAgE;IAChE,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,gDAAgD;IAChD,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,iEAAiE;IACjE,OAAO,CAAC,EAAE,WAAW,GAAG,iBAAiB,GAAG,oBAAoB,CAAA;IAChE,sEAAsE;IACtE,QAAQ,CAAC,EAAE,KAAK,GAAG,OAAO,CAAA;CAC3B;AAED;gEACgE;AAChE,eAAO,MAAM,qBAAqB,EAAE,SAAS,eAAe,EAI3D,CAAA;AAED;;;;qCAIqC;AACrC,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,SAAS,eAAe,EAAE,GAAG,SAAS,GAAG;IAChF,KAAK,EAAE,SAAS,eAAe,EAAE,CAAA;IACjC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;CAC3B,CASA;AAED;2DAC2D;AAC3D,wBAAgB,eAAe,CAAC,IAAI,EAAE,eAAe,GAAG,MAAM,CAM7D"}
|