@deepseek-harness-tui/dsh-tui 0.5.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/LICENSE +21 -0
- package/README.md +235 -0
- package/bin/dsh-tui.js +95 -0
- package/cordis.patch.yml +218 -0
- package/cordis.yml +185 -0
- package/lib/invariant.js +28 -0
- package/lib/types/activityPrefs.d.ts +29 -0
- package/lib/types/activityPrefs.d.ts.map +1 -0
- package/lib/types/activityPrefs.js +60 -0
- package/lib/types/bootstrap/state.d.ts +13 -0
- package/lib/types/bootstrap/state.d.ts.map +1 -0
- package/lib/types/bootstrap/state.js +12 -0
- package/lib/types/cc/cliHighlight.d.ts +20 -0
- package/lib/types/cc/cliHighlight.d.ts.map +1 -0
- package/lib/types/cc/cliHighlight.js +53 -0
- package/lib/types/cc/figures.d.ts +59 -0
- package/lib/types/cc/figures.d.ts.map +1 -0
- package/lib/types/cc/figures.js +69 -0
- package/lib/types/cc/format.d.ts +26 -0
- package/lib/types/cc/format.d.ts.map +1 -0
- package/lib/types/cc/format.js +55 -0
- package/lib/types/cc/hash.d.ts +25 -0
- package/lib/types/cc/hash.d.ts.map +1 -0
- package/lib/types/cc/hash.js +41 -0
- package/lib/types/cc/hyperlink.d.ts +21 -0
- package/lib/types/cc/hyperlink.d.ts.map +1 -0
- package/lib/types/cc/hyperlink.js +31 -0
- package/lib/types/cc/markdown.d.ts +43 -0
- package/lib/types/cc/markdown.d.ts.map +1 -0
- package/lib/types/cc/markdown.js +345 -0
- package/lib/types/cc/spinnerVerbs.d.ts +3 -0
- package/lib/types/cc/spinnerVerbs.d.ts.map +1 -0
- package/lib/types/cc/spinnerVerbs.js +190 -0
- package/lib/types/cc/terminal.d.ts +15 -0
- package/lib/types/cc/terminal.d.ts.map +1 -0
- package/lib/types/cc/terminal.js +84 -0
- package/lib/types/channel.d.ts +672 -0
- package/lib/types/channel.d.ts.map +1 -0
- package/lib/types/channel.js +2427 -0
- package/lib/types/childStderr.d.ts +63 -0
- package/lib/types/childStderr.d.ts.map +1 -0
- package/lib/types/childStderr.js +161 -0
- package/lib/types/commands.d.ts +55 -0
- package/lib/types/commands.d.ts.map +1 -0
- package/lib/types/commands.js +101 -0
- package/lib/types/components/ActivityLine.d.ts +29 -0
- package/lib/types/components/ActivityLine.d.ts.map +1 -0
- package/lib/types/components/ActivityLine.js +47 -0
- package/lib/types/components/ActivityPicker.d.ts +13 -0
- package/lib/types/components/ActivityPicker.d.ts.map +1 -0
- package/lib/types/components/ActivityPicker.js +24 -0
- package/lib/types/components/CommandSuggestions.d.ts +14 -0
- package/lib/types/components/CommandSuggestions.d.ts.map +1 -0
- package/lib/types/components/CommandSuggestions.js +33 -0
- package/lib/types/components/FileSuggestions.d.ts +12 -0
- package/lib/types/components/FileSuggestions.d.ts.map +1 -0
- package/lib/types/components/FileSuggestions.js +26 -0
- package/lib/types/components/GoalTodoPanel.d.ts +13 -0
- package/lib/types/components/GoalTodoPanel.d.ts.map +1 -0
- package/lib/types/components/GoalTodoPanel.js +57 -0
- package/lib/types/components/HelpMenu.d.ts +12 -0
- package/lib/types/components/HelpMenu.d.ts.map +1 -0
- package/lib/types/components/HelpMenu.js +12 -0
- package/lib/types/components/HistorySearchDialog.d.ts +16 -0
- package/lib/types/components/HistorySearchDialog.d.ts.map +1 -0
- package/lib/types/components/HistorySearchDialog.js +31 -0
- package/lib/types/components/InterruptedByUser.d.ts +7 -0
- package/lib/types/components/InterruptedByUser.d.ts.map +1 -0
- package/lib/types/components/InterruptedByUser.js +9 -0
- package/lib/types/components/LoadedContextPanel.d.ts +20 -0
- package/lib/types/components/LoadedContextPanel.d.ts.map +1 -0
- package/lib/types/components/LoadedContextPanel.js +30 -0
- package/lib/types/components/LogoV2.d.ts +23 -0
- package/lib/types/components/LogoV2.d.ts.map +1 -0
- package/lib/types/components/LogoV2.js +95 -0
- package/lib/types/components/Markdown.d.ts +24 -0
- package/lib/types/components/Markdown.d.ts.map +1 -0
- package/lib/types/components/Markdown.js +106 -0
- package/lib/types/components/MarkdownTable.d.ts +17 -0
- package/lib/types/components/MarkdownTable.d.ts.map +1 -0
- package/lib/types/components/MarkdownTable.js +272 -0
- package/lib/types/components/MessageList.d.ts +41 -0
- package/lib/types/components/MessageList.d.ts.map +1 -0
- package/lib/types/components/MessageList.js +303 -0
- package/lib/types/components/ModelPicker.d.ts +14 -0
- package/lib/types/components/ModelPicker.d.ts.map +1 -0
- package/lib/types/components/ModelPicker.js +15 -0
- package/lib/types/components/PresetPicker.d.ts +17 -0
- package/lib/types/components/PresetPicker.d.ts.map +1 -0
- package/lib/types/components/PresetPicker.js +25 -0
- package/lib/types/components/PromptInput.d.ts +67 -0
- package/lib/types/components/PromptInput.d.ts.map +1 -0
- package/lib/types/components/PromptInput.js +778 -0
- package/lib/types/components/ResumePicker.d.ts +15 -0
- package/lib/types/components/ResumePicker.d.ts.map +1 -0
- package/lib/types/components/ResumePicker.js +34 -0
- package/lib/types/components/RewindPicker.d.ts +14 -0
- package/lib/types/components/RewindPicker.d.ts.map +1 -0
- package/lib/types/components/RewindPicker.js +23 -0
- package/lib/types/components/SearchBox.d.ts +20 -0
- package/lib/types/components/SearchBox.d.ts.map +1 -0
- package/lib/types/components/SearchBox.js +33 -0
- package/lib/types/components/Select.d.ts +22 -0
- package/lib/types/components/Select.d.ts.map +1 -0
- package/lib/types/components/Select.js +19 -0
- package/lib/types/components/Spinner/GlimmerMessage.d.ts +19 -0
- package/lib/types/components/Spinner/GlimmerMessage.d.ts.map +1 -0
- package/lib/types/components/Spinner/GlimmerMessage.js +78 -0
- package/lib/types/components/Spinner/SpinnerAnimationRow.d.ts +31 -0
- package/lib/types/components/Spinner/SpinnerAnimationRow.d.ts.map +1 -0
- package/lib/types/components/Spinner/SpinnerAnimationRow.js +162 -0
- package/lib/types/components/Spinner/SpinnerGlyph.d.ts +16 -0
- package/lib/types/components/Spinner/SpinnerGlyph.d.ts.map +1 -0
- package/lib/types/components/Spinner/SpinnerGlyph.js +36 -0
- package/lib/types/components/Spinner/spinnerMode.d.ts +6 -0
- package/lib/types/components/Spinner/spinnerMode.d.ts.map +1 -0
- package/lib/types/components/Spinner/spinnerMode.js +1 -0
- package/lib/types/components/Spinner/spinnerUtils.d.ts +41 -0
- package/lib/types/components/Spinner/spinnerUtils.d.ts.map +1 -0
- package/lib/types/components/Spinner/spinnerUtils.js +104 -0
- package/lib/types/components/Spinner/useStalledAnimation.d.ts +16 -0
- package/lib/types/components/Spinner/useStalledAnimation.d.ts.map +1 -0
- package/lib/types/components/Spinner/useStalledAnimation.js +71 -0
- package/lib/types/components/StreamingMarkdown.d.ts +12 -0
- package/lib/types/components/StreamingMarkdown.d.ts.map +1 -0
- package/lib/types/components/StreamingMarkdown.js +39 -0
- package/lib/types/components/ThemePicker.d.ts +22 -0
- package/lib/types/components/ThemePicker.d.ts.map +1 -0
- package/lib/types/components/ThemePicker.js +51 -0
- package/lib/types/components/ThinkingToggle.d.ts +17 -0
- package/lib/types/components/ThinkingToggle.d.ts.map +1 -0
- package/lib/types/components/ThinkingToggle.js +30 -0
- package/lib/types/components/ToolUseLoader.d.ts +13 -0
- package/lib/types/components/ToolUseLoader.d.ts.map +1 -0
- package/lib/types/components/ToolUseLoader.js +17 -0
- package/lib/types/components/Whale.d.ts +22 -0
- package/lib/types/components/Whale.d.ts.map +1 -0
- package/lib/types/components/Whale.js +78 -0
- package/lib/types/components/WorkingSpinner.d.ts +26 -0
- package/lib/types/components/WorkingSpinner.d.ts.map +1 -0
- package/lib/types/components/WorkingSpinner.js +68 -0
- package/lib/types/components/activityFrames.d.ts +31 -0
- package/lib/types/components/activityFrames.d.ts.map +1 -0
- package/lib/types/components/activityFrames.js +83 -0
- package/lib/types/components/bigfont.d.ts +28 -0
- package/lib/types/components/bigfont.d.ts.map +1 -0
- package/lib/types/components/bigfont.js +91 -0
- package/lib/types/components/design-system/Byline.d.ts +14 -0
- package/lib/types/components/design-system/Byline.d.ts.map +1 -0
- package/lib/types/components/design-system/Byline.js +17 -0
- package/lib/types/components/design-system/Divider.d.ts +40 -0
- package/lib/types/components/design-system/Divider.d.ts.map +1 -0
- package/lib/types/components/design-system/Divider.js +24 -0
- package/lib/types/components/design-system/KeyboardShortcutHint.d.ts +19 -0
- package/lib/types/components/design-system/KeyboardShortcutHint.d.ts.map +1 -0
- package/lib/types/components/design-system/KeyboardShortcutHint.js +14 -0
- package/lib/types/components/design-system/ListItem.d.ts +36 -0
- package/lib/types/components/design-system/ListItem.d.ts.map +1 -0
- package/lib/types/components/design-system/ListItem.js +48 -0
- package/lib/types/components/design-system/LoadingState.d.ts +19 -0
- package/lib/types/components/design-system/LoadingState.d.ts.map +1 -0
- package/lib/types/components/design-system/LoadingState.js +22 -0
- package/lib/types/components/design-system/Pane.d.ts +17 -0
- package/lib/types/components/design-system/Pane.d.ts.map +1 -0
- package/lib/types/components/design-system/Pane.js +15 -0
- package/lib/types/components/design-system/ProgressBar.d.ts +22 -0
- package/lib/types/components/design-system/ProgressBar.d.ts.map +1 -0
- package/lib/types/components/design-system/ProgressBar.js +27 -0
- package/lib/types/components/design-system/StatusIcon.d.ts +15 -0
- package/lib/types/components/design-system/StatusIcon.d.ts.map +1 -0
- package/lib/types/components/design-system/StatusIcon.js +20 -0
- package/lib/types/components/design-system/ThemeProvider.d.ts +11 -0
- package/lib/types/components/design-system/ThemeProvider.d.ts.map +1 -0
- package/lib/types/components/design-system/ThemeProvider.js +135 -0
- package/lib/types/components/design-system/ThemedBox.d.ts +37 -0
- package/lib/types/components/design-system/ThemedBox.d.ts.map +1 -0
- package/lib/types/components/design-system/ThemedBox.js +26 -0
- package/lib/types/components/design-system/ThemedText.d.ts +56 -0
- package/lib/types/components/design-system/ThemedText.d.ts.map +1 -0
- package/lib/types/components/design-system/ThemedText.js +45 -0
- package/lib/types/components/messages/AssistantTextMessage.d.ts +18 -0
- package/lib/types/components/messages/AssistantTextMessage.d.ts.map +1 -0
- package/lib/types/components/messages/AssistantTextMessage.js +15 -0
- package/lib/types/components/messages/AssistantThinkingMessage.d.ts +23 -0
- package/lib/types/components/messages/AssistantThinkingMessage.d.ts.map +1 -0
- package/lib/types/components/messages/AssistantThinkingMessage.js +23 -0
- package/lib/types/components/messages/AssistantToolUseMessage.d.ts +23 -0
- package/lib/types/components/messages/AssistantToolUseMessage.d.ts.map +1 -0
- package/lib/types/components/messages/AssistantToolUseMessage.js +220 -0
- package/lib/types/components/messages/MessageMetadata.d.ts +15 -0
- package/lib/types/components/messages/MessageMetadata.d.ts.map +1 -0
- package/lib/types/components/messages/MessageMetadata.js +20 -0
- package/lib/types/components/messages/UserPromptMessage.d.ts +19 -0
- package/lib/types/components/messages/UserPromptMessage.d.ts.map +1 -0
- package/lib/types/components/messages/UserPromptMessage.js +15 -0
- package/lib/types/components/questions/AskUserQuestionPanel.d.ts +39 -0
- package/lib/types/components/questions/AskUserQuestionPanel.d.ts.map +1 -0
- package/lib/types/components/questions/AskUserQuestionPanel.js +228 -0
- package/lib/types/components/shimmer.d.ts +35 -0
- package/lib/types/components/shimmer.d.ts.map +1 -0
- package/lib/types/components/shimmer.js +43 -0
- package/lib/types/components/whaleFrames.d.ts +25 -0
- package/lib/types/components/whaleFrames.d.ts.map +1 -0
- package/lib/types/components/whaleFrames.js +419 -0
- package/lib/types/customTheme.d.ts +104 -0
- package/lib/types/customTheme.d.ts.map +1 -0
- package/lib/types/customTheme.js +268 -0
- package/lib/types/effortPrefs.d.ts +22 -0
- package/lib/types/effortPrefs.d.ts.map +1 -0
- package/lib/types/effortPrefs.js +45 -0
- package/lib/types/history.d.ts +24 -0
- package/lib/types/history.d.ts.map +1 -0
- package/lib/types/history.js +75 -0
- package/lib/types/hooks/useBlink.d.ts +11 -0
- package/lib/types/hooks/useBlink.d.ts.map +1 -0
- package/lib/types/hooks/useBlink.js +20 -0
- package/lib/types/i18n.d.ts +926 -0
- package/lib/types/i18n.d.ts.map +1 -0
- package/lib/types/i18n.js +356 -0
- package/lib/types/index.d.ts +70 -0
- package/lib/types/index.d.ts.map +1 -0
- package/lib/types/index.js +31 -0
- package/lib/types/ink/Ansi.d.ts +11 -0
- package/lib/types/ink/Ansi.d.ts.map +1 -0
- package/lib/types/ink/Ansi.js +269 -0
- package/lib/types/ink/bidi.d.ts +18 -0
- package/lib/types/ink/bidi.d.ts.map +1 -0
- package/lib/types/ink/bidi.js +119 -0
- package/lib/types/ink/clearTerminal.d.ts +22 -0
- package/lib/types/ink/clearTerminal.d.ts.map +1 -0
- package/lib/types/ink/clearTerminal.js +72 -0
- package/lib/types/ink/colorize.d.ts +33 -0
- package/lib/types/ink/colorize.d.ts.map +1 -0
- package/lib/types/ink/colorize.js +213 -0
- package/lib/types/ink/components/AlternateScreen.d.ts +22 -0
- package/lib/types/ink/components/AlternateScreen.d.ts.map +1 -0
- package/lib/types/ink/components/AlternateScreen.js +74 -0
- package/lib/types/ink/components/App.d.ts +73 -0
- package/lib/types/ink/components/App.d.ts.map +1 -0
- package/lib/types/ink/components/App.js +597 -0
- package/lib/types/ink/components/AppContext.d.ts +15 -0
- package/lib/types/ink/components/AppContext.d.ts.map +1 -0
- package/lib/types/ink/components/AppContext.js +11 -0
- package/lib/types/ink/components/Box.d.ts +49 -0
- package/lib/types/ink/components/Box.d.ts.map +1 -0
- package/lib/types/ink/components/Box.js +153 -0
- package/lib/types/ink/components/Button.d.ts +37 -0
- package/lib/types/ink/components/Button.d.ts.map +1 -0
- package/lib/types/ink/components/Button.js +166 -0
- package/lib/types/ink/components/ClockContext.d.ts +10 -0
- package/lib/types/ink/components/ClockContext.d.ts.map +1 -0
- package/lib/types/ink/components/ClockContext.js +108 -0
- package/lib/types/ink/components/CursorDeclarationContext.d.ts +30 -0
- package/lib/types/ink/components/CursorDeclarationContext.d.ts.map +1 -0
- package/lib/types/ink/components/CursorDeclarationContext.js +6 -0
- package/lib/types/ink/components/ErrorOverview.d.ts +7 -0
- package/lib/types/ink/components/ErrorOverview.d.ts.map +1 -0
- package/lib/types/ink/components/ErrorOverview.js +49 -0
- package/lib/types/ink/components/Link.d.ts +8 -0
- package/lib/types/ink/components/Link.d.ts.map +1 -0
- package/lib/types/ink/components/Link.js +33 -0
- package/lib/types/ink/components/Newline.d.ts +13 -0
- package/lib/types/ink/components/Newline.d.ts.map +1 -0
- package/lib/types/ink/components/Newline.js +29 -0
- package/lib/types/ink/components/NoSelect.d.ts +20 -0
- package/lib/types/ink/components/NoSelect.d.ts.map +1 -0
- package/lib/types/ink/components/NoSelect.js +56 -0
- package/lib/types/ink/components/RawAnsi.d.ts +17 -0
- package/lib/types/ink/components/RawAnsi.d.ts.map +1 -0
- package/lib/types/ink/components/RawAnsi.js +45 -0
- package/lib/types/ink/components/ScrollBox.d.ts +78 -0
- package/lib/types/ink/components/ScrollBox.d.ts.map +1 -0
- package/lib/types/ink/components/ScrollBox.js +174 -0
- package/lib/types/ink/components/Spacer.d.ts +6 -0
- package/lib/types/ink/components/Spacer.d.ts.map +1 -0
- package/lib/types/ink/components/Spacer.js +19 -0
- package/lib/types/ink/components/StdinContext.d.ts +32 -0
- package/lib/types/ink/components/StdinContext.d.ts.map +1 -0
- package/lib/types/ink/components/StdinContext.js +16 -0
- package/lib/types/ink/components/TerminalFocusContext.d.ts +11 -0
- package/lib/types/ink/components/TerminalFocusContext.d.ts.map +1 -0
- package/lib/types/ink/components/TerminalFocusContext.js +45 -0
- package/lib/types/ink/components/TerminalSizeContext.d.ts +6 -0
- package/lib/types/ink/components/TerminalSizeContext.d.ts.map +1 -0
- package/lib/types/ink/components/TerminalSizeContext.js +3 -0
- package/lib/types/ink/components/Text.d.ts +56 -0
- package/lib/types/ink/components/Text.d.ts.map +1 -0
- package/lib/types/ink/components/Text.js +194 -0
- package/lib/types/ink/constants.d.ts +3 -0
- package/lib/types/ink/constants.d.ts.map +1 -0
- package/lib/types/ink/constants.js +2 -0
- package/lib/types/ink/cursor.d.ts +11 -0
- package/lib/types/ink/cursor.d.ts.map +1 -0
- package/lib/types/ink/cursor.js +1 -0
- package/lib/types/ink/devtools.d.ts +7 -0
- package/lib/types/ink/devtools.d.ts.map +1 -0
- package/lib/types/ink/devtools.js +1 -0
- package/lib/types/ink/dom.d.ts +178 -0
- package/lib/types/ink/dom.d.ts.map +1 -0
- package/lib/types/ink/dom.js +424 -0
- package/lib/types/ink/events/click-event.d.ts +32 -0
- package/lib/types/ink/events/click-event.d.ts.map +1 -0
- package/lib/types/ink/events/click-event.js +36 -0
- package/lib/types/ink/events/dispatcher.d.ts +63 -0
- package/lib/types/ink/events/dispatcher.d.ts.map +1 -0
- package/lib/types/ink/events/dispatcher.js +194 -0
- package/lib/types/ink/events/emitter.d.ts +20 -0
- package/lib/types/ink/events/emitter.d.ts.map +1 -0
- package/lib/types/ink/events/emitter.js +43 -0
- package/lib/types/ink/events/event-handlers.d.ts +47 -0
- package/lib/types/ink/events/event-handlers.d.ts.map +1 -0
- package/lib/types/ink/events/event-handlers.js +30 -0
- package/lib/types/ink/events/event.d.ts +19 -0
- package/lib/types/ink/events/event.d.ts.map +1 -0
- package/lib/types/ink/events/event.js +22 -0
- package/lib/types/ink/events/focus-event.d.ts +19 -0
- package/lib/types/ink/events/focus-event.d.ts.map +1 -0
- package/lib/types/ink/events/focus-event.js +21 -0
- package/lib/types/ink/events/input-event.d.ts +53 -0
- package/lib/types/ink/events/input-event.d.ts.map +1 -0
- package/lib/types/ink/events/input-event.js +180 -0
- package/lib/types/ink/events/keyboard-event.d.ts +40 -0
- package/lib/types/ink/events/keyboard-event.d.ts.map +1 -0
- package/lib/types/ink/events/keyboard-event.js +65 -0
- package/lib/types/ink/events/paste-event.d.ts +11 -0
- package/lib/types/ink/events/paste-event.d.ts.map +1 -0
- package/lib/types/ink/events/paste-event.js +13 -0
- package/lib/types/ink/events/resize-event.d.ts +13 -0
- package/lib/types/ink/events/resize-event.d.ts.map +1 -0
- package/lib/types/ink/events/resize-event.js +16 -0
- package/lib/types/ink/events/terminal-event.d.ts +112 -0
- package/lib/types/ink/events/terminal-event.d.ts.map +1 -0
- package/lib/types/ink/events/terminal-event.js +131 -0
- package/lib/types/ink/events/terminal-focus-event.d.ts +21 -0
- package/lib/types/ink/events/terminal-focus-event.d.ts.map +1 -0
- package/lib/types/ink/events/terminal-focus-event.js +18 -0
- package/lib/types/ink/focus.d.ts +74 -0
- package/lib/types/ink/focus.d.ts.map +1 -0
- package/lib/types/ink/focus.js +188 -0
- package/lib/types/ink/frame.d.ts +119 -0
- package/lib/types/ink/frame.d.ts.map +1 -0
- package/lib/types/ink/frame.js +43 -0
- package/lib/types/ink/get-max-width.d.ts +20 -0
- package/lib/types/ink/get-max-width.d.ts.map +1 -0
- package/lib/types/ink/get-max-width.js +25 -0
- package/lib/types/ink/hit-test.d.ts +47 -0
- package/lib/types/ink/hit-test.d.ts.map +1 -0
- package/lib/types/ink/hit-test.js +126 -0
- package/lib/types/ink/hooks/use-animation-frame.d.ts +27 -0
- package/lib/types/ink/hooks/use-animation-frame.d.ts.map +1 -0
- package/lib/types/ink/hooks/use-animation-frame.js +48 -0
- package/lib/types/ink/hooks/use-app.d.ts +8 -0
- package/lib/types/ink/hooks/use-app.d.ts.map +1 -0
- package/lib/types/ink/hooks/use-app.js +8 -0
- package/lib/types/ink/hooks/use-copy-on-select.d.ts +22 -0
- package/lib/types/ink/hooks/use-copy-on-select.d.ts.map +1 -0
- package/lib/types/ink/hooks/use-copy-on-select.js +40 -0
- package/lib/types/ink/hooks/use-declared-cursor.d.ts +31 -0
- package/lib/types/ink/hooks/use-declared-cursor.d.ts.map +1 -0
- package/lib/types/ink/hooks/use-declared-cursor.js +65 -0
- package/lib/types/ink/hooks/use-input.d.ts +41 -0
- package/lib/types/ink/hooks/use-input.d.ts.map +1 -0
- package/lib/types/ink/hooks/use-input.js +73 -0
- package/lib/types/ink/hooks/use-interval.d.ts +23 -0
- package/lib/types/ink/hooks/use-interval.d.ts.map +1 -0
- package/lib/types/ink/hooks/use-interval.js +58 -0
- package/lib/types/ink/hooks/use-search-highlight.d.ts +34 -0
- package/lib/types/ink/hooks/use-search-highlight.d.ts.map +1 -0
- package/lib/types/ink/hooks/use-search-highlight.js +35 -0
- package/lib/types/ink/hooks/use-selection.d.ts +44 -0
- package/lib/types/ink/hooks/use-selection.d.ts.map +1 -0
- package/lib/types/ink/hooks/use-selection.js +64 -0
- package/lib/types/ink/hooks/use-stdin.d.ts +8 -0
- package/lib/types/ink/hooks/use-stdin.d.ts.map +1 -0
- package/lib/types/ink/hooks/use-stdin.js +8 -0
- package/lib/types/ink/hooks/use-tab-status.d.ts +18 -0
- package/lib/types/ink/hooks/use-tab-status.d.ts.map +1 -0
- package/lib/types/ink/hooks/use-tab-status.js +58 -0
- package/lib/types/ink/hooks/use-terminal-focus.d.ts +11 -0
- package/lib/types/ink/hooks/use-terminal-focus.d.ts.map +1 -0
- package/lib/types/ink/hooks/use-terminal-focus.js +15 -0
- package/lib/types/ink/hooks/use-terminal-size.d.ts +6 -0
- package/lib/types/ink/hooks/use-terminal-size.d.ts.map +1 -0
- package/lib/types/ink/hooks/use-terminal-size.js +12 -0
- package/lib/types/ink/hooks/use-terminal-title.d.ts +14 -0
- package/lib/types/ink/hooks/use-terminal-title.d.ts.map +1 -0
- package/lib/types/ink/hooks/use-terminal-title.js +30 -0
- package/lib/types/ink/hooks/use-terminal-viewport.d.ts +32 -0
- package/lib/types/ink/hooks/use-terminal-viewport.d.ts.map +1 -0
- package/lib/types/ink/hooks/use-terminal-viewport.js +79 -0
- package/lib/types/ink/ink.d.ts +370 -0
- package/lib/types/ink/ink.d.ts.map +1 -0
- package/lib/types/ink/ink.js +1665 -0
- package/lib/types/ink/instances.d.ts +10 -0
- package/lib/types/ink/instances.d.ts.map +1 -0
- package/lib/types/ink/instances.js +13 -0
- package/lib/types/ink/layout/engine.d.ts +7 -0
- package/lib/types/ink/layout/engine.d.ts.map +1 -0
- package/lib/types/ink/layout/engine.js +8 -0
- package/lib/types/ink/layout/geometry.d.ts +86 -0
- package/lib/types/ink/layout/geometry.d.ts.map +1 -0
- package/lib/types/ink/layout/geometry.js +95 -0
- package/lib/types/ink/layout/node.d.ts +151 -0
- package/lib/types/ink/layout/node.d.ts.map +1 -0
- package/lib/types/ink/layout/node.js +72 -0
- package/lib/types/ink/layout/yoga.d.ts +69 -0
- package/lib/types/ink/layout/yoga.d.ts.map +1 -0
- package/lib/types/ink/layout/yoga.js +249 -0
- package/lib/types/ink/line-width-cache.d.ts +9 -0
- package/lib/types/ink/line-width-cache.d.ts.map +1 -0
- package/lib/types/ink/line-width-cache.js +45 -0
- package/lib/types/ink/log-update.d.ts +57 -0
- package/lib/types/ink/log-update.d.ts.map +1 -0
- package/lib/types/ink/log-update.js +710 -0
- package/lib/types/ink/measure-element.d.ts +19 -0
- package/lib/types/ink/measure-element.d.ts.map +1 -0
- package/lib/types/ink/measure-element.js +10 -0
- package/lib/types/ink/measure-text.d.ts +13 -0
- package/lib/types/ink/measure-text.d.ts.map +1 -0
- package/lib/types/ink/measure-text.js +38 -0
- package/lib/types/ink/node-cache.d.ts +33 -0
- package/lib/types/ink/node-cache.d.ts.map +1 -0
- package/lib/types/ink/node-cache.js +42 -0
- package/lib/types/ink/optimizer.d.ts +18 -0
- package/lib/types/ink/optimizer.d.ts.map +1 -0
- package/lib/types/ink/optimizer.js +83 -0
- package/lib/types/ink/output.d.ts +200 -0
- package/lib/types/ink/output.d.ts.map +1 -0
- package/lib/types/ink/output.js +663 -0
- package/lib/types/ink/parse-keypress.d.ts +132 -0
- package/lib/types/ink/parse-keypress.d.ts.map +1 -0
- package/lib/types/ink/parse-keypress.js +707 -0
- package/lib/types/ink/reconciler.d.ts +43 -0
- package/lib/types/ink/reconciler.d.ts.map +1 -0
- package/lib/types/ink/reconciler.js +413 -0
- package/lib/types/ink/render-border.d.ts +36 -0
- package/lib/types/ink/render-border.d.ts.map +1 -0
- package/lib/types/ink/render-border.js +143 -0
- package/lib/types/ink/render-node-to-output.d.ts +93 -0
- package/lib/types/ink/render-node-to-output.d.ts.map +1 -0
- package/lib/types/ink/render-node-to-output.js +1290 -0
- package/lib/types/ink/render-to-screen.d.ts +65 -0
- package/lib/types/ink/render-to-screen.d.ts.map +1 -0
- package/lib/types/ink/render-to-screen.js +189 -0
- package/lib/types/ink/renderer.d.ts +24 -0
- package/lib/types/ink/renderer.d.ts.map +1 -0
- package/lib/types/ink/renderer.js +136 -0
- package/lib/types/ink/root.d.ts +91 -0
- package/lib/types/ink/root.d.ts.map +1 -0
- package/lib/types/ink/root.js +93 -0
- package/lib/types/ink/screen.d.ts +443 -0
- package/lib/types/ink/screen.d.ts.map +1 -0
- package/lib/types/ink/screen.js +1295 -0
- package/lib/types/ink/searchHighlight.d.ts +25 -0
- package/lib/types/ink/searchHighlight.d.ts.map +1 -0
- package/lib/types/ink/searchHighlight.js +82 -0
- package/lib/types/ink/selection.d.ts +323 -0
- package/lib/types/ink/selection.d.ts.map +1 -0
- package/lib/types/ink/selection.js +881 -0
- package/lib/types/ink/squash-text-nodes.d.ts +30 -0
- package/lib/types/ink/squash-text-nodes.d.ts.map +1 -0
- package/lib/types/ink/squash-text-nodes.js +63 -0
- package/lib/types/ink/stringWidth.d.ts +11 -0
- package/lib/types/ink/stringWidth.d.ts.map +1 -0
- package/lib/types/ink/stringWidth.js +209 -0
- package/lib/types/ink/styles.d.ts +324 -0
- package/lib/types/ink/styles.d.ts.map +1 -0
- package/lib/types/ink/styles.js +307 -0
- package/lib/types/ink/supports-hyperlinks.d.ts +20 -0
- package/lib/types/ink/supports-hyperlinks.d.ts.map +1 -0
- package/lib/types/ink/supports-hyperlinks.js +44 -0
- package/lib/types/ink/tabstops.d.ts +9 -0
- package/lib/types/ink/tabstops.d.ts.map +1 -0
- package/lib/types/ink/tabstops.js +46 -0
- package/lib/types/ink/terminal-focus-state.d.ts +35 -0
- package/lib/types/ink/terminal-focus-state.d.ts.map +1 -0
- package/lib/types/ink/terminal-focus-state.js +57 -0
- package/lib/types/ink/terminal-querier.d.ts +161 -0
- package/lib/types/ink/terminal-querier.d.ts.map +1 -0
- package/lib/types/ink/terminal-querier.js +204 -0
- package/lib/types/ink/terminal.d.ts +80 -0
- package/lib/types/ink/terminal.d.ts.map +1 -0
- package/lib/types/ink/terminal.js +268 -0
- package/lib/types/ink/termio/ansi.d.ts +75 -0
- package/lib/types/ink/termio/ansi.d.ts.map +1 -0
- package/lib/types/ink/termio/ansi.js +79 -0
- package/lib/types/ink/termio/csi.d.ts +253 -0
- package/lib/types/ink/termio/csi.d.ts.map +1 -0
- package/lib/types/ink/termio/csi.js +347 -0
- package/lib/types/ink/termio/dec.d.ts +61 -0
- package/lib/types/ink/termio/dec.d.ts.map +1 -0
- package/lib/types/ink/termio/dec.js +76 -0
- package/lib/types/ink/termio/esc.d.ts +15 -0
- package/lib/types/ink/termio/esc.d.ts.map +1 -0
- package/lib/types/ink/termio/esc.js +57 -0
- package/lib/types/ink/termio/osc.d.ts +208 -0
- package/lib/types/ink/termio/osc.d.ts.map +1 -0
- package/lib/types/ink/termio/osc.js +466 -0
- package/lib/types/ink/termio/parser.d.ts +46 -0
- package/lib/types/ink/termio/parser.d.ts.map +1 -0
- package/lib/types/ink/termio/parser.js +366 -0
- package/lib/types/ink/termio/sgr.d.ts +17 -0
- package/lib/types/ink/termio/sgr.d.ts.map +1 -0
- package/lib/types/ink/termio/sgr.js +300 -0
- package/lib/types/ink/termio/tokenize.d.ts +50 -0
- package/lib/types/ink/termio/tokenize.d.ts.map +1 -0
- package/lib/types/ink/termio/tokenize.js +266 -0
- package/lib/types/ink/termio/types.d.ts +211 -0
- package/lib/types/ink/termio/types.d.ts.map +1 -0
- package/lib/types/ink/termio/types.js +68 -0
- package/lib/types/ink/termio.d.ts +25 -0
- package/lib/types/ink/termio.d.ts.map +1 -0
- package/lib/types/ink/termio.js +24 -0
- package/lib/types/ink/truncateToWidth.d.ts +7 -0
- package/lib/types/ink/truncateToWidth.d.ts.map +1 -0
- package/lib/types/ink/truncateToWidth.js +18 -0
- package/lib/types/ink/useTerminalNotification.d.ts +45 -0
- package/lib/types/ink/useTerminalNotification.d.ts.map +1 -0
- package/lib/types/ink/useTerminalNotification.js +70 -0
- package/lib/types/ink/warn.d.ts +7 -0
- package/lib/types/ink/warn.d.ts.map +1 -0
- package/lib/types/ink/warn.js +15 -0
- package/lib/types/ink/widest-line.d.ts +7 -0
- package/lib/types/ink/widest-line.d.ts.map +1 -0
- package/lib/types/ink/widest-line.js +19 -0
- package/lib/types/ink/wrap-text.d.ts +10 -0
- package/lib/types/ink/wrap-text.d.ts.map +1 -0
- package/lib/types/ink/wrap-text.js +61 -0
- package/lib/types/ink/wrapAnsi.d.ts +18 -0
- package/lib/types/ink/wrapAnsi.d.ts.map +1 -0
- package/lib/types/ink/wrapAnsi.js +16 -0
- package/lib/types/invariant.d.ts +20 -0
- package/lib/types/invariant.d.ts.map +1 -0
- package/lib/types/invariant.js +26 -0
- package/lib/types/modelPrefs.d.ts +37 -0
- package/lib/types/modelPrefs.d.ts.map +1 -0
- package/lib/types/modelPrefs.js +66 -0
- package/lib/types/modelRoute.d.ts +79 -0
- package/lib/types/modelRoute.d.ts.map +1 -0
- package/lib/types/modelRoute.js +96 -0
- package/lib/types/native-ts/yoga-layout/enums.d.ts +183 -0
- package/lib/types/native-ts/yoga-layout/enums.d.ts.map +1 -0
- package/lib/types/native-ts/yoga-layout/enums.js +150 -0
- package/lib/types/native-ts/yoga-layout/index.d.ts +788 -0
- package/lib/types/native-ts/yoga-layout/index.d.ts.map +1 -0
- package/lib/types/native-ts/yoga-layout/index.js +2571 -0
- package/lib/types/packaged-skills.d.ts +10 -0
- package/lib/types/packaged-skills.d.ts.map +1 -0
- package/lib/types/packaged-skills.js +63 -0
- package/lib/types/plugin.d.ts +33 -0
- package/lib/types/plugin.d.ts.map +1 -0
- package/lib/types/plugin.js +454 -0
- package/lib/types/presetPrefs.d.ts +29 -0
- package/lib/types/presetPrefs.d.ts.map +1 -0
- package/lib/types/presetPrefs.js +61 -0
- package/lib/types/presets.d.ts +110 -0
- package/lib/types/presets.d.ts.map +1 -0
- package/lib/types/presets.js +114 -0
- package/lib/types/questions.d.ts +97 -0
- package/lib/types/questions.d.ts.map +1 -0
- package/lib/types/questions.js +201 -0
- package/lib/types/screens/Chat.d.ts +23 -0
- package/lib/types/screens/Chat.d.ts.map +1 -0
- package/lib/types/screens/Chat.js +1263 -0
- package/lib/types/screens/StatusLine.d.ts +16 -0
- package/lib/types/screens/StatusLine.d.ts.map +1 -0
- package/lib/types/screens/StatusLine.js +105 -0
- package/lib/types/screens/StatusMetrics.d.ts +87 -0
- package/lib/types/screens/StatusMetrics.d.ts.map +1 -0
- package/lib/types/screens/StatusMetrics.js +252 -0
- package/lib/types/sessionHistory.d.ts +32 -0
- package/lib/types/sessionHistory.d.ts.map +1 -0
- package/lib/types/sessionHistory.js +87 -0
- package/lib/types/theme.d.ts +115 -0
- package/lib/types/theme.d.ts.map +1 -0
- package/lib/types/theme.js +300 -0
- package/lib/types/themePrefs.d.ts +28 -0
- package/lib/types/themePrefs.d.ts.map +1 -0
- package/lib/types/themePrefs.js +59 -0
- package/lib/types/ui.d.ts +28 -0
- package/lib/types/ui.d.ts.map +1 -0
- package/lib/types/ui.js +25 -0
- package/lib/types/update.d.ts +76 -0
- package/lib/types/update.d.ts.map +1 -0
- package/lib/types/update.js +203 -0
- package/lib/types/utils/clipboard.d.ts +43 -0
- package/lib/types/utils/clipboard.d.ts.map +1 -0
- package/lib/types/utils/clipboard.js +82 -0
- package/lib/types/utils/debug.d.ts +8 -0
- package/lib/types/utils/debug.d.ts.map +1 -0
- package/lib/types/utils/debug.js +12 -0
- package/lib/types/utils/earlyInput.d.ts +7 -0
- package/lib/types/utils/earlyInput.d.ts.map +1 -0
- package/lib/types/utils/earlyInput.js +6 -0
- package/lib/types/utils/env.d.ts +10 -0
- package/lib/types/utils/env.d.ts.map +1 -0
- package/lib/types/utils/env.js +9 -0
- package/lib/types/utils/envUtils.d.ts +8 -0
- package/lib/types/utils/envUtils.d.ts.map +1 -0
- package/lib/types/utils/envUtils.js +13 -0
- package/lib/types/utils/execFileNoThrow.d.ts +34 -0
- package/lib/types/utils/execFileNoThrow.d.ts.map +1 -0
- package/lib/types/utils/execFileNoThrow.js +31 -0
- package/lib/types/utils/fullscreen.d.ts +8 -0
- package/lib/types/utils/fullscreen.d.ts.map +1 -0
- package/lib/types/utils/fullscreen.js +10 -0
- package/lib/types/utils/intl.d.ts +7 -0
- package/lib/types/utils/intl.d.ts.map +1 -0
- package/lib/types/utils/intl.js +9 -0
- package/lib/types/utils/loaded-context.d.ts +20 -0
- package/lib/types/utils/loaded-context.d.ts.map +1 -0
- package/lib/types/utils/loaded-context.js +36 -0
- package/lib/types/utils/log.d.ts +7 -0
- package/lib/types/utils/log.d.ts.map +1 -0
- package/lib/types/utils/log.js +9 -0
- package/lib/types/utils/mentions.d.ts +30 -0
- package/lib/types/utils/mentions.d.ts.map +1 -0
- package/lib/types/utils/mentions.js +72 -0
- package/lib/types/utils/narration.d.ts +11 -0
- package/lib/types/utils/narration.d.ts.map +1 -0
- package/lib/types/utils/narration.js +16 -0
- package/lib/types/utils/semver.d.ts +9 -0
- package/lib/types/utils/semver.d.ts.map +1 -0
- package/lib/types/utils/semver.js +24 -0
- package/lib/types/utils/sliceAnsi.d.ts +12 -0
- package/lib/types/utils/sliceAnsi.d.ts.map +1 -0
- package/lib/types/utils/sliceAnsi.js +79 -0
- package/lib/types/working-activity.d.ts +19 -0
- package/lib/types/working-activity.d.ts.map +1 -0
- package/lib/types/working-activity.js +18 -0
- package/package.json +141 -0
- package/skills/audit/SKILL.md +24 -0
- package/skills/bug/SKILL.md +27 -0
- package/skills/pr-comments/SKILL.md +20 -0
- package/skills/practice/SKILL.md +22 -0
- package/skills/release-notes/SKILL.md +25 -0
- package/skills/review/SKILL.md +25 -0
- package/skills/vuln-check/SKILL.md +25 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
2
|
+
/**
|
|
3
|
+
* Register every `skills/<name>/SKILL.md` shipped in this package. No-op when
|
|
4
|
+
* the composition mounts no skill registry (bare standalone boots); duplicate
|
|
5
|
+
* or invalid entries are skipped so a skill can never take down the TUI boot.
|
|
6
|
+
*
|
|
7
|
+
* @param ctx - the plugin's cordis context
|
|
8
|
+
*/
|
|
9
|
+
export declare function registerPackagedSkills(ctx: Context): void;
|
|
10
|
+
//# sourceMappingURL=packaged-skills.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"packaged-skills.d.ts","sourceRoot":"","sources":["../../src/packaged-skills.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AA+BlD;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAqBzD"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Packaged skill self-registration. Mature harnesses (Claude Code plugins,
|
|
3
|
+
* pi packages) ship skills inside the package and contribute them through the
|
|
4
|
+
* host's skill registry seam — users never copy SKILL.md files into discovery
|
|
5
|
+
* directories by hand. This module does the same for dsh-tui: every
|
|
6
|
+
* `skills/<name>/SKILL.md` in the npm package is registered at boot, so the
|
|
7
|
+
* `/audit`-style slash commands resolve out of the box.
|
|
8
|
+
* @module @deepseek-harness-tui/dsh-tui/packaged-skills
|
|
9
|
+
*/
|
|
10
|
+
import { existsSync, readdirSync, readFileSync } from 'node:fs';
|
|
11
|
+
import { dirname, join } from 'node:path';
|
|
12
|
+
import { fileURLToPath } from 'node:url';
|
|
13
|
+
/**
|
|
14
|
+
* Parse a SKILL.md into name/description/content. Dependency-free: the
|
|
15
|
+
* packaged files use single-line scalar frontmatter fields only.
|
|
16
|
+
*
|
|
17
|
+
* @param raw - the raw SKILL.md text
|
|
18
|
+
* @param fallbackName - directory name used when frontmatter omits `name`
|
|
19
|
+
* @returns the parsed registration fields
|
|
20
|
+
*/
|
|
21
|
+
function parseSkillMarkdown(raw, fallbackName) {
|
|
22
|
+
const match = raw.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/);
|
|
23
|
+
const frontmatter = match?.[1] ?? '';
|
|
24
|
+
const content = (match?.[2] ?? raw).trim();
|
|
25
|
+
const name = frontmatter.match(/^name:\s*(.+)$/m)?.[1]?.trim() ?? fallbackName;
|
|
26
|
+
const description = frontmatter.match(/^description:\s*(.+)$/m)?.[1]?.trim() ?? '';
|
|
27
|
+
return { name, description, content };
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Register every `skills/<name>/SKILL.md` shipped in this package. No-op when
|
|
31
|
+
* the composition mounts no skill registry (bare standalone boots); duplicate
|
|
32
|
+
* or invalid entries are skipped so a skill can never take down the TUI boot.
|
|
33
|
+
*
|
|
34
|
+
* @param ctx - the plugin's cordis context
|
|
35
|
+
*/
|
|
36
|
+
export function registerPackagedSkills(ctx) {
|
|
37
|
+
const registry = ctx.get('skills');
|
|
38
|
+
if (!registry)
|
|
39
|
+
return;
|
|
40
|
+
// import.meta.url is lib/types/packaged-skills.js — two levels up is the
|
|
41
|
+
// package root, which is where `files` ships the skills/ directory.
|
|
42
|
+
const skillsRoot = join(dirname(fileURLToPath(import.meta.url)), '..', '..', 'skills');
|
|
43
|
+
if (!existsSync(skillsRoot))
|
|
44
|
+
return;
|
|
45
|
+
for (const entry of readdirSync(skillsRoot, { withFileTypes: true })) {
|
|
46
|
+
if (!entry.isDirectory())
|
|
47
|
+
continue;
|
|
48
|
+
const file = join(skillsRoot, entry.name, 'SKILL.md');
|
|
49
|
+
if (!existsSync(file))
|
|
50
|
+
continue;
|
|
51
|
+
const { name, description, content } = parseSkillMarkdown(readFileSync(file, 'utf8'), entry.name);
|
|
52
|
+
if (!description)
|
|
53
|
+
continue;
|
|
54
|
+
try {
|
|
55
|
+
registry.register({ name, description, content, path: file, provider: 'dsh-tui', source: 'bundled' });
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
// The registry itself warns and ignores duplicates; surface anything
|
|
59
|
+
// else (bad name, empty description) instead of failing the boot.
|
|
60
|
+
ctx.logger.warn(`packaged skill "${name}" skipped: ${error.message}`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
2
|
+
import { Config } from './index.js';
|
|
3
|
+
/**
|
|
4
|
+
* Claude Code style interactive TUI front door for DeepSeek Harness agents.
|
|
5
|
+
*
|
|
6
|
+
* The plugin attaches to (or creates) one agent, renders a chat transcript
|
|
7
|
+
* from the agent's session log and live `session/event` records, and submits
|
|
8
|
+
* user turns through `Agent.followup`. It is a client-driver front door like
|
|
9
|
+
* `dsh-jsonrpc`: the surrounding `cordis.yml` supplies the agent spine, the
|
|
10
|
+
* LLM adapter, and the tool plugins.
|
|
11
|
+
*/
|
|
12
|
+
export declare function apply(ctx: Context, config: Config): Promise<void>;
|
|
13
|
+
/**
|
|
14
|
+
* Distinguish a user-driven exit from a cordis context teardown (issue #12).
|
|
15
|
+
*
|
|
16
|
+
* Both paths settle the Ink instance's exit promise, but only a user exit
|
|
17
|
+
* (`/exit`, double Ctrl+C, render crash) may leave the process. A teardown —
|
|
18
|
+
* the DSH launcher's boot-time recompose disposes every entry once — must
|
|
19
|
+
* only unmount the UI: the recomposed tree re-runs `apply` and mounts a
|
|
20
|
+
* fresh instance, so exiting here would kill the process mid-recompose
|
|
21
|
+
* (the "flash back to bash with no error" symptom).
|
|
22
|
+
*
|
|
23
|
+
* `markTeardown` must run before the unmount that settles the exit promise
|
|
24
|
+
* (the settle reaches `handleExit` through a microtask, so a same-tick flag
|
|
25
|
+
* is always observed). Exported for scripts/verify-teardown-exit.tsx.
|
|
26
|
+
*/
|
|
27
|
+
export declare function createExitFunnel(deps: {
|
|
28
|
+
onUserExit: (error?: unknown) => void;
|
|
29
|
+
}): {
|
|
30
|
+
handleExit: (error?: unknown) => void;
|
|
31
|
+
markTeardown: () => void;
|
|
32
|
+
};
|
|
33
|
+
//# sourceMappingURL=plugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/plugin.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAkBnC;;;;;;;;GAQG;AACH,wBAAsB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAwSvE;AAyGD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE;IAAE,UAAU,EAAE,CAAC,KAAK,CAAC,EAAE,OAAO,KAAK,IAAI,CAAA;CAAE,GAAG;IACjF,UAAU,EAAE,CAAC,KAAK,CAAC,EAAE,OAAO,KAAK,IAAI,CAAA;IACrC,YAAY,EAAE,MAAM,IAAI,CAAA;CACzB,CAcA"}
|
|
@@ -0,0 +1,454 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { SessionId } from '@deepseek-ai/dsh-session';
|
|
4
|
+
import UserQuestionService from '@deepseek-ai/dsh-user-questions';
|
|
5
|
+
import * as toolAskUser from '@deepseek-ai/dsh-tool-ask-user';
|
|
6
|
+
import { createChannel } from './channel.js';
|
|
7
|
+
import { createChildStderrReporter, installChildStderrGuard } from './childStderr.js';
|
|
8
|
+
import { logForDebugging } from './utils/debug.js';
|
|
9
|
+
import { QuestionStore } from './questions.js';
|
|
10
|
+
import { registerPackagedSkills } from './packaged-skills.js';
|
|
11
|
+
import { readActivityFrames } from './activityPrefs.js';
|
|
12
|
+
import { readModelPref } from './modelPrefs.js';
|
|
13
|
+
import { explicitModelRoute, recordedModelRoute, resolveModelRoute, validateModelRoute } from './modelRoute.js';
|
|
14
|
+
import { readPresetPref } from './presetPrefs.js';
|
|
15
|
+
import { composePreset, resolvePersistedPreset, runningPresetOf } from './presets.js';
|
|
16
|
+
import { writeResumeTarget } from './sessionHistory.js';
|
|
17
|
+
import { checkForTuiUpdate, installedTuiVersion, isVersionNewer, resolveDshProfileName, resolveTuiUpdateTarget, updateTuiAndRestart } from './update.js';
|
|
18
|
+
import { isLang, resolveStartupLang, setLang, t } from './i18n.js';
|
|
19
|
+
import { Chat } from './screens/Chat.js';
|
|
20
|
+
import { render, ThemeProvider, AlternateScreen } from './ui.js';
|
|
21
|
+
/**
|
|
22
|
+
* Claude Code style interactive TUI front door for DeepSeek Harness agents.
|
|
23
|
+
*
|
|
24
|
+
* The plugin attaches to (or creates) one agent, renders a chat transcript
|
|
25
|
+
* from the agent's session log and live `session/event` records, and submits
|
|
26
|
+
* user turns through `Agent.followup`. It is a client-driver front door like
|
|
27
|
+
* `dsh-jsonrpc`: the surrounding `cordis.yml` supplies the agent spine, the
|
|
28
|
+
* LLM adapter, and the tool plugins.
|
|
29
|
+
*/
|
|
30
|
+
export async function apply(ctx, config) {
|
|
31
|
+
if (!process.stdout.isTTY) {
|
|
32
|
+
throw new Error('dsh-tui requires an interactive terminal (stdout must be a TTY).');
|
|
33
|
+
}
|
|
34
|
+
// UI language resolution: CC_TUI_LANG env var wins, then cordis.yml
|
|
35
|
+
// `lang`, then the persisted `/lang` choice, then `zh`. Must settle
|
|
36
|
+
// before the first render so every module resolves strings in the same
|
|
37
|
+
// language.
|
|
38
|
+
const envLang = process.env.CC_TUI_LANG;
|
|
39
|
+
setLang(isLang(envLang) ? envLang : isLang(config.lang) ? config.lang : resolveStartupLang());
|
|
40
|
+
// /update restart verification: the pre-update process stamps the version
|
|
41
|
+
// it was leaving behind; if the freshly loaded one is not newer, the
|
|
42
|
+
// package manager "succeeded" without actually moving the version (mirror
|
|
43
|
+
// lag, cached manifest, wrong profile). Say so instead of silently
|
|
44
|
+
// pretending the update landed.
|
|
45
|
+
{
|
|
46
|
+
const updatedFrom = process.env.DSH_CC_UPDATED_FROM;
|
|
47
|
+
if (updatedFrom !== undefined) {
|
|
48
|
+
// Assigning undefined would stringify to "undefined" and leak the
|
|
49
|
+
// marker into every child process; remove it for real.
|
|
50
|
+
delete process.env.DSH_CC_UPDATED_FROM;
|
|
51
|
+
const now = installedTuiVersion();
|
|
52
|
+
if (now === undefined || !isVersionNewer(now, updatedFrom)) {
|
|
53
|
+
ctx.logger.warn(`dsh-tui: /update restarted but the version did not advance (still ${now ?? 'unknown'}, was ${updatedFrom})`);
|
|
54
|
+
if (process.stderr.isTTY) {
|
|
55
|
+
process.stderr.write(`\ndsh-tui: 更新后版本未变化(仍为 ${now ?? 'unknown'},原为 ${updatedFrom});` +
|
|
56
|
+
`可能是镜像 registry 未同步,请稍后重试或检查 registry 配置。\n`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// DSH user-interaction seam: the model's ask_user_question tool parks on
|
|
62
|
+
// the userInteraction service until a UI provider answers. Mount the
|
|
63
|
+
// service when the composition doesn't (the official dsh-base
|
|
64
|
+
// user-interaction config row does; a bare plugin mount creates it on
|
|
65
|
+
// this context), expose the model-facing tool, and register this TUI's
|
|
66
|
+
// questionnaire as the provider. All three must be in place before the
|
|
67
|
+
// agent is resolved so the per-step tool assembly includes
|
|
68
|
+
// ask_user_question. Optional-service access goes through `ctx.get`, not
|
|
69
|
+
// the inject proxy.
|
|
70
|
+
const userQuestions = ctx.get('userQuestions') ?? new UserQuestionService(ctx);
|
|
71
|
+
ctx.plugin(toolAskUser);
|
|
72
|
+
const questionStore = new QuestionStore();
|
|
73
|
+
// Packaged skills (/audit, /bug, …): contribute them through the host's
|
|
74
|
+
// skill registry so they resolve with zero manual copying.
|
|
75
|
+
registerPackagedSkills(ctx);
|
|
76
|
+
userQuestions.registerProvider({
|
|
77
|
+
ask: request => questionStore.ask(request),
|
|
78
|
+
});
|
|
79
|
+
ctx.effect(() => () => questionStore.rejectAll());
|
|
80
|
+
// Child-process stderr guard (issue #17): MCP servers spawned with an
|
|
81
|
+
// inherited stderr (the MCP SDK's stdio default) write straight to the
|
|
82
|
+
// terminal device from the child process, bypassing the renderer's own
|
|
83
|
+
// stderr patch and corrupting the alt-screen. Take over those spawns and
|
|
84
|
+
// surface their stderr as deduplicated notifications instead. Installed
|
|
85
|
+
// before agent resolution so servers spawned during startup are covered;
|
|
86
|
+
// notices posted before the channel exists are buffered and flushed then.
|
|
87
|
+
const stderrBacklog = [];
|
|
88
|
+
let notifyStderr;
|
|
89
|
+
const stderrReporter = createChildStderrReporter((text, options) => {
|
|
90
|
+
if (notifyStderr !== undefined)
|
|
91
|
+
notifyStderr(text, options);
|
|
92
|
+
else
|
|
93
|
+
stderrBacklog.push([text, options]);
|
|
94
|
+
});
|
|
95
|
+
ctx.effect(() => {
|
|
96
|
+
const restoreSpawn = installChildStderrGuard(line => {
|
|
97
|
+
logForDebugging(`[child-stderr] ${line}`);
|
|
98
|
+
stderrReporter.push(line);
|
|
99
|
+
});
|
|
100
|
+
return () => {
|
|
101
|
+
restoreSpawn();
|
|
102
|
+
stderrReporter.dispose();
|
|
103
|
+
};
|
|
104
|
+
});
|
|
105
|
+
// Config-only route: resolveAgent applies the persisted `/model`
|
|
106
|
+
// preference on CREATE only — a resumed session keeps the route its own
|
|
107
|
+
// log records (last request/header), matching the preset rule.
|
|
108
|
+
const configuredRoute = {
|
|
109
|
+
provider: config.provider,
|
|
110
|
+
model: config.model,
|
|
111
|
+
};
|
|
112
|
+
// Atomic route resolution (issue #67): a complete cordis.yml route wins
|
|
113
|
+
// whole, else the persisted `/model` choice wins whole, else the harness
|
|
114
|
+
// defaults — a provider-only config pin never merges with the persisted
|
|
115
|
+
// model half. resolveAgent validates this route on create and reports the
|
|
116
|
+
// one actually used, so the status line shows the real request route.
|
|
117
|
+
const startupRoute = resolveModelRoute(configuredRoute, readModelPref());
|
|
118
|
+
const meta = { cwd: config.cwd ?? process.cwd() };
|
|
119
|
+
const { agent, handle, agentPreset, route: createdRoute } = await resolveAgent(ctx, config.sessionId, configuredRoute, startupRoute, meta, config.preset);
|
|
120
|
+
// Status-line route: the exact route the agent runs with — on create the
|
|
121
|
+
// validated startup resolution, on resume the route the target session's
|
|
122
|
+
// own records carry (a complete cordis.yml pin wins over them).
|
|
123
|
+
const displayRoute = createdRoute ?? startupRoute;
|
|
124
|
+
const channel = createChannel(ctx, agent, {
|
|
125
|
+
model: displayRoute.model,
|
|
126
|
+
cwd: config.cwd ?? process.cwd(),
|
|
127
|
+
provider: displayRoute.provider,
|
|
128
|
+
// Raw cordis.yml route (undefined when unset): the channel's
|
|
129
|
+
// new-session path re-resolves prefs against these, and resume passes
|
|
130
|
+
// only explicit values so the target session's own record wins.
|
|
131
|
+
configuredModel: config.model,
|
|
132
|
+
configuredProvider: config.provider,
|
|
133
|
+
effort: config.effort,
|
|
134
|
+
activity: config.activity,
|
|
135
|
+
// Explicit cordis.yml value (static deployment choice) wins over the
|
|
136
|
+
// runtime `/activity` preference, which wins over the default.
|
|
137
|
+
activityFrames: config.activityFrames ?? readActivityFrames() ?? 'claude',
|
|
138
|
+
// Static footer preference: cordis.yml `contextBar` (schema default on).
|
|
139
|
+
contextBar: config.contextBar,
|
|
140
|
+
// Same precedence for the agent preset: cordis.yml `preset` over the
|
|
141
|
+
// persisted `/preset` choice; undefined adopts the roster default.
|
|
142
|
+
configuredPreset: config.preset,
|
|
143
|
+
agentPreset,
|
|
144
|
+
handle,
|
|
145
|
+
});
|
|
146
|
+
// Attach the stderr reporter to the live channel and flush anything a
|
|
147
|
+
// startup-spawned server produced while the channel didn't exist yet.
|
|
148
|
+
notifyStderr = (text, options) => channel.notify(text, options);
|
|
149
|
+
for (const [text, options] of stderrBacklog.splice(0)) {
|
|
150
|
+
notifyStderr(text, options);
|
|
151
|
+
}
|
|
152
|
+
// Single exit funnel: `/exit` and double Ctrl+C land here, and so does
|
|
153
|
+
// the unmount triggered by a cordis context teardown — but the two must
|
|
154
|
+
// not share a fate (issue #12). The DSH launcher's boot-time recompose
|
|
155
|
+
// disposes every entry once; treating that teardown as a user exit killed
|
|
156
|
+
// the process before the recomposed tree could re-mount the TUI (the
|
|
157
|
+
// "flash back to bash with no error" symptom). Teardown only unmounts the
|
|
158
|
+
// UI; user exit runs the full leave sequence: unmount() restores the
|
|
159
|
+
// terminal (cursor, raw mode, mouse tracking) and the explicit newlines
|
|
160
|
+
// keep the shell prompt from overlapping the TUI's last line.
|
|
161
|
+
let instance;
|
|
162
|
+
let exited = false;
|
|
163
|
+
let updateRequested = false;
|
|
164
|
+
// The profile this process was booted with (`dsh --profile <name>`); dsh
|
|
165
|
+
// exposes it nowhere else, and /update must update the installation the
|
|
166
|
+
// user is actually running, not a hard-coded one.
|
|
167
|
+
const profile = resolveDshProfileName();
|
|
168
|
+
// Single exit funnel: `/exit` and double Ctrl+C land here, and so does
|
|
169
|
+
// the unmount triggered by a cordis context teardown — but the two must
|
|
170
|
+
// not share a fate (issue #12). Teardown only unmounts the UI; user exit
|
|
171
|
+
// runs the full leave sequence below (resume marker, terminal restore,
|
|
172
|
+
// update handoff or resume hint).
|
|
173
|
+
const funnel = createExitFunnel({
|
|
174
|
+
onUserExit: error => {
|
|
175
|
+
// Mirror the funnel's internal exited flag for the /update and
|
|
176
|
+
// background-check guards that still read the outer one.
|
|
177
|
+
exited = true;
|
|
178
|
+
try {
|
|
179
|
+
writeResumeTarget(channel.agentId);
|
|
180
|
+
}
|
|
181
|
+
catch {
|
|
182
|
+
// Best effort — the resume marker is a launcher nicety; a stale
|
|
183
|
+
// marker must never block a clean exit.
|
|
184
|
+
}
|
|
185
|
+
try {
|
|
186
|
+
instance?.unmount();
|
|
187
|
+
}
|
|
188
|
+
catch {
|
|
189
|
+
// The terminal state may already be gone (broken pipe, alt session);
|
|
190
|
+
// the exit path must never throw.
|
|
191
|
+
}
|
|
192
|
+
if (error !== undefined) {
|
|
193
|
+
// Error-driven unmount (render crash): stay loud and exit non-zero.
|
|
194
|
+
// A success code + resume hint here would tell wrappers/CI the
|
|
195
|
+
// session ended cleanly while the TUI actually crashed.
|
|
196
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
197
|
+
ctx.logger.error(`dsh-tui: exit after error: ${message}`);
|
|
198
|
+
if (process.stderr.isTTY) {
|
|
199
|
+
process.stderr.write(`\ndsh-tui crashed: ${message}\n`);
|
|
200
|
+
}
|
|
201
|
+
disposeRootAndExit(ctx, 1);
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
if (updateRequested) {
|
|
205
|
+
if (process.stdout.isTTY) {
|
|
206
|
+
process.stdout.write('\nUpdating @deepseek-harness-tui/dsh-tui and restarting…\n');
|
|
207
|
+
}
|
|
208
|
+
disposeRootAndThen(ctx, () => {
|
|
209
|
+
// updateRequested only flips when onUpdate exists, which itself
|
|
210
|
+
// requires a resolved profile — narrow for the call below.
|
|
211
|
+
const updateProfile = profile;
|
|
212
|
+
if (updateProfile === undefined) {
|
|
213
|
+
process.stderr.write('\ndsh-tui update aborted: no dsh profile resolved.\n');
|
|
214
|
+
process.exit(1);
|
|
215
|
+
}
|
|
216
|
+
void updateTuiAndRestart(channel.agentId, updateProfile).then(({ updateCode, restartCode }) => {
|
|
217
|
+
if (updateCode !== 0) {
|
|
218
|
+
// The session survives: its log lives in DSH persistence and
|
|
219
|
+
// resume.txt was already written. A bare non-zero exit would
|
|
220
|
+
// drop the user into a shell with no way back in.
|
|
221
|
+
process.stderr.write(`\ndsh-tui update failed (exit ${updateCode}). Your session is preserved — resume with:\n` +
|
|
222
|
+
`${resumeCommand(profile, channel.agentId)}\n\n`);
|
|
223
|
+
}
|
|
224
|
+
process.exit(restartCode);
|
|
225
|
+
}, updateError => {
|
|
226
|
+
const message = updateError instanceof Error ? updateError.message : String(updateError);
|
|
227
|
+
process.stderr.write(`\ndsh-tui update failed: ${message}. Your session is preserved — resume with:\n` +
|
|
228
|
+
`${resumeCommand(profile, channel.agentId)}\n\n`);
|
|
229
|
+
process.exit(1);
|
|
230
|
+
});
|
|
231
|
+
});
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
if (process.stdout.isTTY) {
|
|
235
|
+
process.stdout.write(`\nResume with (set the env var, then boot the profile):\n${resumeCommand(profile, channel.agentId)}\n\n`);
|
|
236
|
+
}
|
|
237
|
+
disposeRootAndExit(ctx, 0);
|
|
238
|
+
},
|
|
239
|
+
});
|
|
240
|
+
const handleExit = funnel.handleExit;
|
|
241
|
+
const chat = React.createElement(Chat, {
|
|
242
|
+
channel,
|
|
243
|
+
questionStore,
|
|
244
|
+
onExit: () => handleExit(),
|
|
245
|
+
// Only a `dsh --profile <name>` launch has a profile installation for
|
|
246
|
+
// `/update` to act on; source checkouts and `--config` overlays get the
|
|
247
|
+
// unavailable notice instead.
|
|
248
|
+
onUpdate: profile === undefined ? undefined : () => {
|
|
249
|
+
if (exited || updateRequested)
|
|
250
|
+
return;
|
|
251
|
+
// Confirm the target version before tearing the TUI down: on an
|
|
252
|
+
// already-latest install, an unconditional update+restart would churn
|
|
253
|
+
// the process and then trip the "version did not advance" warning.
|
|
254
|
+
void resolveTuiUpdateTarget().then((target) => {
|
|
255
|
+
if (exited || updateRequested)
|
|
256
|
+
return;
|
|
257
|
+
if (target.kind === 'latest') {
|
|
258
|
+
channel.notify(t('update-already-latest', { current: target.current }), { color: 'warning' });
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
if (target.kind === 'unknown') {
|
|
262
|
+
channel.notify(t('update-check-failed'));
|
|
263
|
+
}
|
|
264
|
+
channel.notify(t('update-starting'));
|
|
265
|
+
updateRequested = true;
|
|
266
|
+
instance?.unmount();
|
|
267
|
+
});
|
|
268
|
+
},
|
|
269
|
+
});
|
|
270
|
+
// fullscreen: wrap the tree in <AlternateScreen> (DEC 1049 + SGR mouse
|
|
271
|
+
// tracking), which turns on in-app text selection (copy-on-select via
|
|
272
|
+
// useCopyOnSelect), wheel scroll, and click/hover hit-testing. Inline
|
|
273
|
+
// mode leaves the mouse to the terminal emulator's native selection.
|
|
274
|
+
const tree = React.createElement(ThemeProvider, null, config.fullscreen ? React.createElement(AlternateScreen, null, chat) : chat);
|
|
275
|
+
instance = await render(tree, { exitOnCtrlC: false });
|
|
276
|
+
// Check in the background so registry latency never delays the first frame.
|
|
277
|
+
// A failed/offline check is intentionally silent; the manual `/update`
|
|
278
|
+
// command remains available regardless of network access.
|
|
279
|
+
void checkForTuiUpdate().then((update) => {
|
|
280
|
+
if (update === undefined || exited || updateRequested)
|
|
281
|
+
return;
|
|
282
|
+
channel.notify(t('update-available', { current: update.current, latest: update.latest }), { color: 'warning', timeoutMs: 12000 });
|
|
283
|
+
});
|
|
284
|
+
// If the surrounding tree goes down (reload, teardown), unmount the UI —
|
|
285
|
+
// but flag it as teardown first so the settling waitUntilExit does not
|
|
286
|
+
// run the user-exit sequence: no resume marker, no disposeRootAndExit,
|
|
287
|
+
// the process stays alive and the recomposed tree re-mounts the TUI.
|
|
288
|
+
ctx.effect(() => () => {
|
|
289
|
+
funnel.markTeardown();
|
|
290
|
+
instance?.unmount();
|
|
291
|
+
});
|
|
292
|
+
// The TUI is the front door: when the user unmounts it (Ctrl+C), dispose
|
|
293
|
+
// the app tree and exit the process. The rejection handler covers
|
|
294
|
+
// error-driven unmounts — without it a rejected exitPromise became an
|
|
295
|
+
// unhandled rejection instead of a clean exit. A teardown-driven settle
|
|
296
|
+
// is swallowed by the funnel (issue #12).
|
|
297
|
+
void instance.waitUntilExit().then(handleExit, handleExit);
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Attach to an existing agent, resume a persisted session (`dsh-tui --resume`
|
|
301
|
+
* feeds the id through `config.sessionId`), or create a fresh one. Resume
|
|
302
|
+
* goes through the DSH persistence seam (`ctx.agents.resume` reads the
|
|
303
|
+
* session log written by dsh-session-persistence-jsonl); a missing artifact
|
|
304
|
+
* or unmounted backend falls back to a fresh session, as does a plain boot
|
|
305
|
+
* without a session id.
|
|
306
|
+
*
|
|
307
|
+
* Preset composition (issue #8): a create resolves the requested preset
|
|
308
|
+
* (cordis.yml `preset` over the persisted `/preset` choice over the roster
|
|
309
|
+
* default) and mounts it in the factory's setup hook; a resume re-mounts the
|
|
310
|
+
* preset the session's own log records. Without the roster both paths behave
|
|
311
|
+
* as before presets existed.
|
|
312
|
+
*
|
|
313
|
+
* Model route (issues #14/#30/#67): a create adopts the caller's atomically
|
|
314
|
+
* resolved route (validated against the adapter catalog below); a resume
|
|
315
|
+
* passes only a COMPLETE cordis.yml route through — a provider-only pin must
|
|
316
|
+
* not half-override the route the target session's own records carry.
|
|
317
|
+
*/
|
|
318
|
+
async function resolveAgent(ctx, requestedSessionId, configuredRoute, startupRoute, meta, configuredPreset) {
|
|
319
|
+
// Resume override (issue #67): cordis.yml overrides the target session's
|
|
320
|
+
// recorded route only when it pins BOTH halves; undefined halves let the
|
|
321
|
+
// session's own request/header records win (issue #30).
|
|
322
|
+
const resumeRoute = explicitModelRoute(configuredRoute);
|
|
323
|
+
const resumeOptions = { provider: resumeRoute?.provider, model: resumeRoute?.model };
|
|
324
|
+
if (requestedSessionId !== undefined) {
|
|
325
|
+
const resumeId = SessionId(requestedSessionId);
|
|
326
|
+
const existing = ctx.agents.get(resumeId);
|
|
327
|
+
if (existing !== undefined) {
|
|
328
|
+
return { agent: existing, agentPreset: runningPresetOf(existing.session) };
|
|
329
|
+
}
|
|
330
|
+
try {
|
|
331
|
+
// The resumed session keeps the preset its log records (last
|
|
332
|
+
// `agent-preset/selected` wins over the creation header), never the
|
|
333
|
+
// caller's current preference.
|
|
334
|
+
const persisted = await resolvePersistedPreset(ctx, resumeId);
|
|
335
|
+
const composed = await composePreset(ctx, persisted);
|
|
336
|
+
const resumed = await ctx.agents.resume({
|
|
337
|
+
resumeSessionId: resumeId,
|
|
338
|
+
agentOptions: resumeOptions,
|
|
339
|
+
...(composed.setup === undefined ? {} : { setup: composed.setup }),
|
|
340
|
+
});
|
|
341
|
+
// Status-line route on resume: the route the session actually
|
|
342
|
+
// continues on — a complete cordis.yml pin, else the route its own
|
|
343
|
+
// request/header records carry (a bare log yields undefined and the
|
|
344
|
+
// caller falls back to the startup resolution, best effort).
|
|
345
|
+
return {
|
|
346
|
+
agent: resumed.agent,
|
|
347
|
+
handle: resumed,
|
|
348
|
+
agentPreset: composed.agentPreset,
|
|
349
|
+
route: resumeRoute ?? recordedModelRoute(resumed.agent.session.events),
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
catch (error) {
|
|
353
|
+
// No artifact (first run / cleared storage) or persistence not
|
|
354
|
+
// mounted: fall through to a fresh session, but stay loud in the log.
|
|
355
|
+
ctx.logger.warn(`dsh-tui: resume of "${requestedSessionId}" failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
const sessionId = SessionId(randomUUID());
|
|
359
|
+
const composed = await composePreset(ctx, configuredPreset ?? readPresetPref());
|
|
360
|
+
// Fresh-session route precedence (issues #14/#30/#67): resolved atomically
|
|
361
|
+
// by the caller (complete cordis.yml route > the persisted `/model` choice
|
|
362
|
+
// > the harness default), then validated against the adapter catalog — a
|
|
363
|
+
// stale persisted choice falls back to the default route wholesale instead
|
|
364
|
+
// of reaching the server as an unknown model name.
|
|
365
|
+
const llm = ctx.get('llm');
|
|
366
|
+
const { route, rejected } = await validateModelRoute(llm, startupRoute);
|
|
367
|
+
if (rejected !== undefined) {
|
|
368
|
+
ctx.logger.warn(`dsh-tui: model route ${rejected.provider}/${rejected.model} is not advertised by provider "${rejected.provider}"; falling back to ${route.provider}/${route.model}`);
|
|
369
|
+
}
|
|
370
|
+
const created = await ctx.agents.create({
|
|
371
|
+
sessionId,
|
|
372
|
+
meta: {
|
|
373
|
+
...meta,
|
|
374
|
+
// Durable header value: a later resume re-mounts exactly this preset.
|
|
375
|
+
...(composed.agentPreset === undefined ? {} : { agentPreset: composed.agentPreset }),
|
|
376
|
+
},
|
|
377
|
+
agentOptions: route,
|
|
378
|
+
...(composed.setup === undefined ? {} : { setup: composed.setup }),
|
|
379
|
+
}).catch((error) => {
|
|
380
|
+
// Fail loud with the reason on stderr — a dead TUI with no message is
|
|
381
|
+
// the worst outcome for a misconfigured leaf (unknown provider/model).
|
|
382
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
383
|
+
throw new Error(`dsh-tui: failed to create agent (provider=${route.provider}, model=${route.model}): ${message}`);
|
|
384
|
+
});
|
|
385
|
+
return { agent: created.agent, handle: created, agentPreset: composed.agentPreset, route };
|
|
386
|
+
}
|
|
387
|
+
/**
|
|
388
|
+
* Distinguish a user-driven exit from a cordis context teardown (issue #12).
|
|
389
|
+
*
|
|
390
|
+
* Both paths settle the Ink instance's exit promise, but only a user exit
|
|
391
|
+
* (`/exit`, double Ctrl+C, render crash) may leave the process. A teardown —
|
|
392
|
+
* the DSH launcher's boot-time recompose disposes every entry once — must
|
|
393
|
+
* only unmount the UI: the recomposed tree re-runs `apply` and mounts a
|
|
394
|
+
* fresh instance, so exiting here would kill the process mid-recompose
|
|
395
|
+
* (the "flash back to bash with no error" symptom).
|
|
396
|
+
*
|
|
397
|
+
* `markTeardown` must run before the unmount that settles the exit promise
|
|
398
|
+
* (the settle reaches `handleExit` through a microtask, so a same-tick flag
|
|
399
|
+
* is always observed). Exported for scripts/verify-teardown-exit.tsx.
|
|
400
|
+
*/
|
|
401
|
+
export function createExitFunnel(deps) {
|
|
402
|
+
let exited = false;
|
|
403
|
+
let teardown = false;
|
|
404
|
+
return {
|
|
405
|
+
markTeardown: () => {
|
|
406
|
+
teardown = true;
|
|
407
|
+
},
|
|
408
|
+
handleExit: (error) => {
|
|
409
|
+
if (teardown)
|
|
410
|
+
return;
|
|
411
|
+
if (exited)
|
|
412
|
+
return;
|
|
413
|
+
exited = true;
|
|
414
|
+
deps.onUserExit(error);
|
|
415
|
+
},
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
/**
|
|
419
|
+
* Dispose the whole application before process exit, with a bounded fallback.
|
|
420
|
+
* Mirrors the deleted dsh-tui front-door exit semantics.
|
|
421
|
+
*/
|
|
422
|
+
function disposeRootAndExit(ctx, code) {
|
|
423
|
+
disposeRootAndThen(ctx, () => process.exit(code), code);
|
|
424
|
+
}
|
|
425
|
+
/**
|
|
426
|
+
* The real way back into a session after the TUI process is gone. The
|
|
427
|
+
* package ships no `dsh-tui` bin — resuming means feeding the session id
|
|
428
|
+
* through `DSH_CC_RESUME_SESSION` (what cordis.patch.yml's `sessionId` reads)
|
|
429
|
+
* and booting the same profile; on Windows the repo's dsh-tui.cmd wrapper
|
|
430
|
+
* does this via --resume + ~/.dsh-cc/resume.txt.
|
|
431
|
+
*/
|
|
432
|
+
function resumeCommand(profile, sessionId) {
|
|
433
|
+
const boot = profile === undefined ? 'dsh --config cordis.yml' : `dsh --profile ${profile}`;
|
|
434
|
+
return process.platform === 'win32'
|
|
435
|
+
? `dsh-tui --resume ${sessionId}`
|
|
436
|
+
: `DSH_CC_RESUME_SESSION=${sessionId} ${boot}`;
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* Dispose the Cordis tree, then run a process-level handoff action. The
|
|
440
|
+
* fallback exit keeps the caller's intended code when disposal stalls — the
|
|
441
|
+
* handoff (update/restart) may legitimately take longer than the bound, and
|
|
442
|
+
* reporting failure on a clean exit would mislead wrapper scripts.
|
|
443
|
+
*/
|
|
444
|
+
function disposeRootAndThen(ctx, done, fallbackCode = 1) {
|
|
445
|
+
const timer = setTimeout(() => process.exit(fallbackCode), 5000);
|
|
446
|
+
timer.unref();
|
|
447
|
+
void ctx.root.fiber.dispose().then(() => {
|
|
448
|
+
clearTimeout(timer);
|
|
449
|
+
done();
|
|
450
|
+
}, () => {
|
|
451
|
+
clearTimeout(timer);
|
|
452
|
+
done();
|
|
453
|
+
});
|
|
454
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Persisted agent-preset preference (`/preset` picker choice), kept at
|
|
3
|
+
* `~/.dsh-cc/agent-preset.json` (`preset` key) so the choice survives
|
|
4
|
+
* restarts — same pattern as working-activity.json. The file is best-effort:
|
|
5
|
+
* a missing/corrupt file or an id the roster no longer supplies simply falls
|
|
6
|
+
* back to the roster default (`standard`). An explicit `preset` key in
|
|
7
|
+
* cordis.yml wins over this preference (deployment choice over runtime
|
|
8
|
+
* preference, matching activityFrames).
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Parse a persisted `{ preset }` value; anything else yields undefined.
|
|
12
|
+
* @param text - Raw file contents.
|
|
13
|
+
* @returns The preset id when valid, else undefined.
|
|
14
|
+
*/
|
|
15
|
+
export declare function parsePresetPref(text: string): string | undefined;
|
|
16
|
+
/**
|
|
17
|
+
* The persisted preset id, or undefined when unset or invalid.
|
|
18
|
+
* @param dir - Prefs directory (injectable for tests).
|
|
19
|
+
* @returns The persisted preset id, if any.
|
|
20
|
+
*/
|
|
21
|
+
export declare function readPresetPref(dir?: string): string | undefined;
|
|
22
|
+
/**
|
|
23
|
+
* Persist the chosen preset id (best effort).
|
|
24
|
+
* @param preset - Preset id to persist.
|
|
25
|
+
* @param dir - Prefs directory (injectable for tests).
|
|
26
|
+
* @returns True when the file was written, false on failure.
|
|
27
|
+
*/
|
|
28
|
+
export declare function writePresetPref(preset: string, dir?: string): boolean;
|
|
29
|
+
//# sourceMappingURL=presetPrefs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presetPrefs.d.ts","sourceRoot":"","sources":["../../src/presetPrefs.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAWH;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAShE;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,GAAG,GAAE,MAAkB,GAAG,MAAM,GAAG,SAAS,CAM1E;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,GAAE,MAAkB,GAAG,OAAO,CAQhF"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Persisted agent-preset preference (`/preset` picker choice), kept at
|
|
3
|
+
* `~/.dsh-cc/agent-preset.json` (`preset` key) so the choice survives
|
|
4
|
+
* restarts — same pattern as working-activity.json. The file is best-effort:
|
|
5
|
+
* a missing/corrupt file or an id the roster no longer supplies simply falls
|
|
6
|
+
* back to the roster default (`standard`). An explicit `preset` key in
|
|
7
|
+
* cordis.yml wins over this preference (deployment choice over runtime
|
|
8
|
+
* preference, matching activityFrames).
|
|
9
|
+
*/
|
|
10
|
+
import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
11
|
+
import { homedir } from 'node:os';
|
|
12
|
+
import { join } from 'node:path';
|
|
13
|
+
const PREFS_DIR = join(homedir(), '.dsh-cc');
|
|
14
|
+
/** Ids a preset directory may use (dsh-agent-presets' own boundary). */
|
|
15
|
+
const PRESET_ID = /^[a-z0-9][a-z0-9-]*$/;
|
|
16
|
+
/**
|
|
17
|
+
* Parse a persisted `{ preset }` value; anything else yields undefined.
|
|
18
|
+
* @param text - Raw file contents.
|
|
19
|
+
* @returns The preset id when valid, else undefined.
|
|
20
|
+
*/
|
|
21
|
+
export function parsePresetPref(text) {
|
|
22
|
+
try {
|
|
23
|
+
const parsed = JSON.parse(text);
|
|
24
|
+
if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed))
|
|
25
|
+
return undefined;
|
|
26
|
+
const preset = parsed.preset;
|
|
27
|
+
return typeof preset === 'string' && PRESET_ID.test(preset) ? preset : undefined;
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* The persisted preset id, or undefined when unset or invalid.
|
|
35
|
+
* @param dir - Prefs directory (injectable for tests).
|
|
36
|
+
* @returns The persisted preset id, if any.
|
|
37
|
+
*/
|
|
38
|
+
export function readPresetPref(dir = PREFS_DIR) {
|
|
39
|
+
try {
|
|
40
|
+
return parsePresetPref(readFileSync(join(dir, 'agent-preset.json'), 'utf8'));
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return undefined;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Persist the chosen preset id (best effort).
|
|
48
|
+
* @param preset - Preset id to persist.
|
|
49
|
+
* @param dir - Prefs directory (injectable for tests).
|
|
50
|
+
* @returns True when the file was written, false on failure.
|
|
51
|
+
*/
|
|
52
|
+
export function writePresetPref(preset, dir = PREFS_DIR) {
|
|
53
|
+
try {
|
|
54
|
+
mkdirSync(dir, { recursive: true });
|
|
55
|
+
writeFileSync(join(dir, 'agent-preset.json'), JSON.stringify({ preset }, null, 2));
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
}
|