@deepseek-harness-tui/dsh-tui 0.10.2 → 0.11.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 +175 -123
- package/bin/dsh-tui.js +748 -22
- package/cordis.patch.yml +42 -13
- package/cordis.yml +5 -2
- package/lib/types/activityPrefs.d.ts +24 -0
- package/lib/types/activityPrefs.d.ts.map +1 -1
- package/lib/types/activityPrefs.js +50 -1
- package/lib/types/adapter/channel/session-projection.d.ts.map +1 -1
- package/lib/types/adapter/channel/session-projection.js +2 -0
- package/lib/types/adapter/channel/state.d.ts.map +1 -1
- package/lib/types/adapter/channel/state.js +3 -1
- package/lib/types/adapter/channel/ui-policy.d.ts +4 -1
- package/lib/types/adapter/channel/ui-policy.d.ts.map +1 -1
- package/lib/types/adapter/channel/ui-policy.js +6 -2
- package/lib/types/adapter/kernel/host-facade.d.ts.map +1 -1
- package/lib/types/adapter/kernel/host-facade.js +1 -0
- package/lib/types/adapter/kernel/replay.d.ts.map +1 -1
- package/lib/types/adapter/kernel/replay.js +3 -0
- package/lib/types/adapter/kernel/runtime.d.ts.map +1 -1
- package/lib/types/adapter/kernel/runtime.js +2 -0
- package/lib/types/adapter/kernel/slices/workspace.d.ts.map +1 -1
- package/lib/types/adapter/kernel/slices/workspace.js +1 -0
- package/lib/types/adapter/ports/channel-ui.d.ts +29 -5
- package/lib/types/adapter/ports/channel-ui.d.ts.map +1 -1
- package/lib/types/adapter/ports/channel-view.d.ts +66 -12
- package/lib/types/adapter/ports/channel-view.d.ts.map +1 -1
- package/lib/types/adapter/ports/channel-workspace.d.ts +23 -0
- package/lib/types/adapter/ports/channel-workspace.d.ts.map +1 -1
- package/lib/types/adapter/ports/channel.d.ts +4 -1
- package/lib/types/adapter/ports/channel.d.ts.map +1 -1
- package/lib/types/adapter/ports/workspace.d.ts +2 -0
- package/lib/types/adapter/ports/workspace.d.ts.map +1 -1
- package/lib/types/adapter/upstream/workspace-driver.d.ts.map +1 -1
- package/lib/types/adapter/upstream/workspace-driver.js +10 -2
- package/lib/types/commands.d.ts.map +1 -1
- package/lib/types/commands.js +1 -0
- package/lib/types/components/ActivityLine.d.ts +7 -2
- package/lib/types/components/ActivityLine.d.ts.map +1 -1
- package/lib/types/components/ActivityLine.js +0 -8
- package/lib/types/components/ContextBarView.d.ts +15 -7
- package/lib/types/components/ContextBarView.d.ts.map +1 -1
- package/lib/types/components/ContextBarView.js +26 -22
- package/lib/types/components/ImagePreviewOverlay.d.ts.map +1 -1
- package/lib/types/components/ImagePreviewOverlay.js +11 -5
- package/lib/types/components/Markdown.d.ts +11 -1
- package/lib/types/components/Markdown.d.ts.map +1 -1
- package/lib/types/components/Markdown.js +20 -2
- package/lib/types/components/MermaidDiagram.d.ts +13 -0
- package/lib/types/components/MermaidDiagram.d.ts.map +1 -0
- package/lib/types/components/MermaidDiagram.js +61 -0
- package/lib/types/components/MessageList.d.ts +26 -1
- package/lib/types/components/MessageList.d.ts.map +1 -1
- package/lib/types/components/MessageList.js +74 -8
- package/lib/types/components/PageMargin.d.ts +1 -1
- package/lib/types/components/PromptInput.d.ts +37 -1
- package/lib/types/components/PromptInput.d.ts.map +1 -1
- package/lib/types/components/PromptInput.js +291 -30
- package/lib/types/components/ScrollbarGutter.d.ts +20 -5
- package/lib/types/components/ScrollbarGutter.d.ts.map +1 -1
- package/lib/types/components/ScrollbarGutter.js +88 -10
- package/lib/types/components/SplitDiffView.d.ts.map +1 -1
- package/lib/types/components/SplitDiffView.js +2 -1
- package/lib/types/components/StreamingMarkdown.d.ts.map +1 -1
- package/lib/types/components/StreamingMarkdown.js +30 -28
- package/lib/types/components/SubagentCard.d.ts.map +1 -1
- package/lib/types/components/SubagentCard.js +12 -6
- package/lib/types/components/SubagentDetailScene.d.ts.map +1 -1
- package/lib/types/components/SubagentDetailScene.js +8 -3
- package/lib/types/components/Tooltip.d.ts.map +1 -1
- package/lib/types/components/Tooltip.js +45 -7
- package/lib/types/components/design-system/HintLine.d.ts +1 -2
- package/lib/types/components/design-system/HintLine.d.ts.map +1 -1
- package/lib/types/components/design-system/HintLine.js +1 -2
- package/lib/types/components/messages/AssistantThinkingMessage.d.ts +2 -1
- package/lib/types/components/messages/AssistantThinkingMessage.d.ts.map +1 -1
- package/lib/types/components/messages/AssistantThinkingMessage.js +2 -1
- package/lib/types/components/messages/AssistantToolUseMessage.d.ts +2 -2
- package/lib/types/components/messages/AssistantToolUseMessage.d.ts.map +1 -1
- package/lib/types/components/messages/AssistantToolUseMessage.js +30 -26
- package/lib/types/components/messages/UserPromptMessage.d.ts.map +1 -1
- package/lib/types/components/messages/UserPromptMessage.js +5 -7
- package/lib/types/components/messages/useImageInspection.d.ts.map +1 -1
- package/lib/types/components/messages/useImageInspection.js +19 -9
- package/lib/types/components/promptDraftCache.d.ts +102 -0
- package/lib/types/components/promptDraftCache.d.ts.map +1 -0
- package/lib/types/components/promptDraftCache.js +76 -0
- package/lib/types/components/questions/AskUserQuestionPanel.d.ts +17 -1
- package/lib/types/components/questions/AskUserQuestionPanel.d.ts.map +1 -1
- package/lib/types/components/questions/AskUserQuestionPanel.js +40 -7
- package/lib/types/components/questions/QuestionMinimizedBar.d.ts +12 -0
- package/lib/types/components/questions/QuestionMinimizedBar.d.ts.map +1 -0
- package/lib/types/components/questions/QuestionMinimizedBar.js +43 -0
- package/lib/types/components/sessions/SessionListRow.d.ts +23 -1
- package/lib/types/components/sessions/SessionListRow.d.ts.map +1 -1
- package/lib/types/components/sessions/SessionListRow.js +52 -5
- package/lib/types/components/workspaces/HomeWorkspaceRow.d.ts +49 -0
- package/lib/types/components/workspaces/HomeWorkspaceRow.d.ts.map +1 -0
- package/lib/types/components/workspaces/HomeWorkspaceRow.js +50 -0
- package/lib/types/dsh-adapter/activity-store.d.ts +221 -0
- package/lib/types/dsh-adapter/activity-store.d.ts.map +1 -0
- package/lib/types/dsh-adapter/activity-store.js +359 -0
- package/lib/types/dsh-adapter/bundled-presets.d.ts +10 -0
- package/lib/types/dsh-adapter/bundled-presets.d.ts.map +1 -0
- package/lib/types/dsh-adapter/bundled-presets.js +80 -0
- package/lib/types/dsh-adapter/channel/action-readiness.d.ts +1 -1
- package/lib/types/dsh-adapter/channel/action-readiness.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/action-readiness.js +3 -0
- package/lib/types/dsh-adapter/channel/agent-view-projection.d.ts +1 -1
- package/lib/types/dsh-adapter/channel/agent-view-projection.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/agent-view-projection.js +19 -2
- package/lib/types/dsh-adapter/channel/background-action.d.ts +1 -1
- package/lib/types/dsh-adapter/channel/background-action.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/background-action.js +53 -29
- package/lib/types/dsh-adapter/channel/binding-events.d.ts +8 -6
- package/lib/types/dsh-adapter/channel/binding-events.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/binding-events.js +5 -4
- package/lib/types/dsh-adapter/channel/binding.d.ts +19 -2
- package/lib/types/dsh-adapter/channel/binding.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/binding.js +78 -18
- package/lib/types/dsh-adapter/channel/compaction.d.ts +0 -1
- package/lib/types/dsh-adapter/channel/compaction.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/compaction.js +0 -2
- package/lib/types/dsh-adapter/channel/composer-images.d.ts +5 -0
- package/lib/types/dsh-adapter/channel/composer-images.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/composer-images.js +105 -6
- package/lib/types/dsh-adapter/channel/context-bookkeeping.d.ts +8 -0
- package/lib/types/dsh-adapter/channel/context-bookkeeping.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/context-bookkeeping.js +3 -2
- package/lib/types/dsh-adapter/channel/ide-selection.d.ts +58 -0
- package/lib/types/dsh-adapter/channel/ide-selection.d.ts.map +1 -0
- package/lib/types/dsh-adapter/channel/ide-selection.js +226 -0
- package/lib/types/dsh-adapter/channel/input-delivery.d.ts +6 -1
- package/lib/types/dsh-adapter/channel/input-delivery.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/input-delivery.js +9 -1
- package/lib/types/dsh-adapter/channel/local-actions.d.ts +3 -19
- package/lib/types/dsh-adapter/channel/local-actions.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/local-actions.js +2 -1
- package/lib/types/dsh-adapter/channel/model-actions.d.ts +4 -1
- package/lib/types/dsh-adapter/channel/model-actions.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/model-actions.js +82 -6
- package/lib/types/dsh-adapter/channel/model-switch.d.ts +1 -2
- package/lib/types/dsh-adapter/channel/model-switch.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/model-switch.js +49 -31
- package/lib/types/dsh-adapter/channel/projection.d.ts +4 -0
- package/lib/types/dsh-adapter/channel/projection.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/projection.js +29 -19
- package/lib/types/dsh-adapter/channel/reports.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/reports.js +4 -12
- package/lib/types/dsh-adapter/channel/session-adoption.d.ts +1 -1
- package/lib/types/dsh-adapter/channel/session-adoption.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/session-adoption.js +1 -0
- package/lib/types/dsh-adapter/channel/session-fork.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/session-fork.js +26 -2
- package/lib/types/dsh-adapter/channel/session-live-adoption.d.ts +4 -1
- package/lib/types/dsh-adapter/channel/session-live-adoption.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/session-live-adoption.js +2 -0
- package/lib/types/dsh-adapter/channel/session-metadata.d.ts +10 -0
- package/lib/types/dsh-adapter/channel/session-metadata.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/session-metadata.js +6 -4
- package/lib/types/dsh-adapter/channel/session-reset.d.ts +1 -1
- package/lib/types/dsh-adapter/channel/session-reset.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/session-reset.js +0 -1
- package/lib/types/dsh-adapter/channel/session-resume.d.ts +12 -3
- package/lib/types/dsh-adapter/channel/session-resume.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/session-resume.js +292 -94
- package/lib/types/dsh-adapter/channel/session-rewind.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/session-rewind.js +34 -16
- package/lib/types/dsh-adapter/channel/session-tree-actions.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/session-tree-actions.js +19 -3
- package/lib/types/dsh-adapter/channel/settings-host.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/settings-host.js +4 -3
- package/lib/types/dsh-adapter/channel/state.d.ts +6 -1
- package/lib/types/dsh-adapter/channel/state.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/state.js +3 -3
- package/lib/types/dsh-adapter/channel/subagent-projection.d.ts +21 -1
- package/lib/types/dsh-adapter/channel/subagent-projection.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/subagent-projection.js +173 -6
- package/lib/types/dsh-adapter/channel/transcript.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/transcript.js +6 -12
- package/lib/types/dsh-adapter/channel/types.d.ts +6 -1
- package/lib/types/dsh-adapter/channel/types.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/workspace-actions.d.ts +4 -1
- package/lib/types/dsh-adapter/channel/workspace-actions.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/workspace-actions.js +41 -1
- package/lib/types/dsh-adapter/channel.d.ts +1 -1
- package/lib/types/dsh-adapter/channel.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel.js +82 -20
- package/lib/types/dsh-adapter/compat/index.d.ts +1 -1
- package/lib/types/dsh-adapter/compat/index.d.ts.map +1 -1
- package/lib/types/dsh-adapter/compat/index.js +1 -1
- package/lib/types/dsh-adapter/compat/messages.d.ts +15 -0
- package/lib/types/dsh-adapter/compat/messages.d.ts.map +1 -0
- package/lib/types/dsh-adapter/compat/messages.js +15 -0
- package/lib/types/dsh-adapter/compat/sessionLog.d.ts +18 -0
- package/lib/types/dsh-adapter/compat/sessionLog.d.ts.map +1 -1
- package/lib/types/dsh-adapter/compat/sessionLog.js +18 -3
- package/lib/types/dsh-adapter/compat/settings.d.ts +35 -0
- package/lib/types/dsh-adapter/compat/settings.d.ts.map +1 -0
- package/lib/types/dsh-adapter/compat/settings.js +57 -0
- package/lib/types/dsh-adapter/compat/shell.d.ts +25 -0
- package/lib/types/dsh-adapter/compat/shell.d.ts.map +1 -0
- package/lib/types/dsh-adapter/compat/shell.js +11 -0
- package/lib/types/dsh-adapter/contract.d.ts +5 -4
- package/lib/types/dsh-adapter/contract.d.ts.map +1 -1
- package/lib/types/dsh-adapter/contract.js +17 -6
- package/lib/types/dsh-adapter/ide-channel.d.ts +224 -0
- package/lib/types/dsh-adapter/ide-channel.d.ts.map +1 -0
- package/lib/types/dsh-adapter/ide-channel.js +556 -0
- package/lib/types/dsh-adapter/index.d.ts +18 -3
- package/lib/types/dsh-adapter/index.d.ts.map +1 -1
- package/lib/types/dsh-adapter/index.js +32 -5
- package/lib/types/dsh-adapter/plugin.d.ts +4 -1
- package/lib/types/dsh-adapter/plugin.d.ts.map +1 -1
- package/lib/types/dsh-adapter/plugin.js +197 -49
- package/lib/types/dsh-adapter/preset-resolution.d.ts +8 -0
- package/lib/types/dsh-adapter/preset-resolution.d.ts.map +1 -1
- package/lib/types/dsh-adapter/preset-resolution.js +10 -0
- package/lib/types/dsh-adapter/session-mount-heartbeat.d.ts +53 -0
- package/lib/types/dsh-adapter/session-mount-heartbeat.d.ts.map +1 -0
- package/lib/types/dsh-adapter/session-mount-heartbeat.js +100 -0
- package/lib/types/dsh-adapter/sessionTree.d.ts.map +1 -1
- package/lib/types/dsh-adapter/sessionTree.js +3 -2
- package/lib/types/dsh-adapter/settings-sections.d.ts.map +1 -1
- package/lib/types/dsh-adapter/settings-sections.js +7 -4
- package/lib/types/dsh-adapter/subagents.d.ts +16 -3
- package/lib/types/dsh-adapter/subagents.d.ts.map +1 -1
- package/lib/types/dsh-adapter/subagents.js +92 -29
- package/lib/types/dsh-adapter/workspaces.d.ts +46 -3
- package/lib/types/dsh-adapter/workspaces.d.ts.map +1 -1
- package/lib/types/dsh-adapter/workspaces.js +116 -0
- package/lib/types/effortPrefs.d.ts +15 -3
- package/lib/types/effortPrefs.d.ts.map +1 -1
- package/lib/types/effortPrefs.js +37 -3
- package/lib/types/history.d.ts +13 -1
- package/lib/types/history.d.ts.map +1 -1
- package/lib/types/history.js +15 -2
- package/lib/types/homePrefs.d.ts +15 -0
- package/lib/types/homePrefs.d.ts.map +1 -0
- package/lib/types/homePrefs.js +53 -0
- package/lib/types/i18n.d.ts +347 -297
- package/lib/types/i18n.d.ts.map +1 -1
- package/lib/types/i18n.js +133 -85
- package/lib/types/ink/colorize.d.ts +10 -0
- package/lib/types/ink/colorize.d.ts.map +1 -1
- package/lib/types/ink/colorize.js +21 -0
- package/lib/types/ink/components/ScrollBox.d.ts.map +1 -1
- package/lib/types/ink/components/ScrollBox.js +12 -1
- package/lib/types/ink/dom.d.ts +1 -0
- package/lib/types/ink/dom.d.ts.map +1 -1
- package/lib/types/ink/hooks/use-copy-on-select.d.ts +5 -1
- package/lib/types/ink/hooks/use-copy-on-select.d.ts.map +1 -1
- package/lib/types/ink/hooks/use-copy-on-select.js +15 -1
- package/lib/types/ink/ink.d.ts.map +1 -1
- package/lib/types/ink/ink.js +36 -1
- package/lib/types/ink/log-update.d.ts.map +1 -1
- package/lib/types/ink/log-update.js +19 -1
- package/lib/types/ink/output.d.ts +10 -1
- package/lib/types/ink/output.d.ts.map +1 -1
- package/lib/types/ink/output.js +109 -17
- package/lib/types/ink/render-border.d.ts +6 -1
- package/lib/types/ink/render-border.d.ts.map +1 -1
- package/lib/types/ink/render-border.js +25 -9
- package/lib/types/ink/render-node-to-output.d.ts.map +1 -1
- package/lib/types/ink/render-node-to-output.js +48 -6
- package/lib/types/ink/renderer.d.ts +6 -0
- package/lib/types/ink/renderer.d.ts.map +1 -1
- package/lib/types/ink/renderer.js +2 -1
- package/lib/types/ink/selection.d.ts +88 -0
- package/lib/types/ink/selection.d.ts.map +1 -1
- package/lib/types/ink/selection.js +164 -0
- package/lib/types/ink/sixel-graphics.d.ts +19 -1
- package/lib/types/ink/sixel-graphics.d.ts.map +1 -1
- package/lib/types/ink/sixel-graphics.js +124 -12
- package/lib/types/ink/terminal-image.d.ts +18 -1
- package/lib/types/ink/terminal-image.d.ts.map +1 -1
- package/lib/types/ink/terminal.d.ts +17 -0
- package/lib/types/ink/terminal.d.ts.map +1 -1
- package/lib/types/ink/terminal.js +20 -1
- package/lib/types/screens/Chat.d.ts +20 -1
- package/lib/types/screens/Chat.d.ts.map +1 -1
- package/lib/types/screens/Chat.js +296 -76
- package/lib/types/screens/SessionSupervisor.d.ts +84 -0
- package/lib/types/screens/SessionSupervisor.d.ts.map +1 -0
- package/lib/types/screens/SessionSupervisor.js +350 -0
- package/lib/types/screens/SessionTree.js +2 -2
- package/lib/types/screens/Settings.d.ts.map +1 -1
- package/lib/types/screens/Settings.js +32 -9
- package/lib/types/screens/StatusLine.d.ts +18 -1
- package/lib/types/screens/StatusLine.d.ts.map +1 -1
- package/lib/types/screens/StatusLine.js +38 -19
- package/lib/types/screens/StatusMetrics.d.ts +79 -22
- package/lib/types/screens/StatusMetrics.d.ts.map +1 -1
- package/lib/types/screens/StatusMetrics.js +153 -88
- package/lib/types/screens/sessionSupervisor/model.d.ts +83 -0
- package/lib/types/screens/sessionSupervisor/model.d.ts.map +1 -0
- package/lib/types/screens/sessionSupervisor/model.js +69 -0
- package/lib/types/screens/sessionSupervisor/useSessionSupervisor.d.ts +120 -0
- package/lib/types/screens/sessionSupervisor/useSessionSupervisor.d.ts.map +1 -0
- package/lib/types/screens/sessionSupervisor/useSessionSupervisor.js +593 -0
- package/lib/types/sessionMounts.d.ts +272 -0
- package/lib/types/sessionMounts.d.ts.map +1 -0
- package/lib/types/sessionMounts.js +706 -0
- package/lib/types/sessions/format.d.ts.map +1 -1
- package/lib/types/sessions/format.js +4 -1
- package/lib/types/sessions/resumeFailure.d.ts +38 -0
- package/lib/types/sessions/resumeFailure.d.ts.map +1 -0
- package/lib/types/sessions/resumeFailure.js +58 -0
- package/lib/types/terminal-utils/mermaid.d.ts +44 -0
- package/lib/types/terminal-utils/mermaid.d.ts.map +1 -0
- package/lib/types/terminal-utils/mermaid.js +83 -0
- package/lib/types/tips.d.ts.map +1 -1
- package/lib/types/tips.js +175 -19
- package/lib/types/tuiDisplayPrefs.d.ts +7 -9
- package/lib/types/tuiDisplayPrefs.d.ts.map +1 -1
- package/lib/types/tuiDisplayPrefs.js +31 -28
- package/lib/types/update.d.ts +61 -0
- package/lib/types/update.d.ts.map +1 -1
- package/lib/types/update.js +194 -0
- package/lib/types/utils/fold-long-lines.d.ts +1 -1
- package/lib/types/utils/fold-long-lines.js +1 -1
- package/lib/types/utils/imageResize.d.ts +90 -0
- package/lib/types/utils/imageResize.d.ts.map +1 -0
- package/lib/types/utils/imageResize.js +272 -0
- package/lib/types/utils/keymap.d.ts +5 -1
- package/lib/types/utils/keymap.d.ts.map +1 -1
- package/lib/types/utils/keymap.js +23 -0
- package/lib/types/working-activity.d.ts +10 -9
- package/lib/types/working-activity.d.ts.map +1 -1
- package/lib/types/working-activity.js +17 -10
- package/lib/types/workspaces.d.ts +2 -1
- package/lib/types/workspaces.d.ts.map +1 -1
- package/lib/types/workspaces.js +1 -1
- package/node_modules/@deepseek-harness-tui/dsh-auth/package.json +10 -10
- package/package.json +126 -105
- package/presets/liangshen/.dsh-tui-managed.json +1 -1
- package/presets/liangshen/agent.cordis.yml +15 -0
- package/lib/types/components/design-system/KeyboardShortcutHint.d.ts +0 -19
- package/lib/types/components/design-system/KeyboardShortcutHint.d.ts.map +0 -1
- package/lib/types/components/design-system/KeyboardShortcutHint.js +0 -14
- package/lib/types/dsh-adapter/channel/activity.d.ts +0 -20
- package/lib/types/dsh-adapter/channel/activity.d.ts.map +0 -1
- package/lib/types/dsh-adapter/channel/activity.js +0 -113
- package/lib/types/screens/AgentView.d.ts +0 -23
- package/lib/types/screens/AgentView.d.ts.map +0 -1
- package/lib/types/screens/AgentView.js +0 -546
- package/lib/types/screens/SessionBrowser.d.ts +0 -42
- package/lib/types/screens/SessionBrowser.d.ts.map +0 -1
- package/lib/types/screens/SessionBrowser.js +0 -911
- package/lib/types/terminal-utils/terminal.d.ts +0 -18
- package/lib/types/terminal-utils/terminal.d.ts.map +0 -1
- package/lib/types/terminal-utils/terminal.js +0 -96
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { ChannelSelection, SelectionAttachment } from '../../adapter/ports/channel-view.js';
|
|
2
|
+
import type { MentionExpansion, MentionFs } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Escape a path for reuse inside a quoted `<attached-file path="…">` attribute:
|
|
5
|
+
* POSIX filenames are legal with `"`, `&`, `<`, `>` — a raw interpolated path
|
|
6
|
+
* could break out of the attribute or smuggle markup into the model-facing
|
|
7
|
+
* block. `&` first so the replacements themselves are not re-escaped.
|
|
8
|
+
*/
|
|
9
|
+
export declare function escapeSnippetAttr(value: string): string;
|
|
10
|
+
/**
|
|
11
|
+
* Build the `<attached-file path="…" selection>` block for an IDE selection:
|
|
12
|
+
* coordinates arrive 0-based inclusive from the extension and convert to
|
|
13
|
+
* sliceLines' 1-based; an endLine past EOF clamps to the last line (the model
|
|
14
|
+
* receives every remaining line), while a startLine past EOF yields undefined
|
|
15
|
+
* — the caller silently skips instead of attaching an empty or stale block.
|
|
16
|
+
* An empty selection is rejected here too so the guard cannot be bypassed.
|
|
17
|
+
*/
|
|
18
|
+
export declare function buildSelectionBlock(selection: ChannelSelection, content: string): {
|
|
19
|
+
text: string;
|
|
20
|
+
lines: number;
|
|
21
|
+
} | undefined;
|
|
22
|
+
/**
|
|
23
|
+
* Append the selection's attached-file block to a message's content. Returns
|
|
24
|
+
* what was attached ({lines, path}) or undefined when there is nothing to
|
|
25
|
+
* attach — no selection, or an unresolvable/unreadable file. The caller
|
|
26
|
+
* passes the ENQUEUE-time snapshot (and its fs handle) so a selection made
|
|
27
|
+
* after submit can never attach to the wrong message.
|
|
28
|
+
*
|
|
29
|
+
* Protocol 2 carries the editor buffer's own `text` (unsaved edits
|
|
30
|
+
* included): when present it is attached VERBATIM and the filesystem is not
|
|
31
|
+
* touched — reading the disk copy would hand the model a version the user
|
|
32
|
+
* never saw (maintainer review round 3). The disk read remains only as the
|
|
33
|
+
* protocol-1 fallback.
|
|
34
|
+
*/
|
|
35
|
+
export declare function attachIdeSelection(blocks: MentionExpansion['blocks'], cwd: string, selection: ChannelSelection | undefined, fs: MentionFs | undefined): Promise<SelectionAttachment | undefined>;
|
|
36
|
+
/**
|
|
37
|
+
* Derive the transcript indicator from the DURABLE user-message content:
|
|
38
|
+
* the `<attached-file path="…" selection count="N">` block the submit path
|
|
39
|
+
* appended is part of the persisted event, so a replayed session can rebuild
|
|
40
|
+
* the "Selected N lines from <file>" line even though the in-memory
|
|
41
|
+
* message-id → attachment map starts empty (maintainer review round 3: the
|
|
42
|
+
* session log is the source of truth — the indicator must not depend on
|
|
43
|
+
* process-local state).
|
|
44
|
+
*/
|
|
45
|
+
export declare function replaySelectionAttachment(content: readonly unknown[] | undefined): SelectionAttachment | undefined;
|
|
46
|
+
/**
|
|
47
|
+
* Bounded map from a submitted message id → what its selection attached.
|
|
48
|
+
* The delivery path remembers at submit; the transcript projection reads it
|
|
49
|
+
* when the durable `user/message` event lands (the event carries the same
|
|
50
|
+
* message id) to stamp the row's indicator. FIFO-capped like the other
|
|
51
|
+
* row-keyed caches — ids grow monotonically and a miss only loses the
|
|
52
|
+
* indicator, never the attachment itself.
|
|
53
|
+
*/
|
|
54
|
+
export declare function createSelectionAttachments(): {
|
|
55
|
+
remember(messageId: string, info: SelectionAttachment): void;
|
|
56
|
+
take(messageId: string): SelectionAttachment | undefined;
|
|
57
|
+
};
|
|
58
|
+
//# sourceMappingURL=ide-selection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ide-selection.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/channel/ide-selection.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAA;AAEhG,OAAO,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAuB7D;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEvD;AAyCD;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,gBAAgB,EAC3B,OAAO,EAAE,MAAM,GACd;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAc7C;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,gBAAgB,CAAC,QAAQ,CAAC,EAClC,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,gBAAgB,GAAG,SAAS,EACvC,EAAE,EAAE,SAAS,GAAG,SAAS,GACxB,OAAO,CAAC,mBAAmB,GAAG,SAAS,CAAC,CAoC1C;AAED;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,SAAS,OAAO,EAAE,GAAG,SAAS,GACtC,mBAAmB,GAAG,SAAS,CA8BjC;AAED;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,IAAI;IAC5C,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,mBAAmB,GAAG,IAAI,CAAA;IAC5D,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,mBAAmB,GAAG,SAAS,CAAA;CACzD,CAeA"}
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* IDE selection consumption: turn a live editor-selection snapshot into the
|
|
3
|
+
* model-facing `<attached-file … selection>` block. Protocol 2 pushes carry
|
|
4
|
+
* the editor buffer's own selection text — that is attached verbatim; the
|
|
5
|
+
* disk read below remains only as the protocol-1 fallback, and every failure
|
|
6
|
+
* mode is silent (an IDE-side extra must never block a send).
|
|
7
|
+
*
|
|
8
|
+
* The block builder never goes through text parsing (unlike `@`-mentions):
|
|
9
|
+
* selection paths may contain spaces no tokenizer could survive. It reuses
|
|
10
|
+
* the same line-slice semantics and size-cap policy as mention attachments.
|
|
11
|
+
*/
|
|
12
|
+
import { isAbsolute, join } from 'node:path';
|
|
13
|
+
import { MENTION_MAX_FILE_CHARS } from './mentions.js';
|
|
14
|
+
/**
|
|
15
|
+
* Slice `content` into the 1-based inclusive [`startLine`, `endLine`] range.
|
|
16
|
+
* Returns undefined for malformed ranges (non-safe integers, zero/negative
|
|
17
|
+
* start, inverted) and for a start past EOF — counted against REAL lines: a
|
|
18
|
+
* trailing newline splits into a phantom final element that is not a line.
|
|
19
|
+
*/
|
|
20
|
+
function sliceLines(content, startLine, endLine) {
|
|
21
|
+
const end = endLine ?? startLine;
|
|
22
|
+
if (!Number.isSafeInteger(startLine) || startLine < 1)
|
|
23
|
+
return undefined;
|
|
24
|
+
if (!Number.isSafeInteger(end) || end < startLine)
|
|
25
|
+
return undefined;
|
|
26
|
+
const lines = content.split('\n');
|
|
27
|
+
// A trailing newline splits into a phantom final element that is not a line.
|
|
28
|
+
if (lines.length > 1 && lines[lines.length - 1] === '')
|
|
29
|
+
lines.pop();
|
|
30
|
+
if (startLine > lines.length)
|
|
31
|
+
return undefined;
|
|
32
|
+
return lines.slice(startLine - 1, end).join('\n');
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Escape a path for reuse inside a quoted `<attached-file path="…">` attribute:
|
|
36
|
+
* POSIX filenames are legal with `"`, `&`, `<`, `>` — a raw interpolated path
|
|
37
|
+
* could break out of the attribute or smuggle markup into the model-facing
|
|
38
|
+
* block. `&` first so the replacements themselves are not re-escaped.
|
|
39
|
+
*/
|
|
40
|
+
export function escapeSnippetAttr(value) {
|
|
41
|
+
return value.replace(/&/g, '&').replace(/"/g, '"').replace(/</g, '<').replace(/>/g, '>');
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Format the attached-file block from an ALREADY-SLICED body: cap it like
|
|
45
|
+
* @-mention attachments (same MENTION_MAX_FILE_CHARS policy, same visible
|
|
46
|
+
* truncation marker) and count the lines the model gets — the truncated body,
|
|
47
|
+
* not the request (review round 3).
|
|
48
|
+
*
|
|
49
|
+
* `allowEmpty` keeps a selection that covers ONE blank line: the body is
|
|
50
|
+
* legitimately empty there while the badge still says "1 line selected", and
|
|
51
|
+
* dropping the block made the footer and the transcript disagree (review
|
|
52
|
+
* round 7). Callers pass it only for a single-line range that really exists.
|
|
53
|
+
*/
|
|
54
|
+
function cappedSelectionBlock(path, sliced, allowEmpty = false) {
|
|
55
|
+
if (sliced === '' && !allowEmpty)
|
|
56
|
+
return undefined;
|
|
57
|
+
let body = sliced;
|
|
58
|
+
let attached = sliced;
|
|
59
|
+
if (body.length > MENTION_MAX_FILE_CHARS) {
|
|
60
|
+
attached = body.slice(0, MENTION_MAX_FILE_CHARS);
|
|
61
|
+
body = `${attached}\n[… truncated]`;
|
|
62
|
+
}
|
|
63
|
+
// `count` is the number of lines in the attached BODY — the truncation
|
|
64
|
+
// marker line is not counted (it rides on top of the cap and the live
|
|
65
|
+
// indicator reports the same number). It exists so the replay path never has
|
|
66
|
+
// to GUESS that number from the body tail: a selection whose last line is
|
|
67
|
+
// literally `[… truncated]` used to lose one line when the indicator was
|
|
68
|
+
// rebuilt from the persisted event (fuzz rounds found 46/400 such bodies).
|
|
69
|
+
// Deliberately NOT `lines`: @-mention attachments already use `lines="2-4"`
|
|
70
|
+
// for the REQUESTED range, and overloading the key with a count would make
|
|
71
|
+
// the two block flavours read alike.
|
|
72
|
+
const lines = attached.split('\n').length;
|
|
73
|
+
return {
|
|
74
|
+
text: `<attached-file path="${escapeSnippetAttr(path)}" selection count="${lines}">\n${body}\n</attached-file>`,
|
|
75
|
+
lines,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Build the `<attached-file path="…" selection>` block for an IDE selection:
|
|
80
|
+
* coordinates arrive 0-based inclusive from the extension and convert to
|
|
81
|
+
* sliceLines' 1-based; an endLine past EOF clamps to the last line (the model
|
|
82
|
+
* receives every remaining line), while a startLine past EOF yields undefined
|
|
83
|
+
* — the caller silently skips instead of attaching an empty or stale block.
|
|
84
|
+
* An empty selection is rejected here too so the guard cannot be bypassed.
|
|
85
|
+
*/
|
|
86
|
+
export function buildSelectionBlock(selection, content) {
|
|
87
|
+
if (selection.isEmpty)
|
|
88
|
+
return undefined;
|
|
89
|
+
// 0-based inclusive [start, end] → 1-based inclusive [start+1, end+1].
|
|
90
|
+
// sliceLines clamps an oversized end itself (Array#slice bounds); a start
|
|
91
|
+
// past EOF returns undefined and the whole attach is silently dropped.
|
|
92
|
+
const sliced = sliceLines(content, selection.startLine + 1, selection.endLine + 1);
|
|
93
|
+
if (sliced === undefined)
|
|
94
|
+
return undefined;
|
|
95
|
+
// sliceLines returning '' (not undefined) means the requested line EXISTS and
|
|
96
|
+
// is blank — a single blank line is a real selection the badge reports.
|
|
97
|
+
return cappedSelectionBlock(selection.path, sliced, selection.startLine === selection.endLine);
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Append the selection's attached-file block to a message's content. Returns
|
|
101
|
+
* what was attached ({lines, path}) or undefined when there is nothing to
|
|
102
|
+
* attach — no selection, or an unresolvable/unreadable file. The caller
|
|
103
|
+
* passes the ENQUEUE-time snapshot (and its fs handle) so a selection made
|
|
104
|
+
* after submit can never attach to the wrong message.
|
|
105
|
+
*
|
|
106
|
+
* Protocol 2 carries the editor buffer's own `text` (unsaved edits
|
|
107
|
+
* included): when present it is attached VERBATIM and the filesystem is not
|
|
108
|
+
* touched — reading the disk copy would hand the model a version the user
|
|
109
|
+
* never saw (maintainer review round 3). The disk read remains only as the
|
|
110
|
+
* protocol-1 fallback.
|
|
111
|
+
*/
|
|
112
|
+
export async function attachIdeSelection(blocks, cwd, selection, fs) {
|
|
113
|
+
if (selection === undefined || selection.isEmpty)
|
|
114
|
+
return undefined;
|
|
115
|
+
if (selection.text !== undefined) {
|
|
116
|
+
// Protocol 2: `text` is the editor's OWN text for the selection
|
|
117
|
+
// (document.getText(selection)) — the ABSOLUTE document coordinates ride
|
|
118
|
+
// along for the badge/indicator, but they must NOT slice this string:
|
|
119
|
+
// it already contains exactly the selected lines, so anything not
|
|
120
|
+
// starting at line 0 would be mis-cut or dropped entirely (review
|
|
121
|
+
// round 4). Attach it verbatim with the shared size cap. A full-line
|
|
122
|
+
// selection ends at column 0 of the NEXT line, so getText hands back a
|
|
123
|
+
// trailing '\n' — strip that one terminator or the body grows a phantom
|
|
124
|
+
// blank line and the indicator over-counts by one (review round 5).
|
|
125
|
+
let text = selection.text;
|
|
126
|
+
if (text.endsWith('\n'))
|
|
127
|
+
text = text.slice(0, -1);
|
|
128
|
+
// Triple-clicking ONE blank line hands back "\n": after the strip the body
|
|
129
|
+
// is empty but a line WAS selected (the footer badge says so) — keep the
|
|
130
|
+
// block so the indicator and the badge agree instead of attaching nothing.
|
|
131
|
+
const block = cappedSelectionBlock(selection.path, text, selection.text !== '');
|
|
132
|
+
if (block === undefined)
|
|
133
|
+
return undefined;
|
|
134
|
+
blocks.push({ type: 'text', text: block.text });
|
|
135
|
+
return { lines: block.lines, path: selection.path };
|
|
136
|
+
}
|
|
137
|
+
if (fs === undefined)
|
|
138
|
+
return undefined;
|
|
139
|
+
try {
|
|
140
|
+
const absolute = isAbsolute(selection.path) ? selection.path : join(cwd, selection.path);
|
|
141
|
+
const target = await fs.resolve(absolute);
|
|
142
|
+
const info = await fs.stat(target);
|
|
143
|
+
if (info?.type !== 'file')
|
|
144
|
+
return undefined;
|
|
145
|
+
const content = await fs.readText(target);
|
|
146
|
+
const block = buildSelectionBlock(selection, content);
|
|
147
|
+
if (block === undefined)
|
|
148
|
+
return undefined;
|
|
149
|
+
blocks.push({ type: 'text', text: block.text });
|
|
150
|
+
return { lines: block.lines, path: selection.path };
|
|
151
|
+
}
|
|
152
|
+
catch {
|
|
153
|
+
return undefined;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Derive the transcript indicator from the DURABLE user-message content:
|
|
158
|
+
* the `<attached-file path="…" selection count="N">` block the submit path
|
|
159
|
+
* appended is part of the persisted event, so a replayed session can rebuild
|
|
160
|
+
* the "Selected N lines from <file>" line even though the in-memory
|
|
161
|
+
* message-id → attachment map starts empty (maintainer review round 3: the
|
|
162
|
+
* session log is the source of truth — the indicator must not depend on
|
|
163
|
+
* process-local state).
|
|
164
|
+
*/
|
|
165
|
+
export function replaySelectionAttachment(content) {
|
|
166
|
+
if (content === undefined)
|
|
167
|
+
return undefined;
|
|
168
|
+
for (const block of content) {
|
|
169
|
+
if (block === null || typeof block !== 'object')
|
|
170
|
+
continue;
|
|
171
|
+
const text = block.text;
|
|
172
|
+
if (block.type !== 'text' || typeof text !== 'string')
|
|
173
|
+
continue;
|
|
174
|
+
const opened = /^<attached-file path="([^"]+)" selection(?: count="(\d+)")?>\n/.exec(text);
|
|
175
|
+
if (opened === null)
|
|
176
|
+
continue;
|
|
177
|
+
let closed = text.slice(opened[0].length);
|
|
178
|
+
if (closed.endsWith('</attached-file>'))
|
|
179
|
+
closed = closed.slice(0, -'</attached-file>'.length);
|
|
180
|
+
// The builder writes `body\n</attached-file>` — strip the newline the
|
|
181
|
+
// close tag rode on, or every body counts one phantom line.
|
|
182
|
+
if (closed.endsWith('\n'))
|
|
183
|
+
closed = closed.slice(0, -1);
|
|
184
|
+
const lines = closed.split('\n').length;
|
|
185
|
+
// `count` is authoritative when present (the builder always writes it).
|
|
186
|
+
// Blocks persisted before it existed fall back to the old tail heuristic,
|
|
187
|
+
// which misreads a body whose last line is literally the truncation marker.
|
|
188
|
+
const counted = opened[2] === undefined ? undefined : Number(opened[2]);
|
|
189
|
+
return {
|
|
190
|
+
lines: counted ?? (closed.endsWith('\n[… truncated]') ? lines - 1 : lines),
|
|
191
|
+
// Reverse escapeSnippetAttr so the replayed indicator shows the path
|
|
192
|
+
// exactly as the live one did (`&` first so entities are not re-baked).
|
|
193
|
+
path: opened[1]
|
|
194
|
+
.replace(/</g, '<')
|
|
195
|
+
.replace(/>/g, '>')
|
|
196
|
+
.replace(/"/g, '"')
|
|
197
|
+
.replace(/&/g, '&'),
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
return undefined;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Bounded map from a submitted message id → what its selection attached.
|
|
204
|
+
* The delivery path remembers at submit; the transcript projection reads it
|
|
205
|
+
* when the durable `user/message` event lands (the event carries the same
|
|
206
|
+
* message id) to stamp the row's indicator. FIFO-capped like the other
|
|
207
|
+
* row-keyed caches — ids grow monotonically and a miss only loses the
|
|
208
|
+
* indicator, never the attachment itself.
|
|
209
|
+
*/
|
|
210
|
+
export function createSelectionAttachments() {
|
|
211
|
+
const byMessageId = new Map();
|
|
212
|
+
return {
|
|
213
|
+
remember(messageId, info) {
|
|
214
|
+
byMessageId.set(messageId, info);
|
|
215
|
+
while (byMessageId.size > 128) {
|
|
216
|
+
const oldest = byMessageId.keys().next().value;
|
|
217
|
+
if (oldest === undefined)
|
|
218
|
+
break;
|
|
219
|
+
byMessageId.delete(oldest);
|
|
220
|
+
}
|
|
221
|
+
},
|
|
222
|
+
take(messageId) {
|
|
223
|
+
return byMessageId.get(messageId);
|
|
224
|
+
},
|
|
225
|
+
};
|
|
226
|
+
}
|
|
@@ -3,6 +3,7 @@ import type { Agent } from '@deepseek-ai/dsh-agent';
|
|
|
3
3
|
import { type UserMessage } from '@deepseek-ai/dsh-llm';
|
|
4
4
|
import { type ComposerImages } from './composer-images.js';
|
|
5
5
|
import type { ChannelOwner } from './owner.js';
|
|
6
|
+
import type { ChannelSelection, SelectionAttachment } from '../../adapter/ports/channel-view.js';
|
|
6
7
|
import type { ChannelImageBlock, ChannelState, ComposerImageRef, MentionAttachments, MentionFs, PendingMessage, StagedImageInput } from './types.js';
|
|
7
8
|
/** One submission's enqueue-time world: the session it was typed in, the
|
|
8
9
|
* services that resolve its references, and the capabilities live then. */
|
|
@@ -14,6 +15,10 @@ interface UserTextOrigin {
|
|
|
14
15
|
readonly fs: MentionFs | undefined;
|
|
15
16
|
readonly attachments: MentionAttachments | undefined;
|
|
16
17
|
readonly stagedImages: ReadonlyMap<string, ChannelImageBlock['attachment']>;
|
|
18
|
+
/** Live editor selection AT ENQUEUE (undefined = none). Captured here so a
|
|
19
|
+
* selection made while the FIFO or mention expansion parks the delivery
|
|
20
|
+
* can never attach to this message. */
|
|
21
|
+
readonly selection: ChannelSelection | undefined;
|
|
17
22
|
}
|
|
18
23
|
/** Input FIFO, staged attachments and decision notice timers share one lifetime. */
|
|
19
24
|
export declare function createInputDelivery(ctx: Context, owner: ChannelOwner, binding: {
|
|
@@ -22,7 +27,7 @@ export declare function createInputDelivery(ctx: Context, owner: ChannelOwner, b
|
|
|
22
27
|
id: string;
|
|
23
28
|
text: string;
|
|
24
29
|
images?: readonly ComposerImageRef[];
|
|
25
|
-
}, placement: PendingMessage['placement']) => void, untrackPending: (id: string) => void, composer: ComposerImages): {
|
|
30
|
+
}, placement: PendingMessage['placement']) => void, untrackPending: (id: string) => void, composer: ComposerImages, selection: () => ChannelSelection | undefined, rememberSelection: (messageId: string, info: SelectionAttachment) => void): {
|
|
26
31
|
dispatchUserText: (text: string, placement: PendingMessage["placement"], images?: readonly ComposerImageRef[], attach?: UserMessage) => void;
|
|
27
32
|
deliverUserText: (text: string, placement: PendingMessage["placement"], images?: readonly ComposerImageRef[], attach?: UserMessage) => void;
|
|
28
33
|
claimAttachments: (messages: readonly UserMessage[]) => UserMessage[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"input-delivery.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/channel/input-delivery.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAA;AACnD,OAAO,EAAqB,KAAK,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAI1E,OAAO,EAIL,KAAK,cAAc,EACpB,MAAM,sBAAsB,CAAA;
|
|
1
|
+
{"version":3,"file":"input-delivery.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/channel/input-delivery.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAA;AACnD,OAAO,EAAqB,KAAK,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAI1E,OAAO,EAIL,KAAK,cAAc,EACpB,MAAM,sBAAsB,CAAA;AAK7B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAC9C,OAAO,KAAK,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAA;AAChG,OAAO,KAAK,EACV,iBAAiB,EACjB,YAAY,EACZ,gBAAgB,EAChB,kBAAkB,EAClB,SAAS,EACT,cAAc,EACd,gBAAgB,EACjB,MAAM,YAAY,CAAA;AAEnB;4EAC4E;AAC5E,UAAU,cAAc;IACtB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,EAAE,SAAS,GAAG,SAAS,CAAA;IAClC,QAAQ,CAAC,WAAW,EAAE,kBAAkB,GAAG,SAAS,CAAA;IACpD,QAAQ,CAAC,YAAY,EAAE,WAAW,CAAC,MAAM,EAAE,iBAAiB,CAAC,YAAY,CAAC,CAAC,CAAA;IAC3E;;4CAEwC;IACxC,QAAQ,CAAC,SAAS,EAAE,gBAAgB,GAAG,SAAS,CAAA;CACjD;AAED,oFAAoF;AACpF,wBAAgB,mBAAmB,CAClC,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE;IAAE,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;CAAE,EACrE,KAAK,EAAE,MAAM,IAAI,CAAC,YAAY,EAAE,KAAK,GAAG,SAAS,GAAG,wBAAwB,CAAC,EAC7E,MAAM,EAAE,YAAY,CAAC,QAAQ,CAAC,EAC9B,YAAY,EAAE,CAAC,OAAO,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,SAAS,gBAAgB,EAAE,CAAA;CAAE,EAAE,SAAS,EAAE,cAAc,CAAC,WAAW,CAAC,KAAK,IAAI,EAC3I,cAAc,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,EACpC,QAAQ,EAAE,cAAc,EACxB,SAAS,EAAE,MAAM,gBAAgB,GAAG,SAAS,EAC7C,iBAAiB,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,mBAAmB,KAAK,IAAI;6BAkRhE,MAAM,aACD,cAAc,CAAC,WAAW,CAAC,WAC9B,SAAS,gBAAgB,EAAE,WAC1B,WAAW,KACnB,IAAI;4BAcC,MAAM,aACD,cAAc,CAAC,WAAW,CAAC,WAC9B,SAAS,gBAAgB,EAAE,WAC1B,WAAW,KACnB,IAAI;iCAlR6B,SAAS,WAAW,EAAE,KAAG,WAAW,EAAE;kCAarC,MAAM,KAAG,IAAI;0BAuIrB,CAAC,QAAQ,MAAM,WAAW,OAAO,CAAC,CAAC,CAAC,WAAW,cAAc,KAAG,OAAO,CAAC,CAAC,CAAC;6BAkIzE,IAAI;wBAaZ,gBAAgB,KAAG,OAAO,CAAC,MAAM,CAAC;wBACpC,WAAW,CAAC,MAAM,EAAE,iBAAiB,CAAC,YAAY,CAAC,CAAC;;EAGzE"}
|
|
@@ -5,9 +5,10 @@ import { dispatchTuiDecision } from '../extension-events.js';
|
|
|
5
5
|
import { firstStaleComposerToken, formatMissingReference, orderedComposerImages, } from './composer-images.js';
|
|
6
6
|
import { expandComposerMentions } from './composer-mentions.js';
|
|
7
7
|
import { normalizeInputDecision } from './decisions.js';
|
|
8
|
+
import { attachIdeSelection } from './ide-selection.js';
|
|
8
9
|
import { mentionAttachments, mentionFs } from './mentions.js';
|
|
9
10
|
/** Input FIFO, staged attachments and decision notice timers share one lifetime. */
|
|
10
|
-
export function createInputDelivery(ctx, owner, binding, state, notify, trackPending, untrackPending, composer) {
|
|
11
|
+
export function createInputDelivery(ctx, owner, binding, state, notify, trackPending, untrackPending, composer, selection, rememberSelection) {
|
|
11
12
|
/**
|
|
12
13
|
* `@` file mentions (issue #15): expansion reads files asynchronously, so
|
|
13
14
|
* every user-text delivery (submit / steer / interrupt-requeue) funnels
|
|
@@ -82,6 +83,7 @@ export function createInputDelivery(ctx, owner, binding, state, notify, trackPen
|
|
|
82
83
|
fs: mentionFs(ctx),
|
|
83
84
|
attachments: mentionAttachments(ctx),
|
|
84
85
|
stagedImages: composer.snapshot(),
|
|
86
|
+
selection: selection(),
|
|
85
87
|
});
|
|
86
88
|
/**
|
|
87
89
|
* Expand the text's `@` mentions and deliver ONE user message: the typed
|
|
@@ -107,10 +109,16 @@ export function createInputDelivery(ctx, owner, binding, state, notify, trackPen
|
|
|
107
109
|
notify(t('ext-stale-dropped'), { color: 'warning', timeoutMs: 4000 });
|
|
108
110
|
return;
|
|
109
111
|
}
|
|
112
|
+
// IDE selection consumption: append the ENQUEUE-time selection as its own
|
|
113
|
+
// attached-file block — direct construction, never text parsing, failures
|
|
114
|
+
// silently skipped (an IDE-side extra must never block a send).
|
|
115
|
+
const selectionAttached = await attachIdeSelection(expansion.blocks, origin.cwd, origin.selection, origin.fs);
|
|
110
116
|
const message = createUserMessage({
|
|
111
117
|
content: expansion.blocks,
|
|
112
118
|
source: { kind: 'user' },
|
|
113
119
|
});
|
|
120
|
+
if (selectionAttached !== undefined)
|
|
121
|
+
rememberSelection(message.id, selectionAttached);
|
|
114
122
|
// The message is real from here on: remember its attached context BEFORE
|
|
115
123
|
// the agent call so the pre-step listener can find it (D6). A throwing
|
|
116
124
|
// followup/steer rolls both the pending preview and this entry back.
|
|
@@ -1,21 +1,6 @@
|
|
|
1
|
+
import { type ForegroundShell } from '../compat/shell.js';
|
|
1
2
|
import { type foldBack as FoldBack } from './transcript.js';
|
|
2
3
|
import type { ChannelState, ToolViewPresenter } from './types.js';
|
|
3
|
-
type Shell = {
|
|
4
|
-
resolve(request: {
|
|
5
|
-
command: string;
|
|
6
|
-
workdir?: string;
|
|
7
|
-
timeoutMs: number;
|
|
8
|
-
}): unknown;
|
|
9
|
-
run(spec: unknown): Promise<{
|
|
10
|
-
stdout: {
|
|
11
|
-
text: string;
|
|
12
|
-
};
|
|
13
|
-
stderr: {
|
|
14
|
-
text: string;
|
|
15
|
-
};
|
|
16
|
-
timedOut: boolean;
|
|
17
|
-
}>;
|
|
18
|
-
};
|
|
19
4
|
/** Owns local-only transcript mutations, shell output, and live subagent queries. */
|
|
20
5
|
export declare function createLocalActions(deps: {
|
|
21
6
|
ctx: {
|
|
@@ -54,9 +39,9 @@ export declare function createLocalActions(deps: {
|
|
|
54
39
|
badge: string;
|
|
55
40
|
label: string;
|
|
56
41
|
};
|
|
57
|
-
commandShell(cwd: string): Promise<
|
|
42
|
+
commandShell(cwd: string): Promise<ForegroundShell | undefined>;
|
|
58
43
|
};
|
|
59
|
-
shell?:
|
|
44
|
+
shell?: ForegroundShell;
|
|
60
45
|
notify: ChannelState['notify'];
|
|
61
46
|
}): {
|
|
62
47
|
loadOlder(): number;
|
|
@@ -66,5 +51,4 @@ export declare function createLocalActions(deps: {
|
|
|
66
51
|
listSubagents(): Promise<string[]>;
|
|
67
52
|
runLocalCommand(command: string, includeInContext: boolean): Promise<void>;
|
|
68
53
|
};
|
|
69
|
-
export {};
|
|
70
54
|
//# sourceMappingURL=local-actions.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"local-actions.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/channel/local-actions.ts"],"names":[],"mappings":"AAOA,OAAO,
|
|
1
|
+
{"version":3,"file":"local-actions.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/channel/local-actions.ts"],"names":[],"mappings":"AAOA,OAAO,EAAsB,KAAK,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAC7E,OAAO,EAA+B,KAAK,QAAQ,IAAI,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AACxF,OAAO,KAAK,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAEjE,qFAAqF;AACrF,wBAAgB,kBAAkB,CAAC,IAAI,EAAE;IACvC,GAAG,EAAE;QAAE,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAA;IACnC,KAAK,EAAE;QAAE,OAAO,IAAI,OAAO,CAAA;KAAE,CAAA;IAC7B,OAAO,EAAE;QACP,OAAO,IAAI,OAAO,CAAA;QAClB,SAAS,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAA;QACpC,QAAQ,CAAC,KAAK,EAAE;YAAE,OAAO,EAAE,OAAO,CAAC;YAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAA;SAAE,CAAA;KACvE,CAAA;IACD,KAAK,EAAE,YAAY,CAAA;IACnB,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;IACzB,SAAS,EAAE;QAAE,KAAK,IAAI,IAAI,CAAC;QAAC,eAAe,EAAE,WAAW,CAAC,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC;QAAC,iBAAiB,EAAE,WAAW,CAAC,iBAAiB,CAAC,CAAC,QAAQ,CAAC,CAAA;KAAE,CAAA;IAClJ,SAAS,EAAE;QAAE,QAAQ,IAAI,IAAI,CAAA;KAAE,CAAA;IAC/B,IAAI,EAAE;QAAE,QAAQ,IAAI,IAAI,CAAA;KAAE,CAAA;IAC1B,QAAQ,EAAE,OAAO,QAAQ,CAAA;IACzB,SAAS,EAAE;QAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC;QAAC,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,SAAS,CAAC,CAAA;KAAE,CAAA;IACrJ,KAAK,CAAC,EAAE,eAAe,CAAA;IACvB,MAAM,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAA;CAC/B;iBAIgB,MAAM;aAKV,IAAI;qBAYI,MAAM,SAAS,SAAS,MAAM,EAAE,GAAG,IAAI;4BAKhC,MAAM,GAAG,OAAO;qBAajB,OAAO,CAAC,MAAM,EAAE,CAAC;6BAmBT,MAAM,oBAAoB,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;EAqBnF"}
|
|
@@ -4,6 +4,7 @@ import { writeActivityFrames } from '../../activityPrefs.js';
|
|
|
4
4
|
import { isPresetName, normalizeActivityPreset } from '../../components/activityFrames.js';
|
|
5
5
|
import { t } from '../../i18n.js';
|
|
6
6
|
import { snapshotLiveSessionEvents } from '../compat/liveSession.js';
|
|
7
|
+
import { runForegroundShell } from '../compat/shell.js';
|
|
7
8
|
import { LOCAL_OUTPUT_LIMIT, preview } from './transcript.js';
|
|
8
9
|
/** Owns local-only transcript mutations, shell output, and live subagent queries. */
|
|
9
10
|
export function createLocalActions(deps) {
|
|
@@ -90,7 +91,7 @@ export function createLocalActions(deps) {
|
|
|
90
91
|
return;
|
|
91
92
|
if (executor) {
|
|
92
93
|
try {
|
|
93
|
-
const result = await
|
|
94
|
+
const result = await runForegroundShell(executor, { command, workdir: cwd, timeoutMs: 30000 });
|
|
94
95
|
output = result.stdout.text.trim() || result.stderr.text.trim() || (result.timedOut ? '(timed out)' : '(no output)');
|
|
95
96
|
}
|
|
96
97
|
catch (error) {
|
|
@@ -11,13 +11,16 @@ type Binding = ReturnType<typeof createChannelBinding>;
|
|
|
11
11
|
* This owns the async catalog caches and their generation fences; callers only
|
|
12
12
|
* compose its surface into ChannelState after the state has been constructed.
|
|
13
13
|
*/
|
|
14
|
-
export declare function createModelActions(ctx: Context, state: Pick<ChannelState, 'provider' | 'model' | 'reasoningEffort' | 'effortLevels' | 'agentPreset' | 'working' | 'emit'>, deps: {
|
|
14
|
+
export declare function createModelActions(ctx: Context, state: Pick<ChannelState, 'provider' | 'model' | 'reasoningEffort' | 'effortLevels' | 'agentPreset' | 'working' | 'contextWindow' | 'emit'>, deps: {
|
|
15
15
|
owner: Pick<ChannelOwner, 'current'>;
|
|
16
16
|
binding: Pick<Binding, 'capture' | 'isCurrent'>;
|
|
17
17
|
selection: ModelSelectionRef;
|
|
18
18
|
initialEffort?: string;
|
|
19
19
|
agent(): Agent;
|
|
20
20
|
notify: ChannelState['notify'];
|
|
21
|
+
/** Re-check the context-low warning after a refreshed route metadata
|
|
22
|
+
* answer carries a newer contextWindow than the session started with. */
|
|
23
|
+
checkContextWarning(): void;
|
|
21
24
|
}): {
|
|
22
25
|
selection: ModelSelectionRef;
|
|
23
26
|
applyPreferredEffort: () => Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model-actions.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/channel/model-actions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAqB,KAAK,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAC3E,OAAO,KAAK,EAAE,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AACtE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAA;AAM9D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAC9C,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAE1E,KAAK,OAAO,GAAG,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAA;AAEtD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,IAAI,CAAC,YAAY,EAAE,UAAU,GAAG,OAAO,GAAG,iBAAiB,GAAG,cAAc,GAAG,aAAa,GAAG,SAAS,GAAG,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"model-actions.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/channel/model-actions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAqB,KAAK,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAC3E,OAAO,KAAK,EAAE,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AACtE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAA;AAM9D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAC9C,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAE1E,KAAK,OAAO,GAAG,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAA;AAEtD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,IAAI,CAAC,YAAY,EAAE,UAAU,GAAG,OAAO,GAAG,iBAAiB,GAAG,cAAc,GAAG,aAAa,GAAG,SAAS,GAAG,eAAe,GAAG,MAAM,CAAC,EAC3I,IAAI,EAAE;IACJ,KAAK,EAAE,IAAI,CAAC,YAAY,EAAE,SAAS,CAAC,CAAA;IACpC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,SAAS,GAAG,WAAW,CAAC,CAAA;IAC/C,SAAS,EAAE,iBAAiB,CAAA;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,KAAK,IAAI,KAAK,CAAA;IACd,MAAM,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAA;IAC9B;6EACyE;IACzE,mBAAmB,IAAI,IAAI,CAAA;CAC5B;;gCA8DsC,OAAO,CAAC,IAAI,CAAC;+BA+DpB,IAAI;uBAqBN,OAAO,CAAC;QAAE,OAAO,EAAE,SAAS,YAAY,EAAE,CAAC;QAAC,aAAa,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,CAAC;oBAWjF,MAAM,KAAG,OAAO,CAAC,OAAO,CAAC;2BAoBxB,MAAM,GAAG,SAAS,KAAG,IAAI;4BAM1B,IAAI;sBAeV,OAAO,CAAC,SAAS,YAAY,EAAE,CAAC;;YAhMnB,MAAM;cAAQ,MAAM;;8BAqMzB,IAAI;0BACR,IAAI;;6BASD,IAAI;;uBAOJ,OAAO,CAAC,SAAS,YAAY,EAAE,CAAC;6BAQxB,MAAM,KAAG,OAAO,CAAC,OAAO,CAAC;EAkChE"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { ReasoningEffortId } from '@deepseek-ai/dsh-llm';
|
|
2
|
-
import { readEffortPref, resolveEffortDefault, writeEffortPref } from '../../effortPrefs.js';
|
|
2
|
+
import { nearestLowerEffort, readEffortPref, resolveEffortDefault, writeEffortPref } from '../../effortPrefs.js';
|
|
3
3
|
import { snapshotLiveSessionEvents } from '../compat/liveSession.js';
|
|
4
4
|
import { getLang, t, tOr } from '../../i18n.js';
|
|
5
5
|
import { migratePresetPref, writePresetPref } from '../../presetPrefs.js';
|
|
6
|
-
import { resolveCompatiblePreset, rosterOf } from '../preset-resolution.js';
|
|
6
|
+
import { presetDisplayId, resolveCompatiblePreset, rosterOf } from '../preset-resolution.js';
|
|
7
7
|
/**
|
|
8
8
|
* Route metadata, effort preference and preset/model catalog actions.
|
|
9
9
|
* This owns the async catalog caches and their generation fences; callers only
|
|
@@ -13,6 +13,9 @@ export function createModelActions(ctx, state, deps) {
|
|
|
13
13
|
const { owner, selection, notify } = deps;
|
|
14
14
|
const llmRuntime = ctx.get('llm');
|
|
15
15
|
let preferredEffort = deps.initialEffort ?? readEffortPref();
|
|
16
|
+
// Last fallback notice shown for a (preferred → applied) pair: bind fires on
|
|
17
|
+
// every session switch, so an unchanged downgrade must not re-toast.
|
|
18
|
+
let lastEffortFallbackNotice;
|
|
16
19
|
// State construction cannot call this factory yet; seed the visible value
|
|
17
20
|
// before the root starts binding or exposes the completed ChannelState.
|
|
18
21
|
state.reasoningEffort = preferredEffort;
|
|
@@ -27,11 +30,28 @@ export function createModelActions(ctx, state, deps) {
|
|
|
27
30
|
});
|
|
28
31
|
const effortCurrent = (capture) => owner.current() && deps.binding.isCurrent(capture.binding) &&
|
|
29
32
|
state.provider === capture.provider && state.model === capture.model && effortOperation === capture.operation;
|
|
33
|
+
/** Route-level metadata shared by every resolveModelInfo consumer. The
|
|
34
|
+
* context window follows the route, not the binding: a resume rebuilds
|
|
35
|
+
* the binding (effortCurrent goes false) while the capacity answer for
|
|
36
|
+
* the same provider/model is still the live truth, so this runs before
|
|
37
|
+
* any effort freshness gate. Lifetime is the one fence it keeps: the
|
|
38
|
+
* answer crosses an await, so a Channel released while the lookup was in
|
|
39
|
+
* flight must neither write into its dead state nor re-arm the
|
|
40
|
+
* context-low warning through checkContextWarning. */
|
|
41
|
+
const applyRouteMetadata = (capture, info) => {
|
|
42
|
+
if (!owner.current())
|
|
43
|
+
return;
|
|
44
|
+
if (state.provider === capture.provider && state.model === capture.model && info.context !== undefined) {
|
|
45
|
+
state.contextWindow = info.context.contextWindow;
|
|
46
|
+
deps.checkContextWarning();
|
|
47
|
+
}
|
|
48
|
+
};
|
|
30
49
|
const resolveEfforts = async (capture) => {
|
|
31
50
|
if (llmRuntime === undefined || typeof llmRuntime.resolveModelInfo !== 'function')
|
|
32
51
|
return 'unavailable';
|
|
33
52
|
try {
|
|
34
53
|
const info = await llmRuntime.resolveModelInfo(capture.provider, capture.model);
|
|
54
|
+
applyRouteMetadata(capture, info);
|
|
35
55
|
if (!effortCurrent(capture))
|
|
36
56
|
return 'stale';
|
|
37
57
|
const efforts = info.reasoning?.efforts ?? [];
|
|
@@ -55,9 +75,62 @@ export function createModelActions(ctx, state, deps) {
|
|
|
55
75
|
// This same binding-time lookup is the route's initial tier refresh even
|
|
56
76
|
// without a stored preference. Do not make a separate competing refresh
|
|
57
77
|
// operation that could invalidate the selected preference completion.
|
|
58
|
-
if (preferredEffort === undefined
|
|
78
|
+
if (preferredEffort === undefined)
|
|
59
79
|
return;
|
|
60
|
-
|
|
80
|
+
const available = resolved.efforts.map(effort => effort.id);
|
|
81
|
+
// Exact hit applies silently; a miss falls back to the nearest LOWER tier
|
|
82
|
+
// the route offers (never up), and both miss paths notify exactly once
|
|
83
|
+
// per (preferred → applied) pair — bind fires on every session switch,
|
|
84
|
+
// so an unchanged downgrade must not re-toast.
|
|
85
|
+
const applied = nearestLowerEffort(preferredEffort, available);
|
|
86
|
+
if (applied === undefined) {
|
|
87
|
+
if (lastEffortFallbackNotice?.preferred !== preferredEffort || lastEffortFallbackNotice.applied !== undefined) {
|
|
88
|
+
lastEffortFallbackNotice = { preferred: preferredEffort, applied: undefined };
|
|
89
|
+
notify(t('effort-preference-unsupported', { preferred: preferredEffort }), { color: 'warning' });
|
|
90
|
+
}
|
|
91
|
+
// Nothing is pinned, so the ROUTE's model default is what actually ships
|
|
92
|
+
// and the readout (status line, /effort status) must say so. Every switch
|
|
93
|
+
// tail clears it before this runs (session-resume.ts / model-switch.ts /
|
|
94
|
+
// session-live-adoption.ts / background-action.ts), but a resumed log's
|
|
95
|
+
// replayed `request/header` can leave an older tier behind — neither blank
|
|
96
|
+
// nor "last route's tier" is the truth. Only the readout moves: pinning
|
|
97
|
+
// the default into selection.current would put a tier the user never chose
|
|
98
|
+
// onto the wire, which is exactly what "never up" forbids.
|
|
99
|
+
const shipped = resolved.defaultEffort;
|
|
100
|
+
if (state.reasoningEffort !== shipped) {
|
|
101
|
+
state.reasoningEffort = shipped;
|
|
102
|
+
state.emit();
|
|
103
|
+
}
|
|
104
|
+
// An effort pin installed earlier (an exact hit, /effort <id>) survives
|
|
105
|
+
// every path that is NOT a bind: /settings' effortDefault hands the level
|
|
106
|
+
// straight to setDefaultEffort → applyPreferredEffort (plugin.ts:804 →
|
|
107
|
+
// setDefaultEffort above), which never resets selection.current — the four
|
|
108
|
+
// switch tails that do are all on the bind side. Leaving it would put the
|
|
109
|
+
// OLD tier back on the wire while the readout above announces the model
|
|
110
|
+
// default. Drop the effort only: the provider/model half of the pin is
|
|
111
|
+
// this route's, not the stale tier's. No emit — setDefaultEffort reaches
|
|
112
|
+
// here through that same non-bind path, and nothing UI-visible reads this
|
|
113
|
+
// ref (it is the router's ModelSelectionRef, not the IDE ChannelSelection
|
|
114
|
+
// the status line shows); the readout above already emits when it moves.
|
|
115
|
+
if (selection.current?.reasoningEffort !== undefined) {
|
|
116
|
+
selection.current = { provider: capture.provider, model: capture.model };
|
|
117
|
+
}
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
// Dedupe gates ONLY the toast: bind resets selection.current on every
|
|
121
|
+
// session switch, so the pin below must re-apply unconditionally — an
|
|
122
|
+
// early return here would ship the model default from the second session
|
|
123
|
+
// on (review C1). The status line shows the tier that actually ships.
|
|
124
|
+
const fresh = lastEffortFallbackNotice?.preferred !== preferredEffort || lastEffortFallbackNotice.applied !== applied;
|
|
125
|
+
if (applied !== preferredEffort && fresh) {
|
|
126
|
+
lastEffortFallbackNotice = { preferred: preferredEffort, applied };
|
|
127
|
+
notify(t('effort-preference-downgraded', { preferred: preferredEffort, applied }), { color: 'warning' });
|
|
128
|
+
}
|
|
129
|
+
if (applied === preferredEffort)
|
|
130
|
+
lastEffortFallbackNotice = undefined;
|
|
131
|
+
state.reasoningEffort = applied;
|
|
132
|
+
selection.current = { provider: capture.provider, model: capture.model, reasoningEffort: ReasoningEffortId(applied) };
|
|
133
|
+
state.emit();
|
|
61
134
|
};
|
|
62
135
|
const refreshEffortLevels = () => {
|
|
63
136
|
if (llmRuntime === undefined || typeof llmRuntime.resolveModelInfo !== 'function')
|
|
@@ -65,7 +138,10 @@ export function createModelActions(ctx, state, deps) {
|
|
|
65
138
|
const capture = captureEffort();
|
|
66
139
|
const generation = ++effortLevelsGeneration;
|
|
67
140
|
void llmRuntime.resolveModelInfo(capture.provider, capture.model).then(info => {
|
|
68
|
-
if (
|
|
141
|
+
if (generation !== effortLevelsGeneration)
|
|
142
|
+
return;
|
|
143
|
+
applyRouteMetadata(capture, info);
|
|
144
|
+
if (!effortCurrent(capture))
|
|
69
145
|
return;
|
|
70
146
|
state.effortLevels = (info.reasoning?.efforts ?? []).map(level => level.id);
|
|
71
147
|
state.emit();
|
|
@@ -192,7 +268,7 @@ export function createModelActions(ctx, state, deps) {
|
|
|
192
268
|
return [];
|
|
193
269
|
const localized = getLang() === 'en';
|
|
194
270
|
try {
|
|
195
|
-
return (await presets.list()).map(preset => ({ id: preset.id, ...(preset.name === undefined ? {} : { name: localized ? tOr(`preset-name-${preset.id}`, preset.name) : preset.name }), ...(preset.description === undefined ? {} : { description: localized ? tOr(`preset-desc-${preset.id}`, preset.description) : preset.description }), ...(preset.broken === undefined ? {} : { broken: preset.broken }), isDefault: preset.id === presets.defaultId }));
|
|
271
|
+
return (await presets.list()).map(preset => ({ id: preset.id, ...(preset.name === undefined ? {} : { name: localized ? tOr(`preset-name-${presetDisplayId(preset.id)}`, preset.name) : preset.name }), ...(preset.description === undefined ? {} : { description: localized ? tOr(`preset-desc-${presetDisplayId(preset.id)}`, preset.description) : preset.description }), ...(preset.broken === undefined ? {} : { broken: preset.broken }), isDefault: preset.id === presets.defaultId }));
|
|
196
272
|
}
|
|
197
273
|
catch {
|
|
198
274
|
return [];
|
|
@@ -5,7 +5,7 @@ import type { ChannelOwner } from './owner.js';
|
|
|
5
5
|
import { resetSessionProjection } from './session-reset.js';
|
|
6
6
|
import type { ChannelState } from './types.js';
|
|
7
7
|
type Binding = ReturnType<typeof createChannelBinding>;
|
|
8
|
-
type SwitchState = Parameters<typeof resetSessionProjection>[0] & Pick<ChannelState, 'cwd' | 'working' | 'status' | 'agentId' | 'agentPreset' | 'provider' | 'model' | 'contextWindow' | 'effortLevels' | 'reasoningEffort' | 'emit'>;
|
|
8
|
+
type SwitchState = Parameters<typeof resetSessionProjection>[0] & Pick<ChannelState, 'cwd' | 'working' | 'status' | 'agentId' | 'sessionId' | 'agentPreset' | 'provider' | 'model' | 'contextWindow' | 'effortLevels' | 'reasoningEffort' | 'emit'>;
|
|
9
9
|
/** Model-route adoption transaction. It settles compaction before its fork snapshot and owns the post-commit reset. */
|
|
10
10
|
export declare function createModelSwitchAction(ctx: Context, state: SwitchState, deps: {
|
|
11
11
|
owner: Pick<ChannelOwner, 'current'>;
|
|
@@ -25,7 +25,6 @@ export declare function createModelSwitchAction(ctx: Context, state: SwitchState
|
|
|
25
25
|
refreshSkillCommands(): Promise<void>;
|
|
26
26
|
clearStagedImages(): void;
|
|
27
27
|
dropModelCompletion(): void;
|
|
28
|
-
onModelSwitch(model: string): void;
|
|
29
28
|
notify: ChannelState['notify'];
|
|
30
29
|
}): (provider: string, model: string) => Promise<boolean>;
|
|
31
30
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model-switch.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/channel/model-switch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAGlD,OAAO,EAAa,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;
|
|
1
|
+
{"version":3,"file":"model-switch.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/channel/model-switch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAGlD,OAAO,EAAa,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAQvE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAC9C,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAA;AAC3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAE9C,KAAK,OAAO,GAAG,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAA;AACtD,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,sBAAsB,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,YAAY,EACjF,KAAK,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,WAAW,GAAG,aAAa,GAAG,UAAU,GAAG,OAAO,GAAG,eAAe,GAAG,cAAc,GAAG,iBAAiB,GAAG,MAAM,CAAC,CAAA;AAEhK,uHAAuH;AACvH,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,WAAW,EAClB,IAAI,EAAE;IACJ,KAAK,EAAE,IAAI,CAAC,YAAY,EAAE,SAAS,CAAC,CAAA;IACpC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,OAAO,CAAC,CAAA;IAC3F,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;IACzB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACjC,cAAc,IAAI,IAAI,CAAA;IACtB,cAAc,IAAI,IAAI,CAAA;IACtB,SAAS,IAAI,IAAI,CAAA;IACjB,MAAM,CAAC,MAAM,EAAE,SAAS,YAAY,EAAE,GAAG,IAAI,CAAA;IAC7C,YAAY,IAAI,IAAI,CAAA;IACpB,SAAS,IAAI,IAAI,CAAA;IACjB,eAAe,IAAI,IAAI,CAAA;IACvB,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACrC,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACrC,iBAAiB,IAAI,IAAI,CAAA;IACzB,mBAAmB,IAAI,IAAI,CAAA;IAC3B,MAAM,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAA;CAC/B,IAEa,UAAU,MAAM,EAAE,OAAO,MAAM,KAAG,OAAO,CAAC,OAAO,CAAC,CA4EjE"}
|