@jingyi0605/codingns4dsh 0.2.0-beta.2 → 0.2.0-rc.3
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.en.md +4 -4
- package/README.md +18 -7
- package/assets/provider-icons/antigravity.svg +39 -0
- package/assets/provider-icons/codebuddy.svg +37 -0
- package/assets/provider-icons/cursor-cli.svg +1 -0
- package/assets/provider-icons/kiro-cli.svg +11 -0
- package/assets/provider-icons/minimax-code.svg +4 -0
- package/assets/provider-icons/qoder-cn.svg +5 -0
- package/assets/provider-icons/qoder.svg +5 -0
- package/assets/provider-icons/workbuddy.svg +29 -0
- package/assets/provider-icons/zcode.svg +14 -0
- package/data/build/dist/bootstrap/dsh-peer-host-preboot-shim.d.ts.map +1 -1
- package/data/build/dist/bootstrap/dsh-peer-host-preboot-shim.js +78 -1
- package/data/build/dist/bootstrap/dsh-peer-host-preboot-shim.js.map +1 -1
- package/data/build/dist/client/account-bar.d.ts +2 -1
- package/data/build/dist/client/account-bar.d.ts.map +1 -1
- package/data/build/dist/client/account-bar.js +21 -16
- package/data/build/dist/client/account-bar.js.map +1 -1
- package/data/build/dist/client/bundle.js +8147 -2158
- package/data/build/dist/client/bundle.js.map +1 -1
- package/data/build/dist/client/cli-catalog.d.ts +1 -1
- package/data/build/dist/client/cli-catalog.d.ts.map +1 -1
- package/data/build/dist/client/cli-catalog.js +11 -5
- package/data/build/dist/client/cli-catalog.js.map +1 -1
- package/data/build/dist/client/cli-slots.d.ts.map +1 -1
- package/data/build/dist/client/cli-slots.js +127 -21
- package/data/build/dist/client/cli-slots.js.map +1 -1
- package/data/build/dist/client/debug/ui.d.ts +2 -1
- package/data/build/dist/client/debug/ui.d.ts.map +1 -1
- package/data/build/dist/client/debug/ui.js +41 -34
- package/data/build/dist/client/debug/ui.js.map +1 -1
- package/data/build/dist/client/delegate-command.d.ts +17 -0
- package/data/build/dist/client/delegate-command.d.ts.map +1 -0
- package/data/build/dist/client/delegate-command.js +597 -0
- package/data/build/dist/client/delegate-command.js.map +1 -0
- package/data/build/dist/client/delegate-plan.d.ts +40 -0
- package/data/build/dist/client/delegate-plan.d.ts.map +1 -0
- package/data/build/dist/client/delegate-plan.js +63 -0
- package/data/build/dist/client/delegate-plan.js.map +1 -0
- package/data/build/dist/client/delegate-ui-dom.d.ts +86 -0
- package/data/build/dist/client/delegate-ui-dom.d.ts.map +1 -0
- package/data/build/dist/client/delegate-ui-dom.js +647 -0
- package/data/build/dist/client/delegate-ui-dom.js.map +1 -0
- package/data/build/dist/client/external-tool-stream.d.ts.map +1 -1
- package/data/build/dist/client/external-tool-stream.js +44 -36
- package/data/build/dist/client/external-tool-stream.js.map +1 -1
- package/data/build/dist/client/features/cli-adapters.d.ts +7 -2
- package/data/build/dist/client/features/cli-adapters.d.ts.map +1 -1
- package/data/build/dist/client/features/cli-adapters.js +153 -95
- package/data/build/dist/client/features/cli-adapters.js.map +1 -1
- package/data/build/dist/client/features/debug.d.ts.map +1 -1
- package/data/build/dist/client/features/debug.js +5 -3
- package/data/build/dist/client/features/debug.js.map +1 -1
- package/data/build/dist/client/features/file-management.d.ts.map +1 -1
- package/data/build/dist/client/features/file-management.js +7 -4
- package/data/build/dist/client/features/file-management.js.map +1 -1
- package/data/build/dist/client/features/lan-access-panel.js +10 -10
- package/data/build/dist/client/features/lan-access-panel.js.map +1 -1
- package/data/build/dist/client/features/lan-access.d.ts.map +1 -1
- package/data/build/dist/client/features/lan-access.js +8 -3
- package/data/build/dist/client/features/lan-access.js.map +1 -1
- package/data/build/dist/client/features/login-protection-panel.d.ts.map +1 -1
- package/data/build/dist/client/features/login-protection-panel.js +9 -7
- package/data/build/dist/client/features/login-protection-panel.js.map +1 -1
- package/data/build/dist/client/features/login-protection.js +2 -2
- package/data/build/dist/client/features/login-protection.js.map +1 -1
- package/data/build/dist/client/features/mobile-access-panel.d.ts.map +1 -1
- package/data/build/dist/client/features/mobile-access-panel.js +8 -7
- package/data/build/dist/client/features/mobile-access-panel.js.map +1 -1
- package/data/build/dist/client/features/mobile-access.d.ts.map +1 -1
- package/data/build/dist/client/features/mobile-access.js +6 -2
- package/data/build/dist/client/features/mobile-access.js.map +1 -1
- package/data/build/dist/client/features/peer-host.d.ts +6 -4
- package/data/build/dist/client/features/peer-host.d.ts.map +1 -1
- package/data/build/dist/client/features/peer-host.js +459 -27
- package/data/build/dist/client/features/peer-host.js.map +1 -1
- package/data/build/dist/client/features/reverse-proxy.js +2 -2
- package/data/build/dist/client/features/reverse-proxy.js.map +1 -1
- package/data/build/dist/client/features/terminal-enhancement.js +2 -2
- package/data/build/dist/client/features/terminal-enhancement.js.map +1 -1
- package/data/build/dist/client/features/workspace-session-enhancement-panel.js +1 -1
- package/data/build/dist/client/features/workspace-session-enhancement-panel.js.map +1 -1
- package/data/build/dist/client/features/workspace-session-enhancement.d.ts.map +1 -1
- package/data/build/dist/client/features/workspace-session-enhancement.js +8 -3
- package/data/build/dist/client/features/workspace-session-enhancement.js.map +1 -1
- package/data/build/dist/client/file-management-dom.d.ts +3 -0
- package/data/build/dist/client/file-management-dom.d.ts.map +1 -1
- package/data/build/dist/client/file-management-dom.js +41 -30
- package/data/build/dist/client/file-management-dom.js.map +1 -1
- package/data/build/dist/client/git-history-graph.d.ts +2 -2
- package/data/build/dist/client/git-history-graph.d.ts.map +1 -1
- package/data/build/dist/client/git-history-graph.js +2 -2
- package/data/build/dist/client/git-history-graph.js.map +1 -1
- package/data/build/dist/client/git-management.d.ts +2 -0
- package/data/build/dist/client/git-management.d.ts.map +1 -1
- package/data/build/dist/client/git-management.js +103 -75
- package/data/build/dist/client/git-management.js.map +1 -1
- package/data/build/dist/client/git-workspace-events.d.ts +7 -0
- package/data/build/dist/client/git-workspace-events.d.ts.map +1 -0
- package/data/build/dist/client/git-workspace-events.js +32 -0
- package/data/build/dist/client/git-workspace-events.js.map +1 -0
- package/data/build/dist/client/index.d.ts +2 -0
- package/data/build/dist/client/index.d.ts.map +1 -1
- package/data/build/dist/client/index.js +6 -5
- package/data/build/dist/client/index.js.map +1 -1
- package/data/build/dist/client/locale.d.ts +7 -0
- package/data/build/dist/client/locale.d.ts.map +1 -1
- package/data/build/dist/client/locale.js +140 -42
- package/data/build/dist/client/locale.js.map +1 -1
- package/data/build/dist/client/locales/debug.d.ts +9 -0
- package/data/build/dist/client/locales/debug.d.ts.map +1 -0
- package/data/build/dist/client/locales/debug.js +163 -0
- package/data/build/dist/client/locales/debug.js.map +1 -0
- package/data/build/dist/client/locales/fileWorkspace.d.ts +9 -0
- package/data/build/dist/client/locales/fileWorkspace.d.ts.map +1 -0
- package/data/build/dist/client/locales/fileWorkspace.js +139 -0
- package/data/build/dist/client/locales/fileWorkspace.js.map +1 -0
- package/data/build/dist/client/locales/git.d.ts +9 -0
- package/data/build/dist/client/locales/git.d.ts.map +1 -0
- package/data/build/dist/client/locales/git.js +223 -0
- package/data/build/dist/client/locales/git.js.map +1 -0
- package/data/build/dist/client/locales/panels.d.ts +9 -0
- package/data/build/dist/client/locales/panels.d.ts.map +1 -0
- package/data/build/dist/client/locales/panels.js +33 -0
- package/data/build/dist/client/locales/panels.js.map +1 -0
- package/data/build/dist/client/locales/peerHost.d.ts +9 -0
- package/data/build/dist/client/locales/peerHost.d.ts.map +1 -0
- package/data/build/dist/client/locales/peerHost.js +153 -0
- package/data/build/dist/client/locales/peerHost.js.map +1 -0
- package/data/build/dist/client/locales/peerHostWorkspace.d.ts +9 -0
- package/data/build/dist/client/locales/peerHostWorkspace.d.ts.map +1 -0
- package/data/build/dist/client/locales/peerHostWorkspace.js +69 -0
- package/data/build/dist/client/locales/peerHostWorkspace.js.map +1 -0
- package/data/build/dist/client/locales/terminalAuth.d.ts +9 -0
- package/data/build/dist/client/locales/terminalAuth.d.ts.map +1 -0
- package/data/build/dist/client/locales/terminalAuth.js +71 -0
- package/data/build/dist/client/locales/terminalAuth.js.map +1 -0
- package/data/build/dist/client/locales/usage.d.ts +9 -0
- package/data/build/dist/client/locales/usage.d.ts.map +1 -0
- package/data/build/dist/client/locales/usage.js +215 -0
- package/data/build/dist/client/locales/usage.js.map +1 -0
- package/data/build/dist/client/mobile-session-interaction.d.ts +44 -0
- package/data/build/dist/client/mobile-session-interaction.d.ts.map +1 -0
- package/data/build/dist/client/mobile-session-interaction.js +308 -0
- package/data/build/dist/client/mobile-session-interaction.js.map +1 -0
- package/data/build/dist/client/mobile-sidebar-gestures.d.ts +55 -7
- package/data/build/dist/client/mobile-sidebar-gestures.d.ts.map +1 -1
- package/data/build/dist/client/mobile-sidebar-gestures.js +339 -40
- package/data/build/dist/client/mobile-sidebar-gestures.js.map +1 -1
- package/data/build/dist/client/mobile-sidebar-rail-dom.d.ts +10 -2
- package/data/build/dist/client/mobile-sidebar-rail-dom.d.ts.map +1 -1
- package/data/build/dist/client/mobile-sidebar-rail-dom.js +14 -6
- package/data/build/dist/client/mobile-sidebar-rail-dom.js.map +1 -1
- package/data/build/dist/client/model-catalog-cache.d.ts +5 -0
- package/data/build/dist/client/model-catalog-cache.d.ts.map +1 -0
- package/data/build/dist/client/model-catalog-cache.js +58 -0
- package/data/build/dist/client/model-catalog-cache.js.map +1 -0
- package/data/build/dist/client/peer-host-aggregate-refresh.d.ts +7 -0
- package/data/build/dist/client/peer-host-aggregate-refresh.d.ts.map +1 -1
- package/data/build/dist/client/peer-host-aggregate-refresh.js +13 -1
- package/data/build/dist/client/peer-host-aggregate-refresh.js.map +1 -1
- package/data/build/dist/client/peer-host-connection-button.d.ts +14 -1
- package/data/build/dist/client/peer-host-connection-button.d.ts.map +1 -1
- package/data/build/dist/client/peer-host-connection-button.js +12 -4
- package/data/build/dist/client/peer-host-connection-button.js.map +1 -1
- package/data/build/dist/client/peer-host-management-panel.d.ts +3 -0
- package/data/build/dist/client/peer-host-management-panel.d.ts.map +1 -1
- package/data/build/dist/client/peer-host-management-panel.js +83 -79
- package/data/build/dist/client/peer-host-management-panel.js.map +1 -1
- package/data/build/dist/client/peer-host-native-projection.d.ts +17 -1
- package/data/build/dist/client/peer-host-native-projection.d.ts.map +1 -1
- package/data/build/dist/client/peer-host-native-projection.js +54 -8
- package/data/build/dist/client/peer-host-native-projection.js.map +1 -1
- package/data/build/dist/client/peer-host-native-store-projection.d.ts +6 -2
- package/data/build/dist/client/peer-host-native-store-projection.d.ts.map +1 -1
- package/data/build/dist/client/peer-host-native-store-projection.js +308 -10
- package/data/build/dist/client/peer-host-native-store-projection.js.map +1 -1
- package/data/build/dist/client/peer-host-scoped-client.js +5 -5
- package/data/build/dist/client/peer-host-scoped-client.js.map +1 -1
- package/data/build/dist/client/peer-host-workspace-tab.d.ts +8 -0
- package/data/build/dist/client/peer-host-workspace-tab.d.ts.map +1 -1
- package/data/build/dist/client/peer-host-workspace-tab.js +48 -28
- package/data/build/dist/client/peer-host-workspace-tab.js.map +1 -1
- package/data/build/dist/client/provider-icon-assets.js +18 -0
- package/data/build/dist/client/provider-icon-assets.js.map +1 -1
- package/data/build/dist/client/provider-icons.d.ts +8 -2
- package/data/build/dist/client/provider-icons.d.ts.map +1 -1
- package/data/build/dist/client/provider-icons.js +28 -7
- package/data/build/dist/client/provider-icons.js.map +1 -1
- package/data/build/dist/client/pwa-install-prompt.d.ts +4 -1
- package/data/build/dist/client/pwa-install-prompt.d.ts.map +1 -1
- package/data/build/dist/client/pwa-install-prompt.js +8 -7
- package/data/build/dist/client/pwa-install-prompt.js.map +1 -1
- package/data/build/dist/client/quick-phrase-layout.d.ts +11 -0
- package/data/build/dist/client/quick-phrase-layout.d.ts.map +1 -1
- package/data/build/dist/client/quick-phrase-layout.js +20 -0
- package/data/build/dist/client/quick-phrase-layout.js.map +1 -1
- package/data/build/dist/client/quick-phrase-slot.d.ts.map +1 -1
- package/data/build/dist/client/quick-phrase-slot.js +20 -8
- package/data/build/dist/client/quick-phrase-slot.js.map +1 -1
- package/data/build/dist/client/remote-web-context.js +10 -6
- package/data/build/dist/client/remote-web-context.js.map +1 -1
- package/data/build/dist/client/service-tier.d.ts +54 -0
- package/data/build/dist/client/service-tier.d.ts.map +1 -0
- package/data/build/dist/client/service-tier.js +78 -0
- package/data/build/dist/client/service-tier.js.map +1 -0
- package/data/build/dist/client/session-changed-files-view.d.ts +8 -1
- package/data/build/dist/client/session-changed-files-view.d.ts.map +1 -1
- package/data/build/dist/client/session-changed-files-view.js +71 -28
- package/data/build/dist/client/session-changed-files-view.js.map +1 -1
- package/data/build/dist/client/settings-anchor.d.ts +9 -3
- package/data/build/dist/client/settings-anchor.d.ts.map +1 -1
- package/data/build/dist/client/settings-anchor.js +8 -2
- package/data/build/dist/client/settings-anchor.js.map +1 -1
- package/data/build/dist/client/settings-promo-styles.d.ts +28 -0
- package/data/build/dist/client/settings-promo-styles.d.ts.map +1 -0
- package/data/build/dist/client/settings-promo-styles.js +58 -0
- package/data/build/dist/client/settings-promo-styles.js.map +1 -0
- package/data/build/dist/client/settings-promo.d.ts +14 -0
- package/data/build/dist/client/settings-promo.d.ts.map +1 -0
- package/data/build/dist/client/settings-promo.js +68 -0
- package/data/build/dist/client/settings-promo.js.map +1 -0
- package/data/build/dist/client/settings-section.d.ts +2 -1
- package/data/build/dist/client/settings-section.d.ts.map +1 -1
- package/data/build/dist/client/settings-section.js +10 -7
- package/data/build/dist/client/settings-section.js.map +1 -1
- package/data/build/dist/client/subscription-slot.d.ts +4 -1
- package/data/build/dist/client/subscription-slot.d.ts.map +1 -1
- package/data/build/dist/client/subscription-slot.js +497 -56
- package/data/build/dist/client/subscription-slot.js.map +1 -1
- package/data/build/dist/client/terminal/model.d.ts +94 -4
- package/data/build/dist/client/terminal/model.d.ts.map +1 -1
- package/data/build/dist/client/terminal/model.js +392 -33
- package/data/build/dist/client/terminal/model.js.map +1 -1
- package/data/build/dist/client/terminal/recovery.d.ts +16 -1
- package/data/build/dist/client/terminal/recovery.d.ts.map +1 -1
- package/data/build/dist/client/terminal/recovery.js +101 -39
- package/data/build/dist/client/terminal/recovery.js.map +1 -1
- package/data/build/dist/client/terminal/styles.d.ts +10 -0
- package/data/build/dist/client/terminal/styles.d.ts.map +1 -1
- package/data/build/dist/client/terminal/styles.js +27 -3
- package/data/build/dist/client/terminal/styles.js.map +1 -1
- package/data/build/dist/client/terminal/ui.d.ts +3 -2
- package/data/build/dist/client/terminal/ui.d.ts.map +1 -1
- package/data/build/dist/client/terminal/ui.js +216 -103
- package/data/build/dist/client/terminal/ui.js.map +1 -1
- package/data/build/dist/client/terminal/xterm-view.d.ts +8 -1
- package/data/build/dist/client/terminal/xterm-view.d.ts.map +1 -1
- package/data/build/dist/client/terminal/xterm-view.js +394 -34
- package/data/build/dist/client/terminal/xterm-view.js.map +1 -1
- package/data/build/dist/client/workspace-session-archive-dom.d.ts +3 -0
- package/data/build/dist/client/workspace-session-archive-dom.d.ts.map +1 -1
- package/data/build/dist/client/workspace-session-archive-dom.js +131 -45
- package/data/build/dist/client/workspace-session-archive-dom.js.map +1 -1
- package/data/build/dist/client/workspace-session-logo-dom.d.ts +3 -0
- package/data/build/dist/client/workspace-session-logo-dom.d.ts.map +1 -1
- package/data/build/dist/client/workspace-session-logo-dom.js +3 -1
- package/data/build/dist/client/workspace-session-logo-dom.js.map +1 -1
- package/data/build/dist/client/workspace-session-visibility-dom.d.ts +3 -0
- package/data/build/dist/client/workspace-session-visibility-dom.d.ts.map +1 -1
- package/data/build/dist/client/workspace-session-visibility-dom.js +46 -17
- package/data/build/dist/client/workspace-session-visibility-dom.js.map +1 -1
- package/data/build/dist/dsh-capabilities/client/primitives-adapter.d.ts +10 -0
- package/data/build/dist/dsh-capabilities/client/primitives-adapter.d.ts.map +1 -1
- package/data/build/dist/dsh-capabilities/client/primitives-adapter.js +20 -0
- package/data/build/dist/dsh-capabilities/client/primitives-adapter.js.map +1 -1
- package/data/build/dist/host/browser-text.d.ts +30 -0
- package/data/build/dist/host/browser-text.d.ts.map +1 -0
- package/data/build/dist/host/browser-text.js +105 -0
- package/data/build/dist/host/browser-text.js.map +1 -0
- package/data/build/dist/host/cli-adapters/acp-cli-driver.d.ts +58 -0
- package/data/build/dist/host/cli-adapters/acp-cli-driver.d.ts.map +1 -0
- package/data/build/dist/host/cli-adapters/acp-cli-driver.js +271 -0
- package/data/build/dist/host/cli-adapters/acp-cli-driver.js.map +1 -0
- package/data/build/dist/host/cli-adapters/antigravity-driver.d.ts +30 -0
- package/data/build/dist/host/cli-adapters/antigravity-driver.d.ts.map +1 -0
- package/data/build/dist/host/cli-adapters/antigravity-driver.js +210 -0
- package/data/build/dist/host/cli-adapters/antigravity-driver.js.map +1 -0
- package/data/build/dist/host/cli-adapters/claude-driver.d.ts +28 -2
- package/data/build/dist/host/cli-adapters/claude-driver.d.ts.map +1 -1
- package/data/build/dist/host/cli-adapters/claude-driver.js +74 -4
- package/data/build/dist/host/cli-adapters/claude-driver.js.map +1 -1
- package/data/build/dist/host/cli-adapters/claude-model-options.d.ts.map +1 -1
- package/data/build/dist/host/cli-adapters/claude-model-options.js +22 -9
- package/data/build/dist/host/cli-adapters/claude-model-options.js.map +1 -1
- package/data/build/dist/host/cli-adapters/codebuddy-driver.d.ts +139 -0
- package/data/build/dist/host/cli-adapters/codebuddy-driver.d.ts.map +1 -0
- package/data/build/dist/host/cli-adapters/codebuddy-driver.js +1721 -0
- package/data/build/dist/host/cli-adapters/codebuddy-driver.js.map +1 -0
- package/data/build/dist/host/cli-adapters/codebuddy-subscription.d.ts +53 -0
- package/data/build/dist/host/cli-adapters/codebuddy-subscription.d.ts.map +1 -0
- package/data/build/dist/host/cli-adapters/codebuddy-subscription.js +778 -0
- package/data/build/dist/host/cli-adapters/codebuddy-subscription.js.map +1 -0
- package/data/build/dist/host/cli-adapters/codex-driver.d.ts +22 -0
- package/data/build/dist/host/cli-adapters/codex-driver.d.ts.map +1 -1
- package/data/build/dist/host/cli-adapters/codex-driver.js +254 -7
- package/data/build/dist/host/cli-adapters/codex-driver.js.map +1 -1
- package/data/build/dist/host/cli-adapters/command-code-driver.d.ts +43 -3
- package/data/build/dist/host/cli-adapters/command-code-driver.d.ts.map +1 -1
- package/data/build/dist/host/cli-adapters/command-code-driver.js +681 -74
- package/data/build/dist/host/cli-adapters/command-code-driver.js.map +1 -1
- package/data/build/dist/host/cli-adapters/command-code-history.d.ts +147 -0
- package/data/build/dist/host/cli-adapters/command-code-history.d.ts.map +1 -0
- package/data/build/dist/host/cli-adapters/command-code-history.js +659 -0
- package/data/build/dist/host/cli-adapters/command-code-history.js.map +1 -0
- package/data/build/dist/host/cli-adapters/cursor-driver.d.ts +12 -0
- package/data/build/dist/host/cli-adapters/cursor-driver.d.ts.map +1 -0
- package/data/build/dist/host/cli-adapters/cursor-driver.js +20 -0
- package/data/build/dist/host/cli-adapters/cursor-driver.js.map +1 -0
- package/data/build/dist/host/cli-adapters/custom-upstream-classifier.d.ts +67 -0
- package/data/build/dist/host/cli-adapters/custom-upstream-classifier.d.ts.map +1 -0
- package/data/build/dist/host/cli-adapters/custom-upstream-classifier.js +169 -0
- package/data/build/dist/host/cli-adapters/custom-upstream-classifier.js.map +1 -0
- package/data/build/dist/host/cli-adapters/delegate-dispatch.d.ts +48 -0
- package/data/build/dist/host/cli-adapters/delegate-dispatch.d.ts.map +1 -0
- package/data/build/dist/host/cli-adapters/delegate-dispatch.js +111 -0
- package/data/build/dist/host/cli-adapters/delegate-dispatch.js.map +1 -0
- package/data/build/dist/host/cli-adapters/delegation-authorization.d.ts +19 -0
- package/data/build/dist/host/cli-adapters/delegation-authorization.d.ts.map +1 -0
- package/data/build/dist/host/cli-adapters/delegation-authorization.js +49 -0
- package/data/build/dist/host/cli-adapters/delegation-authorization.js.map +1 -0
- package/data/build/dist/host/cli-adapters/delegation-mention-rewrite.d.ts +34 -0
- package/data/build/dist/host/cli-adapters/delegation-mention-rewrite.d.ts.map +1 -0
- package/data/build/dist/host/cli-adapters/delegation-mention-rewrite.js +121 -0
- package/data/build/dist/host/cli-adapters/delegation-mention-rewrite.js.map +1 -0
- package/data/build/dist/host/cli-adapters/desktop-app-runtime.d.ts +32 -0
- package/data/build/dist/host/cli-adapters/desktop-app-runtime.d.ts.map +1 -0
- package/data/build/dist/host/cli-adapters/desktop-app-runtime.js +121 -0
- package/data/build/dist/host/cli-adapters/desktop-app-runtime.js.map +1 -0
- package/data/build/dist/host/cli-adapters/driver.d.ts +6 -0
- package/data/build/dist/host/cli-adapters/driver.d.ts.map +1 -1
- package/data/build/dist/host/cli-adapters/dsh-message-projector.d.ts.map +1 -1
- package/data/build/dist/host/cli-adapters/dsh-message-projector.js +5 -4
- package/data/build/dist/host/cli-adapters/dsh-message-projector.js.map +1 -1
- package/data/build/dist/host/cli-adapters/dsh-virtual-providers.d.ts +16 -0
- package/data/build/dist/host/cli-adapters/dsh-virtual-providers.d.ts.map +1 -0
- package/data/build/dist/host/cli-adapters/dsh-virtual-providers.js +73 -0
- package/data/build/dist/host/cli-adapters/dsh-virtual-providers.js.map +1 -0
- package/data/build/dist/host/cli-adapters/feature.d.ts.map +1 -1
- package/data/build/dist/host/cli-adapters/feature.js +459 -26
- package/data/build/dist/host/cli-adapters/feature.js.map +1 -1
- package/data/build/dist/host/cli-adapters/gemini-driver.d.ts.map +1 -1
- package/data/build/dist/host/cli-adapters/gemini-driver.js +21 -5
- package/data/build/dist/host/cli-adapters/gemini-driver.js.map +1 -1
- package/data/build/dist/host/cli-adapters/grok-driver.d.ts.map +1 -1
- package/data/build/dist/host/cli-adapters/grok-driver.js +24 -7
- package/data/build/dist/host/cli-adapters/grok-driver.js.map +1 -1
- package/data/build/dist/host/cli-adapters/json-rpc-process.d.ts +22 -6
- package/data/build/dist/host/cli-adapters/json-rpc-process.d.ts.map +1 -1
- package/data/build/dist/host/cli-adapters/json-rpc-process.js +118 -21
- package/data/build/dist/host/cli-adapters/json-rpc-process.js.map +1 -1
- package/data/build/dist/host/cli-adapters/kimi-driver.d.ts.map +1 -1
- package/data/build/dist/host/cli-adapters/kimi-driver.js +25 -4
- package/data/build/dist/host/cli-adapters/kimi-driver.js.map +1 -1
- package/data/build/dist/host/cli-adapters/kiro-driver.d.ts +12 -0
- package/data/build/dist/host/cli-adapters/kiro-driver.d.ts.map +1 -0
- package/data/build/dist/host/cli-adapters/kiro-driver.js +18 -0
- package/data/build/dist/host/cli-adapters/kiro-driver.js.map +1 -0
- package/data/build/dist/host/cli-adapters/legacy-session-adapter.d.ts +11 -2
- package/data/build/dist/host/cli-adapters/legacy-session-adapter.d.ts.map +1 -1
- package/data/build/dist/host/cli-adapters/legacy-session-adapter.js +26 -6
- package/data/build/dist/host/cli-adapters/legacy-session-adapter.js.map +1 -1
- package/data/build/dist/host/cli-adapters/mcode-catalog.d.ts +23 -0
- package/data/build/dist/host/cli-adapters/mcode-catalog.d.ts.map +1 -0
- package/data/build/dist/host/cli-adapters/mcode-catalog.js +120 -0
- package/data/build/dist/host/cli-adapters/mcode-catalog.js.map +1 -0
- package/data/build/dist/host/cli-adapters/mcode-driver.d.ts +56 -0
- package/data/build/dist/host/cli-adapters/mcode-driver.d.ts.map +1 -0
- package/data/build/dist/host/cli-adapters/mcode-driver.js +544 -0
- package/data/build/dist/host/cli-adapters/mcode-driver.js.map +1 -0
- package/data/build/dist/host/cli-adapters/model-catalog.d.ts +35 -5
- package/data/build/dist/host/cli-adapters/model-catalog.d.ts.map +1 -1
- package/data/build/dist/host/cli-adapters/model-catalog.js +213 -8
- package/data/build/dist/host/cli-adapters/model-catalog.js.map +1 -1
- package/data/build/dist/host/cli-adapters/native-subagent-dispatch.d.ts +81 -0
- package/data/build/dist/host/cli-adapters/native-subagent-dispatch.d.ts.map +1 -0
- package/data/build/dist/host/cli-adapters/native-subagent-dispatch.js +299 -0
- package/data/build/dist/host/cli-adapters/native-subagent-dispatch.js.map +1 -0
- package/data/build/dist/host/cli-adapters/native-subagent-holder.d.ts +4 -0
- package/data/build/dist/host/cli-adapters/native-subagent-holder.d.ts.map +1 -0
- package/data/build/dist/host/cli-adapters/native-subagent-holder.js +4 -0
- package/data/build/dist/host/cli-adapters/native-subagent-holder.js.map +1 -0
- package/data/build/dist/host/cli-adapters/native-team-proxy.js +18 -15
- package/data/build/dist/host/cli-adapters/native-team-proxy.js.map +1 -1
- package/data/build/dist/host/cli-adapters/native-team-subagent.d.ts +57 -0
- package/data/build/dist/host/cli-adapters/native-team-subagent.d.ts.map +1 -0
- package/data/build/dist/host/cli-adapters/native-team-subagent.js +126 -0
- package/data/build/dist/host/cli-adapters/native-team-subagent.js.map +1 -0
- package/data/build/dist/host/cli-adapters/new-api-subscription.d.ts +75 -0
- package/data/build/dist/host/cli-adapters/new-api-subscription.d.ts.map +1 -0
- package/data/build/dist/host/cli-adapters/new-api-subscription.js +959 -0
- package/data/build/dist/host/cli-adapters/new-api-subscription.js.map +1 -0
- package/data/build/dist/host/cli-adapters/opencode-driver.d.ts.map +1 -1
- package/data/build/dist/host/cli-adapters/opencode-driver.js +22 -10
- package/data/build/dist/host/cli-adapters/opencode-driver.js.map +1 -1
- package/data/build/dist/host/cli-adapters/pi-driver.js +24 -7
- package/data/build/dist/host/cli-adapters/pi-driver.js.map +1 -1
- package/data/build/dist/host/cli-adapters/provider-subscription.d.ts +41 -4
- package/data/build/dist/host/cli-adapters/provider-subscription.d.ts.map +1 -1
- package/data/build/dist/host/cli-adapters/provider-subscription.js +254 -40
- package/data/build/dist/host/cli-adapters/provider-subscription.js.map +1 -1
- package/data/build/dist/host/cli-adapters/qoder-driver.d.ts +71 -0
- package/data/build/dist/host/cli-adapters/qoder-driver.d.ts.map +1 -0
- package/data/build/dist/host/cli-adapters/qoder-driver.js +553 -0
- package/data/build/dist/host/cli-adapters/qoder-driver.js.map +1 -0
- package/data/build/dist/host/cli-adapters/qoder-subscription.d.ts +31 -0
- package/data/build/dist/host/cli-adapters/qoder-subscription.d.ts.map +1 -0
- package/data/build/dist/host/cli-adapters/qoder-subscription.js +178 -0
- package/data/build/dist/host/cli-adapters/qoder-subscription.js.map +1 -0
- package/data/build/dist/host/cli-adapters/registry-holder.d.ts +4 -0
- package/data/build/dist/host/cli-adapters/registry-holder.d.ts.map +1 -0
- package/data/build/dist/host/cli-adapters/registry-holder.js +9 -0
- package/data/build/dist/host/cli-adapters/registry-holder.js.map +1 -0
- package/data/build/dist/host/cli-adapters/registry.d.ts +54 -2
- package/data/build/dist/host/cli-adapters/registry.d.ts.map +1 -1
- package/data/build/dist/host/cli-adapters/registry.js +224 -18
- package/data/build/dist/host/cli-adapters/registry.js.map +1 -1
- package/data/build/dist/host/cli-adapters/session-store.d.ts +10 -1
- package/data/build/dist/host/cli-adapters/session-store.d.ts.map +1 -1
- package/data/build/dist/host/cli-adapters/session-store.js +60 -6
- package/data/build/dist/host/cli-adapters/session-store.js.map +1 -1
- package/data/build/dist/host/cli-adapters/standard-stream-driver.d.ts +16 -1
- package/data/build/dist/host/cli-adapters/standard-stream-driver.d.ts.map +1 -1
- package/data/build/dist/host/cli-adapters/standard-stream-driver.js +150 -26
- package/data/build/dist/host/cli-adapters/standard-stream-driver.js.map +1 -1
- package/data/build/dist/host/cli-adapters/stream-normalizer.d.ts +10 -1
- package/data/build/dist/host/cli-adapters/stream-normalizer.d.ts.map +1 -1
- package/data/build/dist/host/cli-adapters/stream-normalizer.js +23 -0
- package/data/build/dist/host/cli-adapters/stream-normalizer.js.map +1 -1
- package/data/build/dist/host/cli-adapters/subagent-tool.d.ts +5 -0
- package/data/build/dist/host/cli-adapters/subagent-tool.d.ts.map +1 -0
- package/data/build/dist/host/cli-adapters/subagent-tool.js +112 -0
- package/data/build/dist/host/cli-adapters/subagent-tool.js.map +1 -0
- package/data/build/dist/host/cli-adapters/zcode-driver.d.ts +57 -0
- package/data/build/dist/host/cli-adapters/zcode-driver.d.ts.map +1 -0
- package/data/build/dist/host/cli-adapters/zcode-driver.js +843 -0
- package/data/build/dist/host/cli-adapters/zcode-driver.js.map +1 -0
- package/data/build/dist/host/cli-adapters/zcode-subscription.d.ts +28 -0
- package/data/build/dist/host/cli-adapters/zcode-subscription.d.ts.map +1 -0
- package/data/build/dist/host/cli-adapters/zcode-subscription.js +212 -0
- package/data/build/dist/host/cli-adapters/zcode-subscription.js.map +1 -0
- package/data/build/dist/host/cli-bridge/bridge-holder.d.ts +27 -0
- package/data/build/dist/host/cli-bridge/bridge-holder.d.ts.map +1 -0
- package/data/build/dist/host/cli-bridge/bridge-holder.js +51 -0
- package/data/build/dist/host/cli-bridge/bridge-holder.js.map +1 -0
- package/data/build/dist/host/cli-bridge/bridge-server.d.ts +39 -0
- package/data/build/dist/host/cli-bridge/bridge-server.d.ts.map +1 -0
- package/data/build/dist/host/cli-bridge/bridge-server.js +140 -0
- package/data/build/dist/host/cli-bridge/bridge-server.js.map +1 -0
- package/data/build/dist/host/cli-bridge/command-code-mod.d.ts +29 -0
- package/data/build/dist/host/cli-bridge/command-code-mod.d.ts.map +1 -0
- package/data/build/dist/host/cli-bridge/command-code-mod.js +91 -0
- package/data/build/dist/host/cli-bridge/command-code-mod.js.map +1 -0
- package/data/build/dist/host/cli-bridge/dispatch.d.ts +19 -0
- package/data/build/dist/host/cli-bridge/dispatch.d.ts.map +1 -0
- package/data/build/dist/host/cli-bridge/dispatch.js +128 -0
- package/data/build/dist/host/cli-bridge/dispatch.js.map +1 -0
- package/data/build/dist/host/cli-bridge/injections.d.ts +28 -0
- package/data/build/dist/host/cli-bridge/injections.d.ts.map +1 -0
- package/data/build/dist/host/cli-bridge/injections.js +131 -0
- package/data/build/dist/host/cli-bridge/injections.js.map +1 -0
- package/data/build/dist/host/cli-bridge/mcp-stdio-entry.d.ts +8 -0
- package/data/build/dist/host/cli-bridge/mcp-stdio-entry.d.ts.map +1 -0
- package/data/build/dist/host/cli-bridge/mcp-stdio-entry.js +170 -0
- package/data/build/dist/host/cli-bridge/mcp-stdio-entry.js.map +1 -0
- package/data/build/dist/host/features/lan-access-dsh.d.ts.map +1 -1
- package/data/build/dist/host/features/lan-access-dsh.js +6 -2
- package/data/build/dist/host/features/lan-access-dsh.js.map +1 -1
- package/data/build/dist/host/features/peer-host.d.ts +21 -1
- package/data/build/dist/host/features/peer-host.d.ts.map +1 -1
- package/data/build/dist/host/features/peer-host.js +176 -31
- package/data/build/dist/host/features/peer-host.js.map +1 -1
- package/data/build/dist/host/features/types.d.ts +2 -0
- package/data/build/dist/host/features/types.d.ts.map +1 -1
- package/data/build/dist/host/index.d.ts +15 -1
- package/data/build/dist/host/index.d.ts.map +1 -1
- package/data/build/dist/host/index.js +48 -2
- package/data/build/dist/host/index.js.map +1 -1
- package/data/build/dist/host/lan-access-dsh.d.ts +7 -1
- package/data/build/dist/host/lan-access-dsh.d.ts.map +1 -1
- package/data/build/dist/host/lan-access-dsh.js +95 -19
- package/data/build/dist/host/lan-access-dsh.js.map +1 -1
- package/data/build/dist/host/login-attempt-guard.d.ts +55 -0
- package/data/build/dist/host/login-attempt-guard.d.ts.map +1 -0
- package/data/build/dist/host/login-attempt-guard.js +201 -0
- package/data/build/dist/host/login-attempt-guard.js.map +1 -0
- package/data/build/dist/host/modules/peer-host/host-api-proxy-service.d.ts +3 -0
- package/data/build/dist/host/modules/peer-host/host-api-proxy-service.d.ts.map +1 -1
- package/data/build/dist/host/modules/peer-host/host-api-proxy-service.js +2 -0
- package/data/build/dist/host/modules/peer-host/host-api-proxy-service.js.map +1 -1
- package/data/build/dist/host/modules/peer-host/peer-host-aggregate-service.d.ts +1 -0
- package/data/build/dist/host/modules/peer-host/peer-host-aggregate-service.d.ts.map +1 -1
- package/data/build/dist/host/modules/peer-host/peer-host-aggregate-service.js +1 -0
- package/data/build/dist/host/modules/peer-host/peer-host-aggregate-service.js.map +1 -1
- package/data/build/dist/host/modules/peer-host/peer-host-native-protocol.d.ts +1 -1
- package/data/build/dist/host/modules/peer-host/peer-host-native-protocol.d.ts.map +1 -1
- package/data/build/dist/host/modules/peer-host/peer-host-native-protocol.js +9 -1
- package/data/build/dist/host/modules/peer-host/peer-host-native-protocol.js.map +1 -1
- package/data/build/dist/host/modules/peer-host/peer-host-native-transport.d.ts +8 -0
- package/data/build/dist/host/modules/peer-host/peer-host-native-transport.d.ts.map +1 -1
- package/data/build/dist/host/modules/peer-host/peer-host-native-transport.js +9 -0
- package/data/build/dist/host/modules/peer-host/peer-host-native-transport.js.map +1 -1
- package/data/build/dist/host/modules/peer-host/peer-host-remote-summary-source.d.ts +7 -0
- package/data/build/dist/host/modules/peer-host/peer-host-remote-summary-source.d.ts.map +1 -1
- package/data/build/dist/host/modules/peer-host/peer-host-remote-summary-source.js +31 -3
- package/data/build/dist/host/modules/peer-host/peer-host-remote-summary-source.js.map +1 -1
- package/data/build/dist/host/modules/peer-host/peer-host-virtual-registry.d.ts +2 -0
- package/data/build/dist/host/modules/peer-host/peer-host-virtual-registry.d.ts.map +1 -1
- package/data/build/dist/host/modules/peer-host/peer-host-virtual-registry.js +26 -7
- package/data/build/dist/host/modules/peer-host/peer-host-virtual-registry.js.map +1 -1
- package/data/build/dist/host/modules/pwa/pwa-assets.d.ts +6 -4
- package/data/build/dist/host/modules/pwa/pwa-assets.d.ts.map +1 -1
- package/data/build/dist/host/modules/pwa/pwa-assets.js +11 -9
- package/data/build/dist/host/modules/pwa/pwa-assets.js.map +1 -1
- package/data/build/dist/host/modules/pwa/pwa-session-notifications.d.ts +3 -0
- package/data/build/dist/host/modules/pwa/pwa-session-notifications.d.ts.map +1 -1
- package/data/build/dist/host/modules/pwa/pwa-session-notifications.js +6 -4
- package/data/build/dist/host/modules/pwa/pwa-session-notifications.js.map +1 -1
- package/data/build/dist/host/native-session-bridge.d.ts.map +1 -1
- package/data/build/dist/host/native-session-bridge.js +106 -59
- package/data/build/dist/host/native-session-bridge.js.map +1 -1
- package/data/build/dist/host/rpc.js +8 -2
- package/data/build/dist/host/rpc.js.map +1 -1
- package/data/build/dist/host/settings.d.ts.map +1 -1
- package/data/build/dist/host/settings.js +14 -4
- package/data/build/dist/host/settings.js.map +1 -1
- package/data/build/dist/host/terminal/backends/local-pty-backend.d.ts.map +1 -1
- package/data/build/dist/host/terminal/backends/local-pty-backend.js +14 -0
- package/data/build/dist/host/terminal/backends/local-pty-backend.js.map +1 -1
- package/data/build/dist/host/terminal/backends/tmux-backend.d.ts +40 -1
- package/data/build/dist/host/terminal/backends/tmux-backend.d.ts.map +1 -1
- package/data/build/dist/host/terminal/backends/tmux-backend.js +291 -18
- package/data/build/dist/host/terminal/backends/tmux-backend.js.map +1 -1
- package/data/build/dist/host/terminal/runtime-adapter.d.ts +32 -0
- package/data/build/dist/host/terminal/runtime-adapter.d.ts.map +1 -1
- package/data/build/dist/host/terminal/runtime-adapter.js +8 -0
- package/data/build/dist/host/terminal/runtime-adapter.js.map +1 -1
- package/data/build/dist/host/terminal/runtime-manager.d.ts +3 -0
- package/data/build/dist/host/terminal/runtime-manager.d.ts.map +1 -1
- package/data/build/dist/host/terminal/runtime-manager.js +92 -4
- package/data/build/dist/host/terminal/runtime-manager.js.map +1 -1
- package/data/build/dist/host/terminal/terminal-controller.d.ts.map +1 -1
- package/data/build/dist/host/terminal/terminal-controller.js +58 -6
- package/data/build/dist/host/terminal/terminal-controller.js.map +1 -1
- package/data/build/dist/host/terminal/terminal-process-service.d.ts.map +1 -1
- package/data/build/dist/host/terminal/terminal-process-service.js +12 -2
- package/data/build/dist/host/terminal/terminal-process-service.js.map +1 -1
- package/data/build/dist/host/terminal/terminal-service.d.ts +41 -4
- package/data/build/dist/host/terminal/terminal-service.d.ts.map +1 -1
- package/data/build/dist/host/terminal/terminal-service.js +551 -61
- package/data/build/dist/host/terminal/terminal-service.js.map +1 -1
- package/data/build/dist/index.d.ts +2 -2
- package/data/build/dist/index.d.ts.map +1 -1
- package/data/build/dist/index.js +2 -2
- package/data/build/dist/index.js.map +1 -1
- package/data/build/dist/shared/contracts/cli-adapter.d.ts +69 -2
- package/data/build/dist/shared/contracts/cli-adapter.d.ts.map +1 -1
- package/data/build/dist/shared/contracts/config.d.ts +63 -10
- package/data/build/dist/shared/contracts/config.d.ts.map +1 -1
- package/data/build/dist/shared/contracts/config.js +57 -5
- package/data/build/dist/shared/contracts/config.js.map +1 -1
- package/data/build/dist/shared/contracts/peer-host.d.ts +2 -0
- package/data/build/dist/shared/contracts/peer-host.d.ts.map +1 -1
- package/data/build/dist/shared/contracts/peer-host.js.map +1 -1
- package/data/build/dist/shared/contracts/subscription.d.ts +20 -1
- package/data/build/dist/shared/contracts/subscription.d.ts.map +1 -1
- package/data/build/dist/shared/contracts/subscription.js.map +1 -1
- package/data/build/dist/shared/contracts/terminal.d.ts +8 -1
- package/data/build/dist/shared/contracts/terminal.d.ts.map +1 -1
- package/data/build/dist/shared/contracts/version.d.ts +1 -1
- package/data/build/dist/shared/contracts/version.d.ts.map +1 -1
- package/data/build/dist/shared/contracts/version.js +1 -1
- package/data/build/dist/shared/contracts/version.js.map +1 -1
- package/data/build/dist/shared/debug.d.ts +8 -0
- package/data/build/dist/shared/debug.d.ts.map +1 -1
- package/data/build/dist/shared/debug.js +43 -7
- package/data/build/dist/shared/debug.js.map +1 -1
- package/data/build/dist/shared/delegation-carrier.d.ts +24 -0
- package/data/build/dist/shared/delegation-carrier.d.ts.map +1 -0
- package/data/build/dist/shared/delegation-carrier.js +111 -0
- package/data/build/dist/shared/delegation-carrier.js.map +1 -0
- package/data/build/dist/shared/index.d.ts +3 -3
- package/data/build/dist/shared/index.d.ts.map +1 -1
- package/data/build/dist/shared/index.js +2 -2
- package/data/build/dist/shared/index.js.map +1 -1
- package/data/build/dist/shared/terminal-input.d.ts +8 -0
- package/data/build/dist/shared/terminal-input.d.ts.map +1 -0
- package/data/build/dist/shared/terminal-input.js +10 -0
- package/data/build/dist/shared/terminal-input.js.map +1 -0
- package/data/build/dist/transport/debug.d.ts +7 -0
- package/data/build/dist/transport/debug.d.ts.map +1 -1
- package/data/build/dist/transport/debug.js +33 -5
- package/data/build/dist/transport/debug.js.map +1 -1
- package/data/build/dist/transport/index.d.ts +1 -1
- package/data/build/dist/transport/index.d.ts.map +1 -1
- package/data/build/dist/transport/index.js +1 -1
- package/data/build/dist/transport/index.js.map +1 -1
- package/data/build/dist/typert.host.js +1 -1
- package/data/build/dist/typert.host.js.map +1 -1
- package/package.json +3 -1
- package/profile/README.md +2 -2
- package/profile/package.json +2 -2
- package/profile/version.json +1 -1
- package/version.json +1 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { debugInfo, debugWarn } from '../../shared/debug.js';
|
|
2
3
|
/**
|
|
3
4
|
* 持久终端生命周期服务。
|
|
4
5
|
*
|
|
@@ -10,6 +11,8 @@ export class CodingNsTerminalService {
|
|
|
10
11
|
runtimes;
|
|
11
12
|
now;
|
|
12
13
|
controllers = new Map();
|
|
14
|
+
residents = new Map();
|
|
15
|
+
residentPromises = new Map();
|
|
13
16
|
followers = new Map();
|
|
14
17
|
operations = new Map();
|
|
15
18
|
exitCallbacks = new Map();
|
|
@@ -24,6 +27,10 @@ export class CodingNsTerminalService {
|
|
|
24
27
|
return;
|
|
25
28
|
await this.store.load();
|
|
26
29
|
this.initialized = true;
|
|
30
|
+
debugInfo('codingns4dsh: terminal service initialized', {
|
|
31
|
+
recordCount: this.store.list().length,
|
|
32
|
+
records: this.store.list().map(recordSummary),
|
|
33
|
+
});
|
|
27
34
|
}
|
|
28
35
|
supportsRuntimeType(runtimeType) {
|
|
29
36
|
return this.runtimes.supports(runtimeType);
|
|
@@ -77,21 +84,47 @@ export class CodingNsTerminalService {
|
|
|
77
84
|
validateTerminalId(input.terminalId);
|
|
78
85
|
validateSize(input.cols, input.rows);
|
|
79
86
|
const identity = { ...input.scope, terminalId: input.terminalId };
|
|
87
|
+
debugInfo('codingns4dsh: terminal service create start', {
|
|
88
|
+
identity,
|
|
89
|
+
runtimeType: input.runtimeType,
|
|
90
|
+
shellProfileId: input.shell.profileId,
|
|
91
|
+
cols: input.cols,
|
|
92
|
+
rows: input.rows,
|
|
93
|
+
});
|
|
80
94
|
return this.enqueue(identity, async () => {
|
|
81
95
|
const existing = this.store.get(identity);
|
|
96
|
+
debugInfo('codingns4dsh: terminal service create queued', {
|
|
97
|
+
identity,
|
|
98
|
+
existing: existing === undefined ? null : recordSummary(existing),
|
|
99
|
+
});
|
|
82
100
|
if (existing !== undefined) {
|
|
83
101
|
if (existing.state === 'closed' || existing.state === 'closing') {
|
|
84
102
|
throw new TerminalServiceError('TERMINAL_UNAVAILABLE', '终端已关闭,不能复用相同标识');
|
|
85
103
|
}
|
|
86
104
|
const runtime = await this.runtimes.inspect(existing);
|
|
105
|
+
debugInfo('codingns4dsh: terminal service create existing inspect', {
|
|
106
|
+
identity,
|
|
107
|
+
record: recordSummary(existing),
|
|
108
|
+
runtime: runtimeSummary(runtime),
|
|
109
|
+
});
|
|
87
110
|
if (runtime.alive) {
|
|
88
111
|
const running = existing.state === 'running'
|
|
89
112
|
? existing
|
|
90
113
|
: await this.update(existing, { state: 'running', error: '' });
|
|
114
|
+
try {
|
|
115
|
+
await this.ensureResident(running);
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
debugWarn('codingns4dsh: terminal resident connection warmup failed', {
|
|
119
|
+
identity,
|
|
120
|
+
error: errorMessage(error),
|
|
121
|
+
});
|
|
122
|
+
}
|
|
91
123
|
return this.info(running);
|
|
92
124
|
}
|
|
93
|
-
|
|
94
|
-
|
|
125
|
+
// 运行时确实没了:同一个 terminalId 允许重建,这样 Sidebar 标签、标题和
|
|
126
|
+
// 尺寸都能保留。旧实现只把记录标成 lost 再抛错,用户点"重建终端"永远失败。
|
|
127
|
+
return this.rebuild(existing, input);
|
|
95
128
|
}
|
|
96
129
|
const timestamp = this.now().toISOString();
|
|
97
130
|
const record = {
|
|
@@ -117,20 +150,41 @@ export class CodingNsTerminalService {
|
|
|
117
150
|
updatedAt: timestamp,
|
|
118
151
|
};
|
|
119
152
|
await this.store.put(record);
|
|
153
|
+
debugInfo('codingns4dsh: terminal service record starting', { record: recordSummary(record) });
|
|
120
154
|
try {
|
|
121
155
|
const runtime = await this.runtimes.create(record);
|
|
156
|
+
debugInfo('codingns4dsh: terminal service runtime created', {
|
|
157
|
+
identity,
|
|
158
|
+
runtime: runtimeSummary(runtime),
|
|
159
|
+
});
|
|
122
160
|
if (!runtime.alive)
|
|
123
161
|
throw new Error('backend 创建后未报告存活状态');
|
|
124
162
|
if (input.onExit !== undefined)
|
|
125
163
|
this.exitCallbacks.set(identityKey(identity), input.onExit);
|
|
126
164
|
const running = await this.update(record, { state: 'running', error: '' });
|
|
127
|
-
|
|
128
|
-
|
|
165
|
+
// 常驻连接同时承担自然退出监听。这样普通终端和启动项终端都使用同一
|
|
166
|
+
// 条 Host 内存连接,浏览器 follow 不再反复创建 backend attach。
|
|
167
|
+
try {
|
|
168
|
+
await this.ensureResident(running);
|
|
169
|
+
}
|
|
170
|
+
catch (error) {
|
|
171
|
+
debugWarn('codingns4dsh: terminal resident connection warmup failed', {
|
|
172
|
+
identity,
|
|
173
|
+
error: errorMessage(error),
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
debugInfo('codingns4dsh: terminal service create success', { record: recordSummary(running) });
|
|
129
177
|
return this.info(running);
|
|
130
178
|
}
|
|
131
179
|
catch (error) {
|
|
132
180
|
this.exitCallbacks.delete(identityKey(identity));
|
|
133
|
-
|
|
181
|
+
const message = errorMessage(error);
|
|
182
|
+
debugWarn('codingns4dsh: terminal service create failed', {
|
|
183
|
+
identity,
|
|
184
|
+
record: recordSummary(record),
|
|
185
|
+
error: message,
|
|
186
|
+
});
|
|
187
|
+
await this.update(record, { state: 'error', error: message });
|
|
134
188
|
throw error;
|
|
135
189
|
}
|
|
136
190
|
});
|
|
@@ -140,6 +194,72 @@ export class CodingNsTerminalService {
|
|
|
140
194
|
this.requireInitialized();
|
|
141
195
|
return this.store.get(identity);
|
|
142
196
|
}
|
|
197
|
+
/**
|
|
198
|
+
* 用同一个 terminalId 重建已经丢失的运行时。
|
|
199
|
+
*
|
|
200
|
+
* 保留 cwd、标题、shell 与工作区归属,只换一个新的 runtimeSessionKey;旧的
|
|
201
|
+
* tmux 会话/PTY 已经不存在,先按幂等方式清理一次再创建。
|
|
202
|
+
*/
|
|
203
|
+
async rebuild(existing, input) {
|
|
204
|
+
await this.update(existing, { state: 'lost', error: '持久终端运行时不存在' });
|
|
205
|
+
// 重建会更换 runtimeSessionKey;旧 resident 即使 backend 已经丢失,也不能
|
|
206
|
+
// 留在内存映射里,否则后面的 ensureResident 会把新终端绑定到旧订阅。
|
|
207
|
+
await this.releaseResident(identityOfRecord(existing));
|
|
208
|
+
try {
|
|
209
|
+
await this.runtimes.terminate(existing);
|
|
210
|
+
}
|
|
211
|
+
catch { /* 旧运行时已经不存在 */ }
|
|
212
|
+
await this.runtimes.detachTerminal(existing);
|
|
213
|
+
this.exitCallbacks.delete(identityKey(existing));
|
|
214
|
+
const identity = { ...input.scope, terminalId: existing.terminalId };
|
|
215
|
+
const timestamp = this.now().toISOString();
|
|
216
|
+
const record = {
|
|
217
|
+
...existing,
|
|
218
|
+
...input.scope,
|
|
219
|
+
runtimeSessionKey: randomUUID(),
|
|
220
|
+
runtimeType: input.runtimeType,
|
|
221
|
+
shellPath: input.shell.path,
|
|
222
|
+
shellProfileId: input.shell.profileId,
|
|
223
|
+
shellName: input.shell.name,
|
|
224
|
+
shellArgs: [...input.shell.args],
|
|
225
|
+
...(input.commandPath === undefined ? {} : { commandPath: input.commandPath }),
|
|
226
|
+
...(input.commandArgs === undefined ? {} : { commandArgs: [...input.commandArgs] }),
|
|
227
|
+
...(input.commandEnv === undefined ? {} : { commandEnv: { ...input.commandEnv } }),
|
|
228
|
+
...(input.launchProfileId === undefined ? {} : { launchProfileId: input.launchProfileId }),
|
|
229
|
+
cwd: input.cwd,
|
|
230
|
+
title: input.title?.trim() || existing.title,
|
|
231
|
+
cols: input.cols,
|
|
232
|
+
rows: input.rows,
|
|
233
|
+
state: 'starting',
|
|
234
|
+
exitCode: null,
|
|
235
|
+
error: '',
|
|
236
|
+
updatedAt: timestamp,
|
|
237
|
+
};
|
|
238
|
+
await this.store.put(record);
|
|
239
|
+
try {
|
|
240
|
+
const runtime = await this.runtimes.create(record);
|
|
241
|
+
if (!runtime.alive)
|
|
242
|
+
throw new Error('backend 重建后未报告存活状态');
|
|
243
|
+
if (input.onExit !== undefined)
|
|
244
|
+
this.exitCallbacks.set(identityKey(identity), input.onExit);
|
|
245
|
+
const running = await this.update(record, { state: 'running', error: '' });
|
|
246
|
+
try {
|
|
247
|
+
await this.ensureResident(running);
|
|
248
|
+
}
|
|
249
|
+
catch (error) {
|
|
250
|
+
debugWarn('codingns4dsh: terminal resident connection warmup failed', {
|
|
251
|
+
identity,
|
|
252
|
+
error: errorMessage(error),
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
return this.info(running);
|
|
256
|
+
}
|
|
257
|
+
catch (error) {
|
|
258
|
+
this.exitCallbacks.delete(identityKey(identity));
|
|
259
|
+
await this.update(record, { state: 'error', error: errorMessage(error) });
|
|
260
|
+
throw error;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
143
263
|
async inspect(identity) {
|
|
144
264
|
const record = this.getRecord(identity);
|
|
145
265
|
if (record === undefined)
|
|
@@ -156,6 +276,7 @@ export class CodingNsTerminalService {
|
|
|
156
276
|
if (current === undefined || current.state === 'closed')
|
|
157
277
|
return;
|
|
158
278
|
if (current.state === 'closing') {
|
|
279
|
+
await this.releaseResident(identityOfRecord(current));
|
|
159
280
|
await this.runtimes.terminate(current);
|
|
160
281
|
await this.runtimes.detachTerminal(current);
|
|
161
282
|
await this.update(current, { state: 'closed', exitCode: null, error: '' });
|
|
@@ -163,9 +284,25 @@ export class CodingNsTerminalService {
|
|
|
163
284
|
}
|
|
164
285
|
try {
|
|
165
286
|
const identity = await this.runtimes.inspect(current);
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
287
|
+
if (identity.alive) {
|
|
288
|
+
await this.update(current, { state: 'running', error: '' });
|
|
289
|
+
// 恢复阶段提前建立常驻连接,用户第一次点击终端时直接收到已有状态。
|
|
290
|
+
try {
|
|
291
|
+
await this.ensureResident(this.store.get(current) ?? current);
|
|
292
|
+
}
|
|
293
|
+
catch (error) {
|
|
294
|
+
debugWarn('codingns4dsh: terminal resident connection restore failed', {
|
|
295
|
+
identity: identityOfRecord(current),
|
|
296
|
+
error: errorMessage(error),
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
// 运行时不在了:有真实退出码才算 exited,否则只能报告 lost。
|
|
302
|
+
// 少了这一步,DSH 重启后会把"用户已经退出的终端"一直显示成丢失。
|
|
303
|
+
await this.update(current, identity.exitCode === undefined || identity.exitCode === null
|
|
304
|
+
? { state: 'lost', exitCode: null, error: identity.detail ?? '持久终端运行时不存在' }
|
|
305
|
+
: { state: 'exited', exitCode: identity.exitCode, error: '' });
|
|
169
306
|
}
|
|
170
307
|
catch (error) {
|
|
171
308
|
await this.update(current, { state: 'error', error: errorMessage(error) });
|
|
@@ -181,51 +318,84 @@ export class CodingNsTerminalService {
|
|
|
181
318
|
}
|
|
182
319
|
async *follow(input) {
|
|
183
320
|
const record = this.requireAvailable(input.identity);
|
|
321
|
+
debugInfo('codingns4dsh: terminal service follow start', {
|
|
322
|
+
identity: input.identity,
|
|
323
|
+
attachmentId: input.attachmentId,
|
|
324
|
+
generation: input.generation,
|
|
325
|
+
record: recordSummary(record),
|
|
326
|
+
});
|
|
184
327
|
const key = identityKey(input.identity);
|
|
328
|
+
// create/recover 通常已经建立 resident;旧记录或连接抖动时在这里补建一次。
|
|
329
|
+
await this.ensureResident(record);
|
|
330
|
+
const resident = this.residents.get(key);
|
|
331
|
+
if (resident === undefined)
|
|
332
|
+
throw new TerminalServiceError('TERMINAL_RUNTIME_LOST', '终端常驻连接不可用');
|
|
185
333
|
const queue = new TerminalFrameQueue(2 * 1024 * 1024);
|
|
186
334
|
const follower = { attachmentId: input.attachmentId, generation: input.generation, queue };
|
|
187
|
-
|
|
188
|
-
//
|
|
189
|
-
|
|
190
|
-
|
|
335
|
+
// resident 已经存在时不再等待 backend attach;先从 tmux server 读取完整历史,
|
|
336
|
+
// 这样第一帧能真正填充 xterm scrollback,而不是只重放当前屏幕。
|
|
337
|
+
// 如果把它当作 output 增量发送,切换会话或 resident 重连时会把整屏再次追加,
|
|
338
|
+
// 造成 prompt 重复和 ANSI 内容错位。
|
|
339
|
+
let snapshot = resident.replay;
|
|
191
340
|
try {
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
341
|
+
const captured = await this.runtimes.captureHistory(record, RESIDENT_HISTORY_LINES);
|
|
342
|
+
if (captured !== undefined) {
|
|
343
|
+
resident.replay = captured;
|
|
344
|
+
snapshot = captured;
|
|
345
|
+
debugInfo('codingns4dsh: terminal history snapshot ready', {
|
|
346
|
+
identity: input.identity,
|
|
347
|
+
source: 'runtime-capture',
|
|
348
|
+
historyLines: countLines(captured),
|
|
349
|
+
historyCharacters: captured.length,
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
else {
|
|
353
|
+
debugInfo('codingns4dsh: terminal history snapshot fallback', {
|
|
354
|
+
identity: input.identity,
|
|
355
|
+
source: 'resident-replay',
|
|
356
|
+
replayCharacters: snapshot.length,
|
|
357
|
+
});
|
|
358
|
+
}
|
|
202
359
|
}
|
|
203
360
|
catch (error) {
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
361
|
+
debugWarn('codingns4dsh: terminal history capture failed, using resident replay', {
|
|
362
|
+
identity: input.identity,
|
|
363
|
+
error: errorMessage(error),
|
|
364
|
+
replayCharacters: snapshot.length,
|
|
365
|
+
});
|
|
207
366
|
}
|
|
208
|
-
|
|
367
|
+
// 历史读取期间不登记 follower,避免极短竞态把 output 排在 snapshot 之前。
|
|
368
|
+
snapshot = resident.replay;
|
|
369
|
+
this.addFollower(key, follower);
|
|
370
|
+
this.addController(key, input.attachmentId, {
|
|
209
371
|
attachmentId: input.attachmentId,
|
|
210
|
-
subscriptionId:
|
|
372
|
+
subscriptionId: resident.subscriptionId,
|
|
211
373
|
generation: input.generation,
|
|
212
374
|
});
|
|
213
|
-
this.
|
|
214
|
-
|
|
215
|
-
input.signal.addEventListener('abort', abort, { once: true });
|
|
216
|
-
if (input.signal.aborted)
|
|
217
|
-
abort();
|
|
375
|
+
queue.pushSnapshot(this.info(record, input.attachmentId), snapshot);
|
|
376
|
+
queue.pushState(this.info(record, input.attachmentId));
|
|
218
377
|
try {
|
|
378
|
+
debugInfo('codingns4dsh: terminal service follow subscribed', {
|
|
379
|
+
identity: input.identity,
|
|
380
|
+
attachmentId: input.attachmentId,
|
|
381
|
+
residentSubscriptionId: resident.subscriptionId,
|
|
382
|
+
residentRuntimeAttachmentId: resident.runtimeAttachmentId,
|
|
383
|
+
});
|
|
384
|
+
const abort = () => queue.finish();
|
|
385
|
+
input.signal.addEventListener('abort', abort, { once: true });
|
|
386
|
+
if (input.signal.aborted)
|
|
387
|
+
abort();
|
|
219
388
|
yield* queue.read();
|
|
389
|
+
input.signal.removeEventListener('abort', abort);
|
|
220
390
|
}
|
|
221
391
|
finally {
|
|
222
|
-
input.signal.removeEventListener('abort', abort);
|
|
223
392
|
this.removeFollower(key, follower);
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
393
|
+
this.removeController(key, input.attachmentId);
|
|
394
|
+
debugInfo('codingns4dsh: terminal service follow unsubscribed', {
|
|
395
|
+
identity: input.identity,
|
|
396
|
+
attachmentId: input.attachmentId,
|
|
397
|
+
residentSubscriptionId: resident.subscriptionId,
|
|
398
|
+
});
|
|
229
399
|
}
|
|
230
400
|
}
|
|
231
401
|
async write(identity, attachmentId, data) {
|
|
@@ -239,6 +409,11 @@ export class CodingNsTerminalService {
|
|
|
239
409
|
this.requireInitialized();
|
|
240
410
|
await this.enqueue(identity, async () => {
|
|
241
411
|
const record = this.requireAvailable(identity);
|
|
412
|
+
const resident = this.residents.get(identityKey(identity));
|
|
413
|
+
if (resident !== undefined) {
|
|
414
|
+
await this.runtimes.write(resident.subscriptionId, data);
|
|
415
|
+
return;
|
|
416
|
+
}
|
|
242
417
|
await this.runtimes.writeSession(record, data);
|
|
243
418
|
});
|
|
244
419
|
}
|
|
@@ -263,29 +438,41 @@ export class CodingNsTerminalService {
|
|
|
263
438
|
}
|
|
264
439
|
async close(identity) {
|
|
265
440
|
this.requireInitialized();
|
|
441
|
+
debugInfo('codingns4dsh: terminal service close start', { identity });
|
|
266
442
|
await this.enqueue(identity, async () => {
|
|
267
443
|
const record = this.store.get(identity);
|
|
268
|
-
if (record === undefined || record.state === 'closed')
|
|
444
|
+
if (record === undefined || record.state === 'closed') {
|
|
445
|
+
debugInfo('codingns4dsh: terminal service close noop', { identity, record: record === undefined ? null : recordSummary(record) });
|
|
269
446
|
return;
|
|
447
|
+
}
|
|
270
448
|
const closing = record.state === 'closing' ? record : await this.update(record, { state: 'closing' });
|
|
271
449
|
this.broadcastState(identity);
|
|
450
|
+
await this.releaseResident(identity);
|
|
272
451
|
await this.runtimes.terminate(closing);
|
|
452
|
+
debugInfo('codingns4dsh: terminal service runtime terminated', { identity, record: recordSummary(closing) });
|
|
273
453
|
await this.runtimes.detachTerminal(identity);
|
|
274
454
|
this.controllers.delete(identityKey(identity));
|
|
275
455
|
this.exitCallbacks.delete(identityKey(identity));
|
|
276
456
|
const closed = await this.update(closing, { state: 'closed', exitCode: null, error: '' });
|
|
277
457
|
this.broadcastState(identity, closed);
|
|
278
458
|
this.finishFollowers(identityKey(identity));
|
|
459
|
+
debugInfo('codingns4dsh: terminal service close success', { identity, record: recordSummary(closed) });
|
|
279
460
|
});
|
|
280
461
|
}
|
|
281
462
|
async detachGeneration(generation) {
|
|
463
|
+
// 浏览器 attach 已经只是 resident 的订阅,不再拥有 backend attachment;
|
|
464
|
+
// RuntimeManager 的 generation 清理仍保留,用于兼容旧的 monitor/调用方。
|
|
282
465
|
await this.runtimes.detachGeneration(generation);
|
|
283
466
|
const changed = new Set();
|
|
284
|
-
for (const [key,
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
467
|
+
for (const [key, bindings] of this.controllers) {
|
|
468
|
+
for (const [attachmentId, binding] of bindings) {
|
|
469
|
+
if (binding.generation !== generation)
|
|
470
|
+
continue;
|
|
471
|
+
bindings.delete(attachmentId);
|
|
472
|
+
changed.add(key);
|
|
473
|
+
}
|
|
474
|
+
if (bindings.size === 0)
|
|
475
|
+
this.controllers.delete(key);
|
|
289
476
|
}
|
|
290
477
|
for (const [key, followers] of this.followers) {
|
|
291
478
|
for (const follower of followers) {
|
|
@@ -305,13 +492,14 @@ export class CodingNsTerminalService {
|
|
|
305
492
|
follower.queue.finish();
|
|
306
493
|
this.followers.clear();
|
|
307
494
|
this.controllers.clear();
|
|
495
|
+
this.residents.clear();
|
|
308
496
|
this.exitCallbacks.clear();
|
|
309
497
|
await this.runtimes.dispose();
|
|
310
498
|
}
|
|
311
499
|
requireController(identity, attachmentId) {
|
|
312
500
|
this.requireAvailable(identity);
|
|
313
|
-
const controller = this.controllers.get(identityKey(identity));
|
|
314
|
-
if (controller
|
|
501
|
+
const controller = this.controllers.get(identityKey(identity))?.get(attachmentId);
|
|
502
|
+
if (controller === undefined) {
|
|
315
503
|
throw new TerminalServiceError('TERMINAL_CONTROL_UNAVAILABLE', '当前 attach 没有终端输入控制权');
|
|
316
504
|
}
|
|
317
505
|
return controller;
|
|
@@ -340,34 +528,74 @@ export class CodingNsTerminalService {
|
|
|
340
528
|
this.broadcastState(identity, failed);
|
|
341
529
|
}
|
|
342
530
|
}
|
|
343
|
-
|
|
531
|
+
/**
|
|
532
|
+
* 浏览器 attach 客户端结束了。
|
|
533
|
+
*
|
|
534
|
+
* tmux 客户端在"服务器消失""会话被销毁""只是这次连接断了"时都会退出,退出码
|
|
535
|
+
* 本身不能证明 shell 结束。因此这里必须回查运行时的真实状态:只有确实拿到
|
|
536
|
+
* shell 的退出码才算 `exited`,否则只能标记 `lost`,让用户重新连接而不是看到
|
|
537
|
+
* 一个假的"进程已退出(1)"。
|
|
538
|
+
*/
|
|
539
|
+
async handleAttachmentExit(identity, exitCode, queue) {
|
|
344
540
|
try {
|
|
345
|
-
await this.
|
|
541
|
+
await this.finishRuntime(identity, exitCode);
|
|
346
542
|
}
|
|
347
543
|
finally {
|
|
348
|
-
//
|
|
544
|
+
// 先发终态元数据,再结束 Remote 流;否则官方 Client 会把正常退出误判为 attach 故障。
|
|
349
545
|
queue.finish();
|
|
350
546
|
}
|
|
351
547
|
}
|
|
352
|
-
|
|
548
|
+
/** 以运行时的实际状态收尾:能确认真实退出码才算 exited,否则是 lost。 */
|
|
549
|
+
async finishRuntime(identity, exitCode) {
|
|
550
|
+
debugInfo('codingns4dsh: terminal service runtime exit observed', { identity, callbackExitCode: exitCode });
|
|
353
551
|
await this.enqueue(identity, async () => {
|
|
354
552
|
const record = this.store.get(identity);
|
|
355
553
|
if (record === undefined || record.state !== 'running')
|
|
356
554
|
return;
|
|
357
|
-
|
|
358
|
-
|
|
555
|
+
let runtime;
|
|
556
|
+
try {
|
|
557
|
+
runtime = await this.runtimes.inspect(record);
|
|
558
|
+
}
|
|
559
|
+
catch (error) {
|
|
560
|
+
const failed = await this.update(record, { state: 'error', error: errorMessage(error) });
|
|
561
|
+
this.broadcastState(identity, failed);
|
|
562
|
+
return;
|
|
563
|
+
}
|
|
564
|
+
debugInfo('codingns4dsh: terminal service runtime exit inspect', {
|
|
565
|
+
identity,
|
|
566
|
+
record: recordSummary(record),
|
|
567
|
+
runtime: runtimeSummary(runtime),
|
|
568
|
+
});
|
|
569
|
+
if (runtime.alive)
|
|
570
|
+
return;
|
|
571
|
+
const confirmed = runtime.exitCode ?? null;
|
|
572
|
+
const kind = runtime.exitCode === undefined || runtime.exitCode === null ? 'lost' : 'exited';
|
|
573
|
+
const finished = kind === 'exited'
|
|
574
|
+
? await this.update(record, { state: 'exited', exitCode: confirmed, error: '' })
|
|
575
|
+
: await this.update(record, {
|
|
576
|
+
state: 'lost',
|
|
577
|
+
exitCode: null,
|
|
578
|
+
error: runtime.detail ?? `持久终端连接中断(客户端退出码 ${exitCode ?? '未知'})`,
|
|
579
|
+
});
|
|
580
|
+
this.broadcastState(identity, finished);
|
|
359
581
|
const callback = this.exitCallbacks.get(identityKey(identity));
|
|
360
582
|
this.exitCallbacks.delete(identityKey(identity));
|
|
361
|
-
await callback?.(
|
|
583
|
+
await callback?.(confirmed, kind);
|
|
584
|
+
debugInfo('codingns4dsh: terminal service runtime finalized', {
|
|
585
|
+
identity,
|
|
586
|
+
kind,
|
|
587
|
+
record: recordSummary(finished),
|
|
588
|
+
});
|
|
362
589
|
});
|
|
363
590
|
}
|
|
364
|
-
info(record) {
|
|
365
|
-
const controllerId = this.controllers.get(identityKey(record))?.attachmentId;
|
|
591
|
+
info(record, controllerId) {
|
|
366
592
|
const state = record.state === 'running' || record.state === 'starting'
|
|
367
593
|
? 'running'
|
|
368
594
|
: record.state === 'closed' || record.state === 'exited'
|
|
369
595
|
? 'exited'
|
|
370
|
-
: '
|
|
596
|
+
: record.state === 'lost'
|
|
597
|
+
? 'lost'
|
|
598
|
+
: 'failed';
|
|
371
599
|
return {
|
|
372
600
|
id: record.terminalId,
|
|
373
601
|
title: record.title,
|
|
@@ -381,18 +609,210 @@ export class CodingNsTerminalService {
|
|
|
381
609
|
...(controllerId === undefined ? {} : { controllerId }),
|
|
382
610
|
};
|
|
383
611
|
}
|
|
612
|
+
/**
|
|
613
|
+
* 确保一个终端只有一条 Host backend attachment。
|
|
614
|
+
*
|
|
615
|
+
* 这个连接不绑定某个浏览器 generation,直到显式 close 或 Host dispose 才释放。
|
|
616
|
+
* 多个会话的 follow 都复用同一条连接,避免每次点击都重新启动 tmux client/PTY。
|
|
617
|
+
*/
|
|
618
|
+
async ensureResident(record) {
|
|
619
|
+
const key = identityKey(record);
|
|
620
|
+
const existing = this.residents.get(key);
|
|
621
|
+
if (existing !== undefined)
|
|
622
|
+
return existing;
|
|
623
|
+
const pending = this.residentPromises.get(key);
|
|
624
|
+
if (pending !== undefined)
|
|
625
|
+
return pending;
|
|
626
|
+
const identity = identityOfRecord(record);
|
|
627
|
+
// 每次 resident 都使用独立 token。旧 backend attachment 的迟到回调不能
|
|
628
|
+
// 误删同一 terminalId 后面刚重建的新 resident。
|
|
629
|
+
const generation = `host-resident:${key}:${randomUUID()}`;
|
|
630
|
+
const requestedAttachmentId = `resident:${record.terminalId}`;
|
|
631
|
+
// resident 断线重连时,tmux attach 的首批输出是整屏重绘;它可能在
|
|
632
|
+
// backend.attach 返回后异步到达,不能只依赖 runtime-manager 的 earlyData。
|
|
633
|
+
// 在短暂启动窗口内先收集,随后以 snapshot 发给已有 follower。
|
|
634
|
+
const hadFollowers = (this.followers.get(key)?.size ?? 0) > 0;
|
|
635
|
+
// attach 尚未完成时先无限期收集 earlyData;真正的窗口从 attachment
|
|
636
|
+
// 建立后开始计算,避免慢机器上首屏在 100ms 后才到达而被误当增量。
|
|
637
|
+
let bootstrapDeadline = Number.POSITIVE_INFINITY;
|
|
638
|
+
let bootstrapReplay = '';
|
|
639
|
+
let replay = '';
|
|
640
|
+
let task;
|
|
641
|
+
task = this.runtimes.attach(record, {
|
|
642
|
+
identity,
|
|
643
|
+
generation,
|
|
644
|
+
streamId: requestedAttachmentId,
|
|
645
|
+
requestedAttachmentId,
|
|
646
|
+
cols: record.cols,
|
|
647
|
+
rows: record.rows,
|
|
648
|
+
onData: (data) => {
|
|
649
|
+
replay = boundedAppend(replay, data);
|
|
650
|
+
const resident = this.residents.get(key);
|
|
651
|
+
if (resident !== undefined)
|
|
652
|
+
resident.replay = replay;
|
|
653
|
+
if (hadFollowers && Date.now() < bootstrapDeadline) {
|
|
654
|
+
bootstrapReplay = boundedAppend(bootstrapReplay, data);
|
|
655
|
+
return;
|
|
656
|
+
}
|
|
657
|
+
this.broadcastOutput(key, data);
|
|
658
|
+
},
|
|
659
|
+
onExit: (exitCode) => { void this.handleResidentExit(identity, generation, exitCode); },
|
|
660
|
+
}).then(async (attachment) => {
|
|
661
|
+
const resident = {
|
|
662
|
+
subscriptionId: attachment.subscriptionId,
|
|
663
|
+
runtimeAttachmentId: attachment.runtimeAttachmentId,
|
|
664
|
+
generation,
|
|
665
|
+
replay,
|
|
666
|
+
};
|
|
667
|
+
this.residents.set(key, resident);
|
|
668
|
+
// tmux attach 的原始 ANSI 首屏不含 scrollback;把 server buffer 的纯文本历史
|
|
669
|
+
// 作为恢复快照,后续 output 仍由常驻连接增量推送。
|
|
670
|
+
try {
|
|
671
|
+
const captured = await this.runtimes.captureHistory(record, RESIDENT_HISTORY_LINES);
|
|
672
|
+
if (captured !== undefined) {
|
|
673
|
+
replay = captured;
|
|
674
|
+
resident.replay = captured;
|
|
675
|
+
debugInfo('codingns4dsh: terminal resident history captured', {
|
|
676
|
+
identity,
|
|
677
|
+
historyLines: countLines(captured),
|
|
678
|
+
historyCharacters: captured.length,
|
|
679
|
+
});
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
catch (error) {
|
|
683
|
+
debugWarn('codingns4dsh: terminal resident history capture failed', {
|
|
684
|
+
identity,
|
|
685
|
+
error: errorMessage(error),
|
|
686
|
+
});
|
|
687
|
+
}
|
|
688
|
+
bootstrapDeadline = Date.now() + RESIDENT_BOOTSTRAP_WINDOW_MS;
|
|
689
|
+
if (hadFollowers) {
|
|
690
|
+
// 等待 tmux attach 的初始整屏重绘收齐,再替换已有 xterm 画面。
|
|
691
|
+
// 新 follow 不走这里,它会直接收到上面的 snapshot。
|
|
692
|
+
setTimeout(() => {
|
|
693
|
+
const current = this.residents.get(key);
|
|
694
|
+
if (current?.generation !== generation || bootstrapReplay === '')
|
|
695
|
+
return;
|
|
696
|
+
const currentRecord = this.store.get(identity);
|
|
697
|
+
if (currentRecord === undefined || currentRecord.state !== 'running')
|
|
698
|
+
return;
|
|
699
|
+
for (const follower of this.followers.get(key) ?? []) {
|
|
700
|
+
follower.queue.pushSnapshot(this.info(currentRecord, follower.attachmentId), current.replay);
|
|
701
|
+
}
|
|
702
|
+
debugInfo('codingns4dsh: terminal resident bootstrap replay promoted to snapshot', {
|
|
703
|
+
identity,
|
|
704
|
+
generation,
|
|
705
|
+
replayCharacters: current.replay.length,
|
|
706
|
+
});
|
|
707
|
+
}, RESIDENT_BOOTSTRAP_WINDOW_MS);
|
|
708
|
+
}
|
|
709
|
+
debugInfo('codingns4dsh: terminal resident connection ready', {
|
|
710
|
+
identity,
|
|
711
|
+
subscriptionId: resident.subscriptionId,
|
|
712
|
+
runtimeAttachmentId: resident.runtimeAttachmentId,
|
|
713
|
+
generation,
|
|
714
|
+
});
|
|
715
|
+
return resident;
|
|
716
|
+
}).finally(() => {
|
|
717
|
+
if (this.residentPromises.get(key) === task)
|
|
718
|
+
this.residentPromises.delete(key);
|
|
719
|
+
});
|
|
720
|
+
this.residentPromises.set(key, task);
|
|
721
|
+
return task;
|
|
722
|
+
}
|
|
723
|
+
async releaseResident(identity) {
|
|
724
|
+
const key = identityKey(identity);
|
|
725
|
+
const pending = this.residentPromises.get(key);
|
|
726
|
+
if (pending !== undefined) {
|
|
727
|
+
try {
|
|
728
|
+
await pending;
|
|
729
|
+
}
|
|
730
|
+
catch { /* 创建失败时没有可释放的连接 */ }
|
|
731
|
+
}
|
|
732
|
+
const resident = this.residents.get(key);
|
|
733
|
+
if (resident === undefined)
|
|
734
|
+
return;
|
|
735
|
+
this.residents.delete(key);
|
|
736
|
+
await this.runtimes.detach(resident.subscriptionId);
|
|
737
|
+
debugInfo('codingns4dsh: terminal resident connection released', {
|
|
738
|
+
identity,
|
|
739
|
+
subscriptionId: resident.subscriptionId,
|
|
740
|
+
runtimeAttachmentId: resident.runtimeAttachmentId,
|
|
741
|
+
});
|
|
742
|
+
}
|
|
743
|
+
async handleResidentExit(identity, generation, exitCode) {
|
|
744
|
+
const key = identityKey(identity);
|
|
745
|
+
const resident = this.residents.get(key);
|
|
746
|
+
if (resident === undefined || resident.generation !== generation) {
|
|
747
|
+
debugInfo('codingns4dsh: terminal resident stale exit ignored', {
|
|
748
|
+
identity,
|
|
749
|
+
generation,
|
|
750
|
+
currentGeneration: resident?.generation ?? null,
|
|
751
|
+
exitCode,
|
|
752
|
+
});
|
|
753
|
+
return;
|
|
754
|
+
}
|
|
755
|
+
this.residents.delete(key);
|
|
756
|
+
// 这条 backend 连接已经不能继续向浏览器送数据。先撤销输入控制权;
|
|
757
|
+
// 是否结束订阅要等 finishRuntime 判断出“连接断开”还是“Shell 退出”之后决定。
|
|
758
|
+
this.controllers.delete(key);
|
|
759
|
+
try {
|
|
760
|
+
await this.runtimes.detach(resident.subscriptionId);
|
|
761
|
+
}
|
|
762
|
+
catch { /* backend 已经回收 attachment */ }
|
|
763
|
+
await this.finishRuntime(identity, exitCode);
|
|
764
|
+
const current = this.store.get(identity);
|
|
765
|
+
if (current?.state === 'running') {
|
|
766
|
+
// tmux client 断线不等于 Shell 结束。连接层恢复时保留已有 follower,
|
|
767
|
+
// 重新建立 resident;真正退出则由 finishRuntime 收敛并结束所有订阅。
|
|
768
|
+
try {
|
|
769
|
+
const nextResident = await this.ensureResident(current);
|
|
770
|
+
// resident 重建后 subscriptionId 已变化,原 follower 仍然有效,必须
|
|
771
|
+
// 重新绑定它们的输入与 resize 控制权。
|
|
772
|
+
for (const follower of this.followers.get(key) ?? []) {
|
|
773
|
+
this.addController(key, follower.attachmentId, {
|
|
774
|
+
attachmentId: follower.attachmentId,
|
|
775
|
+
subscriptionId: nextResident.subscriptionId,
|
|
776
|
+
generation: follower.generation,
|
|
777
|
+
});
|
|
778
|
+
}
|
|
779
|
+
debugInfo('codingns4dsh: terminal resident connection reattached', {
|
|
780
|
+
identity,
|
|
781
|
+
subscriptionId: nextResident.subscriptionId,
|
|
782
|
+
});
|
|
783
|
+
return;
|
|
784
|
+
}
|
|
785
|
+
catch (error) {
|
|
786
|
+
debugWarn('codingns4dsh: terminal resident connection reattach failed', {
|
|
787
|
+
identity,
|
|
788
|
+
error: errorMessage(error),
|
|
789
|
+
});
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
// finishRuntime 已经把 exited/lost 状态推入队列,队列此时才可结束,
|
|
793
|
+
// 保证 Client 先收到终态再看到流结束。
|
|
794
|
+
this.finishFollowers(key);
|
|
795
|
+
}
|
|
384
796
|
async update(record, patch) {
|
|
385
797
|
const next = await this.store.patch(record, { ...patch, updatedAt: this.now().toISOString() });
|
|
386
798
|
if (next === undefined)
|
|
387
799
|
throw new Error('终端记录在更新期间消失');
|
|
800
|
+
if (record.state !== next.state || patch.error !== undefined || patch.exitCode !== undefined) {
|
|
801
|
+
debugInfo('codingns4dsh: terminal service state update', {
|
|
802
|
+
identity: identityOfRecord(record),
|
|
803
|
+
before: recordSummary(record),
|
|
804
|
+
patch,
|
|
805
|
+
after: recordSummary(next),
|
|
806
|
+
});
|
|
807
|
+
}
|
|
388
808
|
return next;
|
|
389
809
|
}
|
|
390
810
|
broadcastState(identity, record = this.store.get(identity)) {
|
|
391
811
|
if (record === undefined)
|
|
392
812
|
return;
|
|
393
|
-
const
|
|
394
|
-
|
|
395
|
-
|
|
813
|
+
for (const follower of this.followers.get(identityKey(identity)) ?? []) {
|
|
814
|
+
follower.queue.pushState(this.info(record, follower.attachmentId));
|
|
815
|
+
}
|
|
396
816
|
}
|
|
397
817
|
broadcastStateByKey(key) {
|
|
398
818
|
const record = this.store.list().find((candidate) => identityKey(candidate) === key);
|
|
@@ -407,6 +827,26 @@ export class CodingNsTerminalService {
|
|
|
407
827
|
}
|
|
408
828
|
followers.add(follower);
|
|
409
829
|
}
|
|
830
|
+
addController(key, attachmentId, binding) {
|
|
831
|
+
let bindings = this.controllers.get(key);
|
|
832
|
+
if (bindings === undefined) {
|
|
833
|
+
bindings = new Map();
|
|
834
|
+
this.controllers.set(key, bindings);
|
|
835
|
+
}
|
|
836
|
+
bindings.set(attachmentId, binding);
|
|
837
|
+
}
|
|
838
|
+
removeController(key, attachmentId) {
|
|
839
|
+
const bindings = this.controllers.get(key);
|
|
840
|
+
if (bindings === undefined)
|
|
841
|
+
return;
|
|
842
|
+
bindings.delete(attachmentId);
|
|
843
|
+
if (bindings.size === 0)
|
|
844
|
+
this.controllers.delete(key);
|
|
845
|
+
}
|
|
846
|
+
broadcastOutput(key, data) {
|
|
847
|
+
for (const follower of this.followers.get(key) ?? [])
|
|
848
|
+
follower.queue.pushOutput(data);
|
|
849
|
+
}
|
|
410
850
|
removeFollower(key, follower) {
|
|
411
851
|
const followers = this.followers.get(key);
|
|
412
852
|
followers?.delete(follower);
|
|
@@ -453,11 +893,14 @@ class TerminalFrameQueue {
|
|
|
453
893
|
constructor(maxBytes) {
|
|
454
894
|
this.maxBytes = maxBytes;
|
|
455
895
|
}
|
|
456
|
-
pushSnapshot(info) {
|
|
457
|
-
|
|
896
|
+
pushSnapshot(info, screen = '') {
|
|
897
|
+
// tmux capture-pane 返回纯文本 LF;xterm 的真实 PTY 模式不会自动把 LF
|
|
898
|
+
// 转成 CRLF,必须在 wire 边界补回 CR,否则历史行会逐行继承上一行的列位置。
|
|
899
|
+
this.push({ type: 'snapshot', sequence: this.sequence, screen: normalizeSnapshotLineEndings(screen), info });
|
|
458
900
|
}
|
|
459
901
|
pushOutput(data) {
|
|
460
902
|
this.sequence += 1;
|
|
903
|
+
// 增量 PTY 输出保留原始 VT 语义;只有 capture-pane 的纯文本快照需要补 CR。
|
|
461
904
|
this.push({ type: 'output', sequence: this.sequence, data });
|
|
462
905
|
}
|
|
463
906
|
pushState(info) {
|
|
@@ -515,6 +958,33 @@ function shellInfo(record) {
|
|
|
515
958
|
function identityKey(identity) {
|
|
516
959
|
return JSON.stringify([identity.hostId, identity.workspaceId, identity.terminalId]);
|
|
517
960
|
}
|
|
961
|
+
function identityOfRecord(record) {
|
|
962
|
+
return {
|
|
963
|
+
hostId: record.hostId,
|
|
964
|
+
workspaceId: record.workspaceId,
|
|
965
|
+
terminalId: record.terminalId,
|
|
966
|
+
};
|
|
967
|
+
}
|
|
968
|
+
function recordSummary(record) {
|
|
969
|
+
return {
|
|
970
|
+
...identityOfRecord(record),
|
|
971
|
+
dshSessionId: record.dshSessionId ?? null,
|
|
972
|
+
runtimeSessionKey: record.runtimeSessionKey,
|
|
973
|
+
runtimeType: record.runtimeType,
|
|
974
|
+
state: record.state,
|
|
975
|
+
exitCode: record.exitCode,
|
|
976
|
+
error: record.error || null,
|
|
977
|
+
};
|
|
978
|
+
}
|
|
979
|
+
function runtimeSummary(runtime) {
|
|
980
|
+
return {
|
|
981
|
+
alive: runtime.alive,
|
|
982
|
+
runtimePid: runtime.runtimePid ?? null,
|
|
983
|
+
shellPid: runtime.shellPid ?? null,
|
|
984
|
+
exitCode: runtime.exitCode ?? null,
|
|
985
|
+
detail: runtime.detail ?? null,
|
|
986
|
+
};
|
|
987
|
+
}
|
|
518
988
|
function validateTerminalId(id) {
|
|
519
989
|
if (!/^[\w-]{1,128}$/u.test(id))
|
|
520
990
|
throw new TypeError('终端标识无效');
|
|
@@ -527,6 +997,26 @@ function validateSize(cols, rows) {
|
|
|
527
997
|
function frameBytes(frame) {
|
|
528
998
|
return new TextEncoder().encode(JSON.stringify(frame)).byteLength;
|
|
529
999
|
}
|
|
1000
|
+
function normalizeSnapshotLineEndings(value) {
|
|
1001
|
+
return value.replace(/\r?\n/gu, '\r\n');
|
|
1002
|
+
}
|
|
1003
|
+
/** 常驻连接只保留有限的原始输出,避免长期运行终端无限增长。 */
|
|
1004
|
+
const MAX_RESIDENT_REPLAY_CHARACTERS = 1024 * 1024;
|
|
1005
|
+
/** tmux attach 的首屏通常在一个很短的窗口内分片送达。 */
|
|
1006
|
+
const RESIDENT_BOOTSTRAP_WINDOW_MS = 100;
|
|
1007
|
+
/** 初次恢复读取的 tmux 历史行数;xterm 会再按自身 scrollback 上限裁剪。 */
|
|
1008
|
+
const RESIDENT_HISTORY_LINES = 2000;
|
|
1009
|
+
function countLines(value) {
|
|
1010
|
+
if (value.length === 0)
|
|
1011
|
+
return 0;
|
|
1012
|
+
return value.split('\n').length;
|
|
1013
|
+
}
|
|
1014
|
+
function boundedAppend(current, data) {
|
|
1015
|
+
const combined = current + data;
|
|
1016
|
+
return combined.length <= MAX_RESIDENT_REPLAY_CHARACTERS
|
|
1017
|
+
? combined
|
|
1018
|
+
: combined.slice(-MAX_RESIDENT_REPLAY_CHARACTERS);
|
|
1019
|
+
}
|
|
530
1020
|
function untilAborted(signal) {
|
|
531
1021
|
if (signal.aborted)
|
|
532
1022
|
return Promise.resolve();
|