@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
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { randomUUID } from 'node:crypto';
|
|
2
2
|
import { SessionId } from '@deepseek-ai/dsh-session';
|
|
3
3
|
import { explicitModelRoute, recordedModelRoute, resolveModelRoute, validateModelRoute } from '../../modelRoute.js';
|
|
4
|
-
import { clearResumeTarget, touchAgentViewSession, touchSession
|
|
4
|
+
import { clearResumeTarget, writeResumeTarget, touchAgentViewSession, touchSession } from '../../sessionHistory.js';
|
|
5
|
+
import { mountFailureText } from '../../sessions/resumeFailure.js';
|
|
5
6
|
import { t } from '../../i18n.js';
|
|
6
7
|
import { readModelPref } from '../../modelPrefs.js';
|
|
7
8
|
import { migratePresetPref, readPresetPref } from '../../presetPrefs.js';
|
|
8
9
|
import { agentViewHasTurns } from '../agent-view.js';
|
|
10
|
+
import { occupancyOf, readSessionOwners, reserveMount, reserveNewSession, } from '../../sessionMounts.js';
|
|
9
11
|
import { ensureLegacySessionEventTypes } from '../compat/index.js';
|
|
10
12
|
import { snapshotLiveSessionEvents } from '../compat/liveSession.js';
|
|
11
13
|
import { composePreset, resolvePersistedPreset, resolvePersistedRoute } from '../presets.js';
|
|
@@ -18,6 +20,7 @@ export function createSessionResumeActions(ctx, state, options, deps) {
|
|
|
18
20
|
resetSessionProjection(state, deps.rowIds, deps.resetProjector, deps.resetSubagents, deps.resetJobs);
|
|
19
21
|
state.status = handle.agent.status;
|
|
20
22
|
state.agentId = handle.agent.id;
|
|
23
|
+
state.sessionId = handle.agent.session.id;
|
|
21
24
|
state.agentPreset = agentPreset;
|
|
22
25
|
if (route !== undefined) {
|
|
23
26
|
state.provider = route.provider;
|
|
@@ -39,96 +42,272 @@ export function createSessionResumeActions(ctx, state, options, deps) {
|
|
|
39
42
|
void deps.refreshSkillCommands();
|
|
40
43
|
};
|
|
41
44
|
/** Resume a persisted session, optionally parking the attached agent for agent-view attachment. */
|
|
42
|
-
const resume = async (sessionId, kind, keepCurrent, adoption, entrySession
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
...(composed.setup === undefined ? {} : { setup: composed.setup }),
|
|
61
|
-
}));
|
|
62
|
-
}
|
|
63
|
-
catch (error) {
|
|
64
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
65
|
-
deps.notify(t('resume-failed', { err: message }), { color: 'error', timeoutMs: 8000 });
|
|
66
|
-
return { ok: false, reason: 'failed', error: message };
|
|
67
|
-
}
|
|
68
|
-
if (!deps.binding.isCurrent(adoption)) {
|
|
69
|
-
await deps.binding.abandon(handle);
|
|
70
|
-
return { ok: false, reason: 'cancelled' };
|
|
71
|
-
}
|
|
45
|
+
const resume = async (sessionId, kind, keepCurrent, adoption, entrySession,
|
|
46
|
+
/**
|
|
47
|
+
* The ledger reservation this call holds for `sessionId`; ended by this
|
|
48
|
+
* function on every exit. `settle` on a commit (the agent is in the
|
|
49
|
+
* registry from then on), `abandon` on every path that ends WITHOUT one —
|
|
50
|
+
* including a throwing `binding.adopt()` and a setup failure inside its
|
|
51
|
+
* tail, which revokes the candidate.
|
|
52
|
+
*/
|
|
53
|
+
reservation) => {
|
|
54
|
+
/**
|
|
55
|
+
* The reservation is ended on EVERY exit from here, so the attempt owns it
|
|
56
|
+
* for the whole body: `settle` on a commit (the agent is in the registry
|
|
57
|
+
* from then on), `abandon` on everything else — a throwing
|
|
58
|
+
* `binding.adopt()`, a setup failure inside its tail, and also a throw from
|
|
59
|
+
* the preset/route reads below, which used to sit outside any guard and
|
|
60
|
+
* would have left a pin that republishes the session as ours on every beat.
|
|
61
|
+
*/
|
|
62
|
+
let committed = false;
|
|
72
63
|
try {
|
|
73
|
-
await
|
|
64
|
+
return await runResume();
|
|
74
65
|
}
|
|
75
|
-
|
|
76
|
-
|
|
66
|
+
finally {
|
|
67
|
+
if (committed)
|
|
68
|
+
reservation?.settle();
|
|
69
|
+
else
|
|
70
|
+
reservation?.abandon();
|
|
77
71
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
72
|
+
async function runResume() {
|
|
73
|
+
const agents = ctx.get('agents');
|
|
74
|
+
if (!agents) {
|
|
75
|
+
deps.notify(t('resume-unavailable'), { color: 'error' });
|
|
76
|
+
return { ok: false, reason: 'unavailable' };
|
|
77
|
+
}
|
|
78
|
+
ensureLegacySessionEventTypes();
|
|
79
|
+
const composed = await composePreset(ctx, await resolvePersistedPreset(ctx, SessionId(sessionId)));
|
|
80
|
+
const explicitRoute = explicitModelRoute({ provider: options.configuredProvider, model: options.configuredModel });
|
|
81
|
+
const persistedRoute = await resolvePersistedRoute(ctx, SessionId(sessionId));
|
|
82
|
+
let handle;
|
|
83
|
+
try {
|
|
84
|
+
handle = await deps.binding.prepare(adoption, () => agents.resume({
|
|
85
|
+
resumeSessionId: SessionId(sessionId),
|
|
86
|
+
agentOptions: {
|
|
87
|
+
provider: explicitRoute?.provider ?? persistedRoute?.provider,
|
|
88
|
+
model: explicitRoute?.model ?? persistedRoute?.model,
|
|
89
|
+
},
|
|
90
|
+
...(composed.setup === undefined ? {} : { setup: composed.setup }),
|
|
91
|
+
}));
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
95
|
+
deps.notify(t('resume-failed', { err: message }), { color: 'error', timeoutMs: 8000 });
|
|
96
|
+
return { ok: false, reason: 'failed', error: message };
|
|
97
|
+
}
|
|
98
|
+
if (!deps.binding.isCurrent(adoption)) {
|
|
99
|
+
await deps.binding.abandon(handle);
|
|
100
|
+
return { ok: false, reason: 'cancelled' };
|
|
101
|
+
}
|
|
102
|
+
try {
|
|
103
|
+
await attachSessionToWorkspace(ctx, handle.agent.session.header.cwd ?? state.cwd, SessionId(sessionId));
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
deps.notify(t('resume-attach-failed', { err: error instanceof Error ? error.message : String(error) }), { color: 'warning', timeoutMs: 8000 });
|
|
107
|
+
}
|
|
108
|
+
if (entrySession !== undefined && (!deps.owner.current() || deps.binding.agent.session !== entrySession)) {
|
|
109
|
+
await deps.binding.abandon(handle);
|
|
110
|
+
deps.notify(t('resume-session-changed'), { color: 'error' });
|
|
111
|
+
return { ok: false, reason: 'failed', error: 'live session changed during resume' };
|
|
112
|
+
}
|
|
113
|
+
// `adopt` is a transaction: it revokes the candidate and disposes it when
|
|
114
|
+
// the tail fails, and it can also refuse before the tail ever runs. Only a
|
|
115
|
+
// normal return is a commit, which is what the outer finally keys on.
|
|
116
|
+
const result = deps.binding.adopt(handle, adoption, (committedBinding, disposePrevious) => {
|
|
117
|
+
const previousSessionId = String(committedBinding.agent.session.id);
|
|
118
|
+
state.cwd = handle.agent.session.header.cwd ?? state.cwd;
|
|
119
|
+
state.displayCwd = deps.describeWorkspace(state.cwd).description ?? state.cwd;
|
|
120
|
+
deps.resetIdeSelection();
|
|
121
|
+
deps.refreshGitBranch();
|
|
122
|
+
// Reset the input FIFO and pending-decision indicators BEFORE the first
|
|
123
|
+
// emit (main's bind → clear → refresh order); see the /new tail.
|
|
124
|
+
deps.clearStagedImages();
|
|
125
|
+
resetAndBind(handle, composed.agentPreset, explicitRoute ?? recordedModelRoute(snapshotLiveSessionEvents(handle.agent.session)), true);
|
|
126
|
+
writeResumeTarget(sessionId);
|
|
127
|
+
touchSession(sessionId);
|
|
128
|
+
state.emit();
|
|
129
|
+
const keepPrevious = keepCurrent && committedBinding.handle !== undefined
|
|
130
|
+
&& (committedBinding.handle.agent.status === 'running' || agentViewHasTurns(snapshotLiveSessionEvents(committedBinding.handle.agent.session)));
|
|
131
|
+
if (committedBinding.handle !== undefined) {
|
|
132
|
+
if (keepPrevious) {
|
|
133
|
+
deps.backgroundHandles.set(previousSessionId, committedBinding.handle);
|
|
134
|
+
disposePrevious('park');
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
disposePrevious('dispose');
|
|
138
|
+
}
|
|
101
139
|
}
|
|
102
|
-
|
|
103
|
-
|
|
140
|
+
if (kind === 'agent-view') {
|
|
141
|
+
touchAgentViewSession(sessionId);
|
|
142
|
+
touchAgentViewSession(previousSessionId);
|
|
104
143
|
}
|
|
144
|
+
deps.notifySessionSwitched(kind, sessionId, previousSessionId);
|
|
145
|
+
return { ok: true };
|
|
146
|
+
});
|
|
147
|
+
committed = true;
|
|
148
|
+
return result;
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
/**
|
|
152
|
+
* Reserve `sessionId` for a disk resume on THIS terminal.
|
|
153
|
+
*
|
|
154
|
+
* Returning a reservation means the caller owns the session in the ledger
|
|
155
|
+
* until it calls `finish()`. That covers the whole attempt, not just the
|
|
156
|
+
* `agents.resume` call: the awaits in between (veto, compaction, preset and
|
|
157
|
+
* route reads) are exactly the window a publisher beat — or a peer — could
|
|
158
|
+
* otherwise slip into.
|
|
159
|
+
* @param sessionId - Session about to be resumed from disk.
|
|
160
|
+
* @returns The reservation, or the refusal to hand back to the caller.
|
|
161
|
+
*/
|
|
162
|
+
const reserveDiskResume = async (sessionId) => {
|
|
163
|
+
// Cheap pre-filter for the friendly toast: the authoritative conflict test
|
|
164
|
+
// runs inside reserveMount, under the ledger lock.
|
|
165
|
+
const occupancy = occupancyOf(sessionId, readSessionOwners());
|
|
166
|
+
if (occupancy.kind === 'occupied') {
|
|
167
|
+
deps.notify(t('resume-session-occupied', { pid: occupancy.pid }), { color: 'error', timeoutMs: 8000 });
|
|
168
|
+
return { ok: false, result: { ok: false, reason: 'occupied', pid: occupancy.pid } };
|
|
169
|
+
}
|
|
170
|
+
const reserved = await reserveMount(sessionId);
|
|
171
|
+
if (!reserved.ok) {
|
|
172
|
+
if (reserved.reason === 'occupied') {
|
|
173
|
+
const pid = reserved.holders[0] ?? 0;
|
|
174
|
+
deps.notify(t('resume-session-occupied', { pid }), { color: 'error', timeoutMs: 8000 });
|
|
175
|
+
return { ok: false, result: { ok: false, reason: 'occupied', pid } };
|
|
105
176
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
return { ok: true };
|
|
112
|
-
});
|
|
177
|
+
// Both of these are refusals, not conflicts, and neither may be dressed
|
|
178
|
+
// up as "held by pid 0". The generic failure branch carries the sentence.
|
|
179
|
+
return { ok: false, result: { ok: false, reason: 'failed', error: mountFailureText(reserved) } };
|
|
180
|
+
}
|
|
181
|
+
return { ok: true, reservation: reserved.reservation };
|
|
113
182
|
};
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
183
|
+
/**
|
|
184
|
+
* Reserve a freshly minted session id for a create on THIS terminal. See
|
|
185
|
+
* `reserveNewSession`: a new id cannot conflict, so a refusal is a loss of
|
|
186
|
+
* announcement rather than a reason to stop, and it is warned about.
|
|
187
|
+
* @param sessionId - Session id minted for the new agent.
|
|
188
|
+
* @returns The reservation (a no-op when the claim could not be made).
|
|
189
|
+
*/
|
|
190
|
+
const reserveCreatedSession = async (sessionId) => {
|
|
191
|
+
const { reservation, failure } = await reserveNewSession(sessionId);
|
|
192
|
+
if (failure !== undefined && failure.reason !== 'occupied') {
|
|
193
|
+
deps.notify(mountFailureText(failure), { color: 'warning', timeoutMs: 8000 });
|
|
194
|
+
}
|
|
195
|
+
return reservation;
|
|
196
|
+
};
|
|
197
|
+
const resumeInto = async (sessionId, kind, keepCurrent) => {
|
|
117
198
|
const adoption = deps.binding.capture();
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
199
|
+
const agents = ctx.get('agents');
|
|
200
|
+
if (!agents) {
|
|
201
|
+
deps.notify(t('resume-unavailable'), { color: 'error' });
|
|
202
|
+
return { ok: false, reason: 'unavailable' };
|
|
121
203
|
}
|
|
204
|
+
// Same reservation as `/resume`: this is the other public door onto the
|
|
205
|
+
// disk path (`ChannelUi.attachToAgent`), and a mount that skips the ledger
|
|
206
|
+
// is a mount a peer can race from the outside.
|
|
207
|
+
const reserved = await reserveDiskResume(sessionId);
|
|
208
|
+
if (!reserved.ok)
|
|
209
|
+
return reserved.result;
|
|
210
|
+
return resume(sessionId, kind, keepCurrent, adoption, undefined, reserved.reservation);
|
|
211
|
+
};
|
|
212
|
+
/**
|
|
213
|
+
* `/resume` — mount a session on THIS terminal, the same non-destructive way
|
|
214
|
+
* `/agentview` does.
|
|
215
|
+
*
|
|
216
|
+
* There used to be two different mount models behind these two commands.
|
|
217
|
+
* `/agentview` parked the session it left behind (it kept running in this
|
|
218
|
+
* process and was reachable again from the view), while `/resume` DISPOSED
|
|
219
|
+
* it, and refused outright while a turn was running. That split was never a
|
|
220
|
+
* decision about resuming; it was an accident of the two commands growing
|
|
221
|
+
* separately, and it is what made `/resume` feel like a different product
|
|
222
|
+
* from the session overview sitting one command away.
|
|
223
|
+
*
|
|
224
|
+
* The unified model is the overview's, because it is the one that matches
|
|
225
|
+
* what a TUI terminal actually is: one process that can host several agent
|
|
226
|
+
* sessions at once. So:
|
|
227
|
+
*
|
|
228
|
+
* - Leaving a session parks it (`keepCurrent`), it does not end it, and the
|
|
229
|
+
* parked handle is reachable from the session screen afterwards.
|
|
230
|
+
* - A running turn is not a refusal. The user is switching what they are
|
|
231
|
+
* LOOKING at, not asking the model to stop; the turn keeps running in the
|
|
232
|
+
* background and its row keeps reporting progress.
|
|
233
|
+
*
|
|
234
|
+
* The one thing that IS refused is a session another TUI process already has
|
|
235
|
+
* mounted: two processes driving one append-only log interleave its events.
|
|
236
|
+
* The occupancy check happens BEFORE the resume awaits (which yield), and
|
|
237
|
+
* the claim is published immediately after it so this process owns the
|
|
238
|
+
* session before any other process can pass the same check.
|
|
239
|
+
*
|
|
240
|
+
* The reservation also outlives those awaits: it is released only when the
|
|
241
|
+
* attempt ends without a commit. The publisher's beat derives its set from
|
|
242
|
+
* the agent registry, which does not list the target yet, so a reservation
|
|
243
|
+
* that was not held across them could be erased by this process's own
|
|
244
|
+
* heartbeat and handed straight to a peer.
|
|
245
|
+
*/
|
|
246
|
+
const resumeTo = async (sessionId) => {
|
|
247
|
+
const adoption = deps.binding.capture();
|
|
122
248
|
const agents = ctx.get('agents');
|
|
123
249
|
if (!agents) {
|
|
124
250
|
deps.notify(t('resume-unavailable'), { color: 'error' });
|
|
125
251
|
return { ok: false, reason: 'unavailable' };
|
|
126
252
|
}
|
|
127
|
-
|
|
253
|
+
// The attached session as of entry, so a rival switch that commits while
|
|
254
|
+
// the awaits below yield cannot be adopted over.
|
|
255
|
+
const entrySession = deps.binding.agent.session;
|
|
256
|
+
// Already attached: this is a no-op, not a switch.
|
|
257
|
+
//
|
|
258
|
+
// The live-adoption path below hands `backgroundHandles.get(targetId)` to
|
|
259
|
+
// `binding.switchTo()`, and a session this terminal is CURRENTLY attached
|
|
260
|
+
// to has no entry there — its handle is the binding's own `currentHandle`.
|
|
261
|
+
// Calling it with `undefined` therefore parks nothing, and the adoption's
|
|
262
|
+
// default disposition disposes the handle that IS running, so a second
|
|
263
|
+
// Enter on the `current` row stopped the live turn while reporting success.
|
|
264
|
+
// `attachToAgent()` has always short-circuited here; this is the same rule
|
|
265
|
+
// for the unified screen's `/resume` path.
|
|
266
|
+
if (String(sessionId) === String(entrySession.id))
|
|
267
|
+
return { ok: true };
|
|
268
|
+
// Switching away starts disposal without blocking the synchronous commit.
|
|
269
|
+
// Do not adopt that closing Agent (or reopen its still-held JSONL writer).
|
|
270
|
+
await deps.binding.waitForDisposal(sessionId);
|
|
271
|
+
if (!deps.binding.isCurrent(adoption))
|
|
272
|
+
return { ok: false, reason: 'cancelled' };
|
|
273
|
+
// A live agent of this process is already mounted here; there is nothing
|
|
274
|
+
// to claim and nothing that can be occupied. Adoption takes the live
|
|
275
|
+
// handle (parking the current one) with no occupancy round-trip.
|
|
276
|
+
const live = agents.get?.(SessionId(sessionId));
|
|
277
|
+
let reservation;
|
|
278
|
+
if (live === undefined) {
|
|
279
|
+
const reserved = await reserveDiskResume(sessionId);
|
|
280
|
+
if (!reserved.ok)
|
|
281
|
+
return reserved.result;
|
|
282
|
+
reservation = reserved.reservation;
|
|
283
|
+
}
|
|
284
|
+
if (await deps.sessionSwitchVetoed('resume', sessionId)) {
|
|
285
|
+
reservation?.abandon();
|
|
128
286
|
return { ok: false, reason: 'cancelled' };
|
|
287
|
+
}
|
|
129
288
|
await deps.settleCompaction();
|
|
130
|
-
|
|
131
|
-
|
|
289
|
+
if (!deps.binding.isCurrent(adoption) || deps.binding.agent.session !== entrySession) {
|
|
290
|
+
reservation?.abandon();
|
|
291
|
+
return { ok: false, reason: 'cancelled' };
|
|
292
|
+
}
|
|
293
|
+
// The target was read BEFORE those awaits. Re-read it in BOTH directions:
|
|
294
|
+
// the registry can have replaced or dropped that agent while we yielded
|
|
295
|
+
// (adopting the captured object would hand the screen a session nothing
|
|
296
|
+
// owns any more), and it can also have GROWN one — a peer action mounting
|
|
297
|
+
// this very session here means the disk path below would resume a log this
|
|
298
|
+
// process is already driving. `agent-view-projection.attach` has always made
|
|
299
|
+
// the first check.
|
|
300
|
+
const liveNow = agents.get?.(SessionId(sessionId));
|
|
301
|
+
if (liveNow !== live) {
|
|
302
|
+
reservation?.abandon();
|
|
303
|
+
return { ok: false, reason: 'cancelled' };
|
|
304
|
+
}
|
|
305
|
+
// A live target is adopted in place — the same path `/agentview` uses, so
|
|
306
|
+
// the session being left is parked rather than disposed of. Only a target
|
|
307
|
+
// with no live agent here goes back to the persistence backend.
|
|
308
|
+
if (live !== undefined)
|
|
309
|
+
return deps.adoptLive(live);
|
|
310
|
+
return resume(sessionId, 'agent-view', true, adoption, entrySession, reservation);
|
|
132
311
|
};
|
|
133
312
|
const newSessionWithTarget = async (target) => {
|
|
134
313
|
// The typed workspace target seam still creates a real Agent/session; it
|
|
@@ -181,6 +360,10 @@ export function createSessionResumeActions(ctx, state, options, deps) {
|
|
|
181
360
|
}
|
|
182
361
|
return false;
|
|
183
362
|
}
|
|
363
|
+
// Reserve BEFORE the factory runs: the moment `agents.create` returns, this
|
|
364
|
+
// process holds the only write handle on a log no peer has been told about
|
|
365
|
+
// yet, and the publisher would not name it until its next beat.
|
|
366
|
+
const reservation = await reserveCreatedSession(sessionId);
|
|
184
367
|
let handle;
|
|
185
368
|
try {
|
|
186
369
|
handle = await deps.binding.prepare(adoption, () => agents.create({
|
|
@@ -191,6 +374,7 @@ export function createSessionResumeActions(ctx, state, options, deps) {
|
|
|
191
374
|
}));
|
|
192
375
|
}
|
|
193
376
|
catch (error) {
|
|
377
|
+
reservation.abandon();
|
|
194
378
|
if (current()) {
|
|
195
379
|
const message = error instanceof Error ? error.message : String(error);
|
|
196
380
|
deps.notify(t('new-session-failed', { err: message }), { color: 'error', timeoutMs: 8000 });
|
|
@@ -199,6 +383,7 @@ export function createSessionResumeActions(ctx, state, options, deps) {
|
|
|
199
383
|
}
|
|
200
384
|
if (!current()) {
|
|
201
385
|
await deps.binding.abandon(handle);
|
|
386
|
+
reservation.abandon();
|
|
202
387
|
return false;
|
|
203
388
|
}
|
|
204
389
|
try {
|
|
@@ -210,30 +395,43 @@ export function createSessionResumeActions(ctx, state, options, deps) {
|
|
|
210
395
|
}
|
|
211
396
|
if (!current()) {
|
|
212
397
|
await deps.binding.abandon(handle);
|
|
398
|
+
reservation.abandon();
|
|
213
399
|
return false;
|
|
214
400
|
}
|
|
215
401
|
// Do not catch this synchronous commit tail. A post-commit setup failure
|
|
216
402
|
// is owned by binding.adopt(), which revokes the new live handle and must
|
|
217
403
|
// reject its caller rather than masquerade as an ordinary precommit false.
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
404
|
+
let committed = false;
|
|
405
|
+
try {
|
|
406
|
+
const result = deps.binding.adopt(handle, adoption, (committedBinding, disposePrevious) => {
|
|
407
|
+
const previousSessionId = String(committedBinding.agent.session.id);
|
|
408
|
+
// The target only becomes shared channel state inside the successful
|
|
409
|
+
// adoption tail. A losing prepared handle therefore cannot publish or
|
|
410
|
+
// roll back another workspace's cwd.
|
|
411
|
+
state.cwd = targetCwd;
|
|
412
|
+
state.displayCwd = targetDisplayCwd ?? deps.describeWorkspace(targetCwd).description ?? targetCwd;
|
|
413
|
+
deps.resetIdeSelection();
|
|
414
|
+
// Reset the input FIFO and the pending-decision indicators BEFORE the
|
|
415
|
+
// first emit: a submit enqueued from a session-changed subscriber must
|
|
416
|
+
// land on a fresh chain instead of behind the replaced session's parked
|
|
417
|
+
// promise (main's bind → clear → refresh order).
|
|
418
|
+
deps.clearStagedImages();
|
|
419
|
+
resetAndBind(handle, composed.agentPreset, route, false);
|
|
420
|
+
clearResumeTarget();
|
|
421
|
+
touchSession(handle.agent.id);
|
|
422
|
+
disposePrevious('dispose');
|
|
423
|
+
deps.notifySessionSwitched('new', String(handle.agent.id), previousSessionId);
|
|
424
|
+
return true;
|
|
425
|
+
});
|
|
426
|
+
committed = true;
|
|
427
|
+
return result;
|
|
428
|
+
}
|
|
429
|
+
finally {
|
|
430
|
+
if (committed)
|
|
431
|
+
reservation.settle();
|
|
432
|
+
else
|
|
433
|
+
reservation.abandon();
|
|
434
|
+
}
|
|
237
435
|
};
|
|
238
436
|
const newSession = () => newSessionWithTarget();
|
|
239
437
|
return { resumeInto, resumeTo, newSession, newSessionWithTarget };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-rewind.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/channel/session-rewind.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAsB,MAAM,wBAAwB,CAAA;AAC7E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,SAAS,EAAE,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;
|
|
1
|
+
{"version":3,"file":"session-rewind.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/channel/session-rewind.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAsB,MAAM,wBAAwB,CAAA;AAC7E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,SAAS,EAAE,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;AASvE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAC9C,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AAEvD,KAAK,OAAO,GAAG,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAA;AACtD,KAAK,WAAW,GAAG,IAAI,CAAC,YAAY,EAAE,SAAS,GAAG,KAAK,GAAG,UAAU,GAAG,OAAO,CAAC,CAAA;AAgB/E,4EAA4E;AAC5E,wBAAgB,oBAAoB,CAClC,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,CAAC,CAAA;IACjF,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACjC,MAAM,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAA;IAC9B,gBAAgB,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,UAAU,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,YAAY,EAAE,EAAE,WAAW,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,EAAE,SAAS,GAAG,MAAM,CAAA;IAC1K,qBAAqB,CAAC,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAA;CAC1F,IAEa,KAAK,OAAO,EAAE,OAAM,MAAM,GAAG,IAAW,KAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAsGhF"}
|
|
@@ -6,6 +6,7 @@ import { dispatchTuiDecision } from '../extension-events.js';
|
|
|
6
6
|
import { normalizeRewindDoneSummary } from './decisions.js';
|
|
7
7
|
import { composePreset, runningPresetOf } from '../presets.js';
|
|
8
8
|
import { attachSessionToWorkspace } from '../workspace.js';
|
|
9
|
+
import { reserveNewSession } from '../../sessionMounts.js';
|
|
9
10
|
async function waitForTurnEnd(session, fromSeq, timeoutMs) {
|
|
10
11
|
const deadline = Date.now() + timeoutMs;
|
|
11
12
|
while (Date.now() < deadline) {
|
|
@@ -65,6 +66,10 @@ export function createRewindToAction(ctx, state, deps) {
|
|
|
65
66
|
return null;
|
|
66
67
|
}
|
|
67
68
|
const composed = await composePreset(ctx, runningPresetOf(deps.binding.agent.session));
|
|
69
|
+
// Announce the id before the factory: the rewind creates the child's log
|
|
70
|
+
// here, and the publisher only learns the id from the registry on its next
|
|
71
|
+
// beat.
|
|
72
|
+
const { reservation } = await reserveNewSession(String(childId));
|
|
68
73
|
let handle;
|
|
69
74
|
try {
|
|
70
75
|
handle = await deps.binding.prepare(adoption, () => agents.create(liveSessionCreateOptions({
|
|
@@ -87,11 +92,13 @@ export function createRewindToAction(ctx, state, deps) {
|
|
|
87
92
|
})));
|
|
88
93
|
}
|
|
89
94
|
catch {
|
|
95
|
+
reservation.abandon();
|
|
90
96
|
deps.notify(t('rewind-create-failed'), { color: 'error' });
|
|
91
97
|
return null;
|
|
92
98
|
}
|
|
93
99
|
if (!deps.binding.isCurrent(adoption)) {
|
|
94
100
|
await deps.binding.abandon(handle);
|
|
101
|
+
reservation.abandon();
|
|
95
102
|
return null;
|
|
96
103
|
}
|
|
97
104
|
try {
|
|
@@ -102,27 +109,38 @@ export function createRewindToAction(ctx, state, deps) {
|
|
|
102
109
|
}
|
|
103
110
|
if (!deps.owner.current()) {
|
|
104
111
|
await deps.binding.abandon(handle);
|
|
112
|
+
reservation.abandon();
|
|
105
113
|
return null;
|
|
106
114
|
}
|
|
107
|
-
|
|
115
|
+
// `adoptForkedAgent` is the commit: the child is the session this process
|
|
116
|
+
// now drives, so the reservation hands over to the registry. It THROWS when
|
|
117
|
+
// the adoption transaction revokes the candidate, so it is guarded.
|
|
108
118
|
try {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
119
|
+
const sourceSessionId = deps.adoptForkedAgent(handle, adoption, snapshotLiveSessionEvents(handle.agent.session), composed.agentPreset, childId);
|
|
120
|
+
reservation.settle();
|
|
121
|
+
try {
|
|
122
|
+
void dispatchTuiDecision(ctx, 'tui/rewind-done', {
|
|
123
|
+
text: row.text,
|
|
124
|
+
mode,
|
|
125
|
+
boundarySeq: boundary,
|
|
126
|
+
sourceSessionId,
|
|
127
|
+
childSessionId: String(childId),
|
|
128
|
+
sessionId: String(childId),
|
|
129
|
+
cwd: state.cwd,
|
|
130
|
+
}, normalizeRewindDoneSummary).then(summary => {
|
|
131
|
+
if (typeof summary === 'string')
|
|
132
|
+
deps.notify(summary, { timeoutMs: 6000 });
|
|
133
|
+
}).catch((error) => ctx.logger.warn('dsh-tui: tui/rewind-done dispatch failed: %o', error));
|
|
134
|
+
}
|
|
135
|
+
catch (error) {
|
|
136
|
+
ctx.logger.warn('dsh-tui: tui/rewind-done dispatch failed: %o', error);
|
|
137
|
+
}
|
|
138
|
+
deps.notifySessionSwitched('rewind', String(childId), sourceSessionId);
|
|
139
|
+
return row.text;
|
|
121
140
|
}
|
|
122
141
|
catch (error) {
|
|
123
|
-
|
|
142
|
+
reservation.abandon();
|
|
143
|
+
throw error;
|
|
124
144
|
}
|
|
125
|
-
deps.notifySessionSwitched('rewind', String(childId), sourceSessionId);
|
|
126
|
-
return row.text;
|
|
127
145
|
};
|
|
128
146
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-tree-actions.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/channel/session-tree-actions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAsB,MAAM,wBAAwB,CAAA;AAC7E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,SAAS,EAAE,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;
|
|
1
|
+
{"version":3,"file":"session-tree-actions.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/channel/session-tree-actions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAsB,MAAM,wBAAwB,CAAA;AAC7E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,SAAS,EAAE,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAUvE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAC9C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAE9C,KAAK,OAAO,GAAG,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAA;AACtD,KAAK,eAAe,GAAG,IAAI,CAAC,YAAY,EAAE,SAAS,GAAG,KAAK,GAAG,UAAU,GAAG,OAAO,CAAC,CAAA;AAYnF,+GAA+G;AAC/G,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,eAAe,EACtB,IAAI,EAAE;IACJ,KAAK,EAAE,IAAI,CAAC,YAAY,EAAE,SAAS,CAAC,CAAA;IACpC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,SAAS,CAAC,CAAA;IACjF,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACjC,MAAM,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAA;IAC9B,gBAAgB,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,UAAU,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,YAAY,EAAE,EAAE,WAAW,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,EAAE,SAAS,GAAG,MAAM,CAAA;IAC1K,qBAAqB,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAA;CACnG,IAEa,WAAW,MAAM,EAAE,KAAK,MAAM,EAAE,OAAM,QAAQ,GAAG,MAAiB,KAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAyH1G"}
|
|
@@ -6,6 +6,7 @@ import { readPersistedSession } from '../compat/persistence.js';
|
|
|
6
6
|
import { closeLiveForkTurn } from '../compat/liveSession.js';
|
|
7
7
|
import { composePreset, resolvePersistedPreset, runningPresetOf } from '../presets.js';
|
|
8
8
|
import { attachSessionToWorkspace } from '../workspace.js';
|
|
9
|
+
import { reserveNewSession } from '../../sessionMounts.js';
|
|
9
10
|
import { forkTarget, rewindTarget, turnUserText } from '../sessionTree.js';
|
|
10
11
|
async function waitForTurnEnd(session, fromSeq, timeoutMs) {
|
|
11
12
|
const deadline = Date.now() + timeoutMs;
|
|
@@ -85,6 +86,9 @@ export function createTreeRewindAction(ctx, state, deps) {
|
|
|
85
86
|
if (target.closeTurn !== undefined && !closeAfterCreate) {
|
|
86
87
|
appendInterruptedTurnEnd(seed, target.closeTurn);
|
|
87
88
|
}
|
|
89
|
+
// Announce the id before the factory: the child's log is created here, and
|
|
90
|
+
// the publisher only learns the id from the registry on its next beat.
|
|
91
|
+
const { reservation } = await reserveNewSession(String(childId));
|
|
88
92
|
let handle;
|
|
89
93
|
try {
|
|
90
94
|
handle = await deps.binding.prepare(adoption, () => agents.create(liveSessionCreateOptions({
|
|
@@ -112,11 +116,13 @@ export function createTreeRewindAction(ctx, state, deps) {
|
|
|
112
116
|
})));
|
|
113
117
|
}
|
|
114
118
|
catch {
|
|
119
|
+
reservation.abandon();
|
|
115
120
|
deps.notify(t('rewind-create-failed'), { color: 'error' });
|
|
116
121
|
return null;
|
|
117
122
|
}
|
|
118
123
|
if (!deps.binding.isCurrent(adoption)) {
|
|
119
124
|
await deps.binding.abandon(handle);
|
|
125
|
+
reservation.abandon();
|
|
120
126
|
return null;
|
|
121
127
|
}
|
|
122
128
|
try {
|
|
@@ -127,12 +133,22 @@ export function createTreeRewindAction(ctx, state, deps) {
|
|
|
127
133
|
}
|
|
128
134
|
if (!deps.owner.current() || deps.binding.agent.session !== entrySession) {
|
|
129
135
|
await deps.binding.abandon(handle);
|
|
136
|
+
reservation.abandon();
|
|
130
137
|
deps.notify(t('rewind-session-changed'), { color: 'error' });
|
|
131
138
|
return null;
|
|
132
139
|
}
|
|
133
140
|
const replay = closeAfterCreate || mode === 'rewind' ? snapshotLiveSessionEvents(handle.agent.session) : seed;
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
141
|
+
// `adoptForkedAgent` is the commit, and it THROWS when the adoption
|
|
142
|
+
// transaction revokes the candidate.
|
|
143
|
+
try {
|
|
144
|
+
const sourceSessionId = deps.adoptForkedAgent(handle, adoption, replay, composed.agentPreset, childId);
|
|
145
|
+
reservation.settle();
|
|
146
|
+
deps.notifySessionSwitched(mode === 'fork' ? 'fork' : 'rewind', String(childId), sourceSessionId);
|
|
147
|
+
return restoredText;
|
|
148
|
+
}
|
|
149
|
+
catch (error) {
|
|
150
|
+
reservation.abandon();
|
|
151
|
+
throw error;
|
|
152
|
+
}
|
|
137
153
|
};
|
|
138
154
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings-host.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/channel/settings-host.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAGlD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"settings-host.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/channel/settings-host.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAGlD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAMvD,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,EAAE,YAAY,GAAE,MAAM,IAAsB,GAAG,IAAI,CAAC,YAAY,EAAE,cAAc,GAAG,eAAe,GAAG,uBAAuB,CAAC,CAqT5K"}
|