@jingyi0605/codingns4dsh 0.2.0-beta.2 → 0.2.0-rc.2
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 +7 -5
- package/assets/provider-icons/minimax-code.svg +4 -0
- package/assets/provider-icons/zcode.svg +14 -0
- 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 +4172 -1540
- package/data/build/dist/client/bundle.js.map +1 -1
- package/data/build/dist/client/cli-slots.d.ts.map +1 -1
- package/data/build/dist/client/cli-slots.js +20 -12
- 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 +39 -33
- package/data/build/dist/client/debug/ui.js.map +1 -1
- package/data/build/dist/client/delegate-command.d.ts +16 -0
- package/data/build/dist/client/delegate-command.d.ts.map +1 -0
- package/data/build/dist/client/delegate-command.js +138 -0
- package/data/build/dist/client/delegate-command.js.map +1 -0
- package/data/build/dist/client/delegate-plan.d.ts +31 -0
- package/data/build/dist/client/delegate-plan.d.ts.map +1 -0
- package/data/build/dist/client/delegate-plan.js +59 -0
- package/data/build/dist/client/delegate-plan.js.map +1 -0
- package/data/build/dist/client/delegate-ui-dom.d.ts +40 -0
- package/data/build/dist/client/delegate-ui-dom.d.ts.map +1 -0
- package/data/build/dist/client/delegate-ui-dom.js +363 -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 +52 -103
- 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.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.map +1 -1
- package/data/build/dist/client/features/peer-host.js +115 -11
- 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-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 +82 -74
- 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 +80 -36
- 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 +67 -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 +195 -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 +291 -0
- package/data/build/dist/client/mobile-session-interaction.js.map +1 -0
- 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/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 +1 -0
- package/data/build/dist/client/peer-host-native-projection.d.ts.map +1 -1
- package/data/build/dist/client/peer-host-native-projection.js +5 -0
- package/data/build/dist/client/peer-host-native-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 +4 -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 +13 -4
- 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/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-section.js +3 -3
- 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 +327 -51
- package/data/build/dist/client/subscription-slot.js.map +1 -1
- package/data/build/dist/client/terminal/model.d.ts +13 -2
- package/data/build/dist/client/terminal/model.d.ts.map +1 -1
- package/data/build/dist/client/terminal/model.js +27 -7
- package/data/build/dist/client/terminal/model.js.map +1 -1
- package/data/build/dist/client/terminal/ui.d.ts.map +1 -1
- package/data/build/dist/client/terminal/ui.js +3 -1
- package/data/build/dist/client/terminal/ui.js.map +1 -1
- package/data/build/dist/client/terminal/xterm-view.d.ts +4 -1
- package/data/build/dist/client/terminal/xterm-view.d.ts.map +1 -1
- package/data/build/dist/client/terminal/xterm-view.js +19 -17
- 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/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 +73 -3
- 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/codex-driver.d.ts +10 -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 +105 -5
- 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.map +1 -1
- package/data/build/dist/host/cli-adapters/command-code-driver.js +49 -7
- package/data/build/dist/host/cli-adapters/command-code-driver.js.map +1 -1
- package/data/build/dist/host/cli-adapters/delegate-dispatch.d.ts +47 -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 +158 -0
- package/data/build/dist/host/cli-adapters/delegate-dispatch.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/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 +196 -14
- 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/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 +15 -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 +30 -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 +83 -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 +51 -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 +193 -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 +45 -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 +107 -0
- package/data/build/dist/host/cli-adapters/native-team-subagent.js.map +1 -0
- package/data/build/dist/host/cli-adapters/opencode-driver.js +13 -3
- 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 +8 -1
- package/data/build/dist/host/cli-adapters/provider-subscription.d.ts.map +1 -1
- package/data/build/dist/host/cli-adapters/provider-subscription.js +98 -2
- package/data/build/dist/host/cli-adapters/provider-subscription.js.map +1 -1
- 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 +13 -0
- package/data/build/dist/host/cli-adapters/registry.d.ts.map +1 -1
- package/data/build/dist/host/cli-adapters/registry.js +37 -0
- package/data/build/dist/host/cli-adapters/registry.js.map +1 -1
- package/data/build/dist/host/cli-adapters/session-store.d.ts +6 -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 +42 -4
- 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 +2 -0
- 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 +30 -4
- package/data/build/dist/host/cli-adapters/standard-stream-driver.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 +66 -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 +34 -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 +135 -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 +25 -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 +60 -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 +90 -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 +151 -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.map +1 -1
- package/data/build/dist/host/features/peer-host.js +2 -1
- package/data/build/dist/host/features/peer-host.js.map +1 -1
- package/data/build/dist/host/index.d.ts +4 -0
- package/data/build/dist/host/index.d.ts.map +1 -1
- package/data/build/dist/host/index.js +36 -0
- 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 +3 -0
- 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/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 +70 -52
- package/data/build/dist/host/native-session-bridge.js.map +1 -1
- package/data/build/dist/host/rpc.js +4 -1
- 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 +3 -0
- package/data/build/dist/host/settings.js.map +1 -1
- package/data/build/dist/shared/contracts/cli-adapter.d.ts +5 -0
- package/data/build/dist/shared/contracts/cli-adapter.d.ts.map +1 -1
- package/data/build/dist/shared/contracts/config.d.ts +10 -0
- package/data/build/dist/shared/contracts/config.d.ts.map +1 -1
- package/data/build/dist/shared/contracts/config.js +8 -0
- 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 +15 -0
- 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/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/index.d.ts +1 -1
- package/data/build/dist/shared/index.d.ts.map +1 -1
- package/data/build/dist/shared/index.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
|
@@ -0,0 +1,843 @@
|
|
|
1
|
+
import { spawn, spawnSync } from 'node:child_process';
|
|
2
|
+
import { createDecipheriv, createHash } from 'node:crypto';
|
|
3
|
+
import { readFileSync } from 'node:fs';
|
|
4
|
+
import { join } from 'node:path';
|
|
5
|
+
import { homedir, userInfo } from 'node:os';
|
|
6
|
+
import { JsonRpcProcess, JsonRpcRequestError } from './json-rpc-process.js';
|
|
7
|
+
import { detectBinary, emptyCatalog, usageChunk } from './rpc-driver-utils.js';
|
|
8
|
+
import { ZCODE_CATALOG } from './model-catalog.js';
|
|
9
|
+
import { desktopCliRuntimeCommand, resolveZCodeDesktopRuntime } from './desktop-app-runtime.js';
|
|
10
|
+
import { promptWithAttachmentPaths } from './attachment-utils.js';
|
|
11
|
+
/**
|
|
12
|
+
* ZCode 驱动:通过 `zcode app-server` 的 ZCode Protocol({id, method, params}
|
|
13
|
+
* 裸信封)驱动桌面端自带的 zcode.cjs 或 PATH 上的独立 CLI,结构与 Codex 驱动
|
|
14
|
+
* 一致——按 DSH 会话维护持久 app 进程,跨回合复用。
|
|
15
|
+
*
|
|
16
|
+
* 会话流程:session/create|resume → session/send。服务端会在创建期间反向请求
|
|
17
|
+
* session/requestRuntimePreferences,这里用固定默认值应答;模型跟随 CLI 自己
|
|
18
|
+
* 的选择(独立 CLI 的提供商注册表需先在终端 `zcode login` 后才可用)。回合
|
|
19
|
+
* 终态以 state.updated(status=idle / prompt_failed)、computer-use
|
|
20
|
+
* turn-failed 与 v4/telemetry turn.terminal(携带真实 errorCode/errorMessage)
|
|
21
|
+
* 为准。
|
|
22
|
+
*/
|
|
23
|
+
export class ZcodeAppServerDriver {
|
|
24
|
+
descriptor = {
|
|
25
|
+
id: 'zcode',
|
|
26
|
+
name: 'ZCode',
|
|
27
|
+
protocol: 'json-rpc',
|
|
28
|
+
capabilities: ['models', 'stream', 'resume', 'interrupt', 'reasoning', 'usage'],
|
|
29
|
+
};
|
|
30
|
+
binaries;
|
|
31
|
+
runSpawnSync;
|
|
32
|
+
runSpawn;
|
|
33
|
+
cachedRuntime;
|
|
34
|
+
cachedBinary = null;
|
|
35
|
+
sessions = new Map();
|
|
36
|
+
processes = new Set();
|
|
37
|
+
cachedCatalog = null;
|
|
38
|
+
constructor(options = {}) {
|
|
39
|
+
this.binaries = options.binaries ?? ['zcode', 'zcode.cmd'];
|
|
40
|
+
this.runSpawnSync = options.spawnSync ?? spawnSync;
|
|
41
|
+
this.runSpawn = options.spawn ?? spawn;
|
|
42
|
+
}
|
|
43
|
+
async detect() {
|
|
44
|
+
const binary = await detectBinary({ binaries: this.binaries, spawnSync: this.runSpawnSync });
|
|
45
|
+
if (binary.installed) {
|
|
46
|
+
this.cachedBinary = binary.command;
|
|
47
|
+
return binary;
|
|
48
|
+
}
|
|
49
|
+
const runtime = this.resolveRuntime();
|
|
50
|
+
if (runtime !== null)
|
|
51
|
+
return { installed: true, version: runtime.appVersion, command: runtime.entry };
|
|
52
|
+
return binary;
|
|
53
|
+
}
|
|
54
|
+
async listModels() {
|
|
55
|
+
if (!(await this.detect()).installed)
|
|
56
|
+
return emptyCatalog();
|
|
57
|
+
if (this.cachedCatalog !== null)
|
|
58
|
+
return this.cachedCatalog;
|
|
59
|
+
let rpc = null;
|
|
60
|
+
try {
|
|
61
|
+
rpc = this.startAppServer();
|
|
62
|
+
this.installServerRequestHandler(rpc);
|
|
63
|
+
await this.syncAccountProviderConfig(rpc);
|
|
64
|
+
const created = await rpc.request('session/create', {
|
|
65
|
+
workspace: zcodeWorkspace(process.cwd()),
|
|
66
|
+
persistence: 'deferred',
|
|
67
|
+
});
|
|
68
|
+
const catalog = catalogFromZcodeSnapshot(created);
|
|
69
|
+
if (catalog.groups.length > 0)
|
|
70
|
+
this.cachedCatalog = catalog;
|
|
71
|
+
return catalog.groups.length > 0 ? catalog : ZCODE_CATALOG;
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
return this.cachedCatalog ?? ZCODE_CATALOG;
|
|
75
|
+
}
|
|
76
|
+
finally {
|
|
77
|
+
rpc?.dispose();
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
async probeSession(input) {
|
|
81
|
+
const providerSessionId = input.providerSessionId?.trim();
|
|
82
|
+
if (providerSessionId === undefined || providerSessionId === '') {
|
|
83
|
+
return { state: 'unknown', reason: '缺少 Provider 会话标识' };
|
|
84
|
+
}
|
|
85
|
+
let rpc = null;
|
|
86
|
+
try {
|
|
87
|
+
rpc = this.startAppServer();
|
|
88
|
+
const timer = setTimeout(() => rpc?.dispose(), 12_000);
|
|
89
|
+
timer.unref?.();
|
|
90
|
+
const result = await rpc.request('session/list', {});
|
|
91
|
+
clearTimeout(timer);
|
|
92
|
+
const sessions = result?.sessions ?? [];
|
|
93
|
+
const found = sessions.some((session) => session.sessionId === providerSessionId);
|
|
94
|
+
return found
|
|
95
|
+
? { state: 'available', reason: 'Provider 会话仍存在' }
|
|
96
|
+
: { state: 'missing', reason: 'Provider 会话已被删除' };
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
return { state: 'unknown', reason: `会话探测失败: ${error instanceof Error ? error.message : String(error)}` };
|
|
100
|
+
}
|
|
101
|
+
finally {
|
|
102
|
+
rpc?.dispose();
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
async *executeTurn(input) {
|
|
106
|
+
if (!(await this.detect()).installed)
|
|
107
|
+
throw new Error('ZCode 未安装');
|
|
108
|
+
const session = await this.getSession(input);
|
|
109
|
+
// 每轮都清掉上一轮的终态痕迹;常驻 session 可能连续发送多轮。
|
|
110
|
+
session.sawRunning = false;
|
|
111
|
+
session.sawText = false;
|
|
112
|
+
session.failureCode = undefined;
|
|
113
|
+
session.failureMessage = undefined;
|
|
114
|
+
if (session.acpSessionId === '') {
|
|
115
|
+
let created;
|
|
116
|
+
await this.syncAccountProviderConfig(session.rpc, input.signal);
|
|
117
|
+
if (input.providerSessionId !== undefined) {
|
|
118
|
+
try {
|
|
119
|
+
created = await session.rpc.request('session/resume', { sessionId: input.providerSessionId, workspace: zcodeWorkspace(input.cwd) }, { signal: input.signal, killOnAbort: false });
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
// Provider 会话被清理后,新建 DSH 会话仍应可继续工作;绑定会在
|
|
123
|
+
// create 响应中更新,不能把旧 ID 当成当前会话。
|
|
124
|
+
created = undefined;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
if (created === undefined) {
|
|
128
|
+
created = await session.rpc.request('session/create', {
|
|
129
|
+
workspace: zcodeWorkspace(input.cwd),
|
|
130
|
+
persistence: 'deferred',
|
|
131
|
+
}, { signal: input.signal, killOnAbort: false });
|
|
132
|
+
}
|
|
133
|
+
session.acpSessionId = readSessionId(created) ?? input.sessionId;
|
|
134
|
+
const catalog = catalogFromZcodeSnapshot(created);
|
|
135
|
+
if (catalog.groups.length > 0)
|
|
136
|
+
this.cachedCatalog = catalog;
|
|
137
|
+
}
|
|
138
|
+
yield { type: 'session-binding', providerSessionId: session.acpSessionId };
|
|
139
|
+
await this.applyModelSelection(session, input);
|
|
140
|
+
await this.subscribeSessionEvents(session, input.signal);
|
|
141
|
+
const eventQueue = createZcodeTurnEventQueue();
|
|
142
|
+
let rpcExited = false;
|
|
143
|
+
const removeExitListener = session.rpc.addExitListener(() => {
|
|
144
|
+
rpcExited = true;
|
|
145
|
+
eventQueue.close();
|
|
146
|
+
});
|
|
147
|
+
let sendResolved = false;
|
|
148
|
+
let sendError = null;
|
|
149
|
+
// session/resume 的重放通知不能进入当前回合;监听器先于 send 注册并缓存
|
|
150
|
+
// 响应前的通知,send 响应返回后再统一消费。监听器必须挂会话级(请求级的
|
|
151
|
+
// 会在 send 响应返回即被移除,回合终态事件就再也进不来)。
|
|
152
|
+
const notificationsBeforeSend = [];
|
|
153
|
+
const onNotification = (message) => {
|
|
154
|
+
// turn.terminal 详情略晚于 turn-failed 事件到达,宽限期结束前必须已经
|
|
155
|
+
// 记下真实 errorCode/errorMessage。
|
|
156
|
+
captureZcodeFailureDetail(message, session);
|
|
157
|
+
if (!sendResolved) {
|
|
158
|
+
notificationsBeforeSend.push(message);
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
eventQueue.push(message);
|
|
162
|
+
};
|
|
163
|
+
const removeNotificationListener = session.rpc.addNotificationListener(onNotification);
|
|
164
|
+
const sendPromise = session.rpc.request('session/send', {
|
|
165
|
+
sessionId: session.acpSessionId,
|
|
166
|
+
content: promptWithAttachmentPaths(input.prompt, input.attachments ?? []),
|
|
167
|
+
}, { signal: input.signal, killOnAbort: false })
|
|
168
|
+
.then(() => undefined, (error) => { sendError = error; });
|
|
169
|
+
const onAbort = () => {
|
|
170
|
+
void session.rpc.request('session/stop', { sessionId: session.acpSessionId }).catch(() => undefined);
|
|
171
|
+
};
|
|
172
|
+
if (input.signal?.aborted)
|
|
173
|
+
onAbort();
|
|
174
|
+
else
|
|
175
|
+
input.signal?.addEventListener('abort', onAbort, { once: true });
|
|
176
|
+
try {
|
|
177
|
+
await sendPromise;
|
|
178
|
+
if (sendError !== null && !input.signal?.aborted)
|
|
179
|
+
throw new Error('ZCode 消息发送失败');
|
|
180
|
+
sendResolved = true;
|
|
181
|
+
for (const message of notificationsBeforeSend.splice(0))
|
|
182
|
+
eventQueue.push(message);
|
|
183
|
+
let terminalReason = null;
|
|
184
|
+
while (true) {
|
|
185
|
+
const next = await eventQueue.next();
|
|
186
|
+
if (next.done)
|
|
187
|
+
break;
|
|
188
|
+
const chunk = zcodeMessageToChunk(next.value, session, input);
|
|
189
|
+
if (chunk !== null)
|
|
190
|
+
yield chunk;
|
|
191
|
+
terminalReason = readZcodeTerminalReason(next.value, session, input) ?? terminalReason;
|
|
192
|
+
if (terminalReason !== null) {
|
|
193
|
+
if (terminalReason === 'error') {
|
|
194
|
+
// turn.terminal 详情(errorCode/errorMessage)略晚于 turn-failed
|
|
195
|
+
// 到达,稍等再透出真实原因。
|
|
196
|
+
await new Promise((resolve) => setTimeout(resolve, 1_500));
|
|
197
|
+
yield failureChunk(session);
|
|
198
|
+
}
|
|
199
|
+
eventQueue.close();
|
|
200
|
+
break;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
if (rpcExited && !input.signal?.aborted)
|
|
204
|
+
throw new Error('Agent 进程已退出');
|
|
205
|
+
if (terminalReason === 'stop' || terminalReason === null) {
|
|
206
|
+
if (input.signal?.aborted) {
|
|
207
|
+
terminalReason = 'cancel';
|
|
208
|
+
}
|
|
209
|
+
else {
|
|
210
|
+
// usage 查询属于正常终态的一部分,不能因为 idle 事件先到就跳过。
|
|
211
|
+
const usage = await readSessionUsage(session.rpc, session.acpSessionId);
|
|
212
|
+
if (usage !== null)
|
|
213
|
+
yield usage;
|
|
214
|
+
const appUsage = await readApplicationUsage(session.rpc);
|
|
215
|
+
if (appUsage !== null)
|
|
216
|
+
yield appUsage;
|
|
217
|
+
terminalReason = 'stop';
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
if (terminalReason === 'error') {
|
|
221
|
+
// 失败详情已经在通知监听器中捕获;这里统一发唯一终态。
|
|
222
|
+
yield { type: 'finish', reason: 'error', failure: zcodeFailure(session) };
|
|
223
|
+
}
|
|
224
|
+
else if (terminalReason !== null) {
|
|
225
|
+
yield { type: 'finish', reason: input.signal?.aborted ? 'cancel' : terminalReason };
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
// 理论上只剩取消信号,但保留稳定终态,避免上层收到无 finish 的流。
|
|
229
|
+
yield { type: 'finish', reason: 'cancel' };
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
catch (error) {
|
|
233
|
+
if (!input.signal?.aborted)
|
|
234
|
+
throw error;
|
|
235
|
+
yield { type: 'finish', reason: 'cancel' };
|
|
236
|
+
}
|
|
237
|
+
finally {
|
|
238
|
+
input.signal?.removeEventListener('abort', onAbort);
|
|
239
|
+
removeNotificationListener();
|
|
240
|
+
removeExitListener();
|
|
241
|
+
eventQueue.close();
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
async interrupt(sessionId) {
|
|
245
|
+
const session = this.sessions.get(sessionId);
|
|
246
|
+
if (session === undefined)
|
|
247
|
+
return;
|
|
248
|
+
await session.rpc.request('session/stop', { sessionId: session.acpSessionId }).catch(() => undefined);
|
|
249
|
+
}
|
|
250
|
+
dispose() {
|
|
251
|
+
for (const session of this.sessions.values())
|
|
252
|
+
session.rpc.dispose();
|
|
253
|
+
this.sessions.clear();
|
|
254
|
+
for (const rpc of this.processes)
|
|
255
|
+
rpc.dispose();
|
|
256
|
+
this.processes.clear();
|
|
257
|
+
this.cachedRuntime = undefined;
|
|
258
|
+
this.cachedBinary = null;
|
|
259
|
+
this.cachedCatalog = null;
|
|
260
|
+
}
|
|
261
|
+
resolveRuntime() {
|
|
262
|
+
if (this.cachedRuntime === undefined)
|
|
263
|
+
this.cachedRuntime = resolveZCodeDesktopRuntime();
|
|
264
|
+
return this.cachedRuntime;
|
|
265
|
+
}
|
|
266
|
+
startAppServer() {
|
|
267
|
+
if (this.cachedBinary !== null) {
|
|
268
|
+
return new JsonRpcProcess({ command: this.cachedBinary, args: ['app-server'], wireFormat: 'zcode', spawn: this.runSpawn });
|
|
269
|
+
}
|
|
270
|
+
const runtime = this.resolveRuntime();
|
|
271
|
+
if (runtime !== null) {
|
|
272
|
+
const node = desktopCliRuntimeCommand();
|
|
273
|
+
return new JsonRpcProcess({
|
|
274
|
+
command: quoteWindowsArg(node.command),
|
|
275
|
+
// JsonRpcProcess 在 Windows 上经 shell 启动;node 与入口安装路径(如
|
|
276
|
+
// D:\Program Files\…)都可能含空格,command 和入口参数都必须先加引号。
|
|
277
|
+
args: [quoteWindowsArg(runtime.entry), 'app-server'],
|
|
278
|
+
env: { ...node.env, ...runtime.env },
|
|
279
|
+
wireFormat: 'zcode',
|
|
280
|
+
spawn: this.runSpawn,
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
const binary = this.cachedBinary ?? 'zcode';
|
|
284
|
+
return new JsonRpcProcess({ command: binary, args: ['app-server'], wireFormat: 'zcode', spawn: this.runSpawn });
|
|
285
|
+
}
|
|
286
|
+
/** 复用同 cwd 的常驻 app 进程;cwd 变化或进程死亡时重建并重新挂载会话。 */
|
|
287
|
+
async getSession(input) {
|
|
288
|
+
const previous = this.sessions.get(input.sessionId);
|
|
289
|
+
if (previous !== undefined && previous.cwd === input.cwd && !previous.rpc.isClosed)
|
|
290
|
+
return previous;
|
|
291
|
+
previous?.rpc.dispose();
|
|
292
|
+
const rpc = this.startAppServer();
|
|
293
|
+
const session = {
|
|
294
|
+
rpc,
|
|
295
|
+
cwd: input.cwd,
|
|
296
|
+
acpSessionId: '',
|
|
297
|
+
providerSessionId: input.providerSessionId ?? input.sessionId,
|
|
298
|
+
sawRunning: false,
|
|
299
|
+
subscribed: false,
|
|
300
|
+
sawText: false,
|
|
301
|
+
failureCode: undefined,
|
|
302
|
+
failureMessage: undefined,
|
|
303
|
+
};
|
|
304
|
+
this.processes.add(rpc);
|
|
305
|
+
this.sessions.set(input.sessionId, session);
|
|
306
|
+
rpc.addExitListener(() => {
|
|
307
|
+
this.processes.delete(rpc);
|
|
308
|
+
if (this.sessions.get(input.sessionId)?.rpc === rpc)
|
|
309
|
+
this.sessions.delete(input.sessionId);
|
|
310
|
+
});
|
|
311
|
+
// ZCode Protocol 没有 initialize 握手(服务端会回 Method not found),
|
|
312
|
+
// 服务端反向请求(运行时偏好 / Provider 运行时认证头)必须在首个请求前就绪。
|
|
313
|
+
rpc.setServerRequestHandler((request) => handleZcodeServerRequest(request));
|
|
314
|
+
return session;
|
|
315
|
+
}
|
|
316
|
+
installServerRequestHandler(rpc) {
|
|
317
|
+
rpc.setServerRequestHandler((request) => handleZcodeServerRequest(request));
|
|
318
|
+
}
|
|
319
|
+
async syncAccountProviderConfig(rpc, signal) {
|
|
320
|
+
if (this.cachedBinary !== null)
|
|
321
|
+
return;
|
|
322
|
+
const runtime = this.resolveRuntime();
|
|
323
|
+
if (runtime === null)
|
|
324
|
+
return;
|
|
325
|
+
const snapshot = readZcodeAccountProviderSnapshot(runtime);
|
|
326
|
+
if (snapshot === null)
|
|
327
|
+
return;
|
|
328
|
+
try {
|
|
329
|
+
await rpc.request('provider/updateAccountConfig', snapshot, { signal, killOnAbort: false });
|
|
330
|
+
}
|
|
331
|
+
catch (error) {
|
|
332
|
+
// 旧版 app-server 没有该方法时仍允许使用默认模型;新版本的真实
|
|
333
|
+
// Provider 目录则必须在 create 前完成同步,失败直接交给 create 处理。
|
|
334
|
+
if (!isMethodUnavailable(error))
|
|
335
|
+
throw error;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
async applyModelSelection(session, input) {
|
|
339
|
+
if ((input.modelId === undefined || input.modelId.trim() === '' || input.modelId === 'provider-default') &&
|
|
340
|
+
(input.effortId === undefined || input.effortId.trim() === ''))
|
|
341
|
+
return;
|
|
342
|
+
const selection = resolveZcodeModelSelection(input.modelId, input.effortId, this.cachedCatalog);
|
|
343
|
+
if (selection === null)
|
|
344
|
+
throw new Error(`ZCode 模型选择无效: ${input.modelId ?? 'provider-default'}`);
|
|
345
|
+
await session.rpc.request('session/setModel', {
|
|
346
|
+
sessionId: session.acpSessionId,
|
|
347
|
+
model: selection,
|
|
348
|
+
persistAsWorkspaceLastUsed: false,
|
|
349
|
+
}, { signal: input.signal, killOnAbort: false });
|
|
350
|
+
}
|
|
351
|
+
/** ZCode Protocol 默认只发送状态与遥测通知;订阅后才会推送正文事件。 */
|
|
352
|
+
async subscribeSessionEvents(session, signal) {
|
|
353
|
+
if (session.subscribed)
|
|
354
|
+
return;
|
|
355
|
+
try {
|
|
356
|
+
await session.rpc.request('session/subscribe', {
|
|
357
|
+
sessionId: session.acpSessionId,
|
|
358
|
+
deliveryKind: 'desktop-continuous',
|
|
359
|
+
includeSnapshot: false,
|
|
360
|
+
}, { signal, killOnAbort: false });
|
|
361
|
+
session.subscribed = true;
|
|
362
|
+
}
|
|
363
|
+
catch (error) {
|
|
364
|
+
// 旧版 ZCode 没有订阅接口时仍保留状态通知和旧消息通知兼容路径。
|
|
365
|
+
if (!isMethodUnavailable(error))
|
|
366
|
+
throw error;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
/** turn.terminal 失败详情(errorCode/errorMessage)在通知到达时即捕获。 */
|
|
371
|
+
function captureZcodeFailureDetail(message, session) {
|
|
372
|
+
if (message.method !== 'v4/telemetry/event')
|
|
373
|
+
return;
|
|
374
|
+
const params = isRecord(message.params) ? message.params : {};
|
|
375
|
+
if (params.kind !== 'turn.terminal' || params.status !== 'failed')
|
|
376
|
+
return;
|
|
377
|
+
if (typeof params.errorCode === 'string' && params.errorCode.trim() !== '')
|
|
378
|
+
session.failureCode = params.errorCode;
|
|
379
|
+
if (typeof params.errorMessage === 'string' && params.errorMessage.trim() !== '')
|
|
380
|
+
session.failureMessage = params.errorMessage;
|
|
381
|
+
}
|
|
382
|
+
/** ZCode 回合通知 → 单个统一事件;终态由 readZcodeTerminalReason 单独表达。 */
|
|
383
|
+
function zcodeMessageToChunk(message, session, input) {
|
|
384
|
+
const method = typeof message.method === 'string' ? message.method : '';
|
|
385
|
+
if (method === '' || method.startsWith('startup/') || method.startsWith('process/'))
|
|
386
|
+
return null;
|
|
387
|
+
const params = isRecord(message.params) ? message.params : {};
|
|
388
|
+
if (method === 'v4/telemetry/event') {
|
|
389
|
+
if (params.kind === 'turn.terminal' && params.status === 'failed') {
|
|
390
|
+
session.failureCode = typeof params.errorCode === 'string' ? params.errorCode : undefined;
|
|
391
|
+
session.failureMessage = typeof params.errorMessage === 'string' ? params.errorMessage : undefined;
|
|
392
|
+
}
|
|
393
|
+
return null;
|
|
394
|
+
}
|
|
395
|
+
if (method === 'computer-use/operation-event') {
|
|
396
|
+
const kind = typeof params.kind === 'string' ? params.kind : '';
|
|
397
|
+
if (kind === 'turn-failed' || kind.includes('fail')) {
|
|
398
|
+
session.failureCode = session.failureCode ?? 'turn_failed';
|
|
399
|
+
}
|
|
400
|
+
return null;
|
|
401
|
+
}
|
|
402
|
+
if (method === 'session/event') {
|
|
403
|
+
const payload = isRecord(params.payload) ? params.payload : {};
|
|
404
|
+
const kind = typeof payload.kind === 'string' ? payload.kind : '';
|
|
405
|
+
const messageId = typeof payload.assistantMessageId === 'string' ? payload.assistantMessageId : undefined;
|
|
406
|
+
if (kind === 'reasoning_delta') {
|
|
407
|
+
const text = firstText(payload.delta, payload.text);
|
|
408
|
+
return text === null ? null : { type: 'reasoning-delta', text, ...(messageId === undefined ? {} : { messageId }) };
|
|
409
|
+
}
|
|
410
|
+
if (kind === 'text_delta') {
|
|
411
|
+
const text = firstText(payload.delta, payload.text);
|
|
412
|
+
if (text === null)
|
|
413
|
+
return null;
|
|
414
|
+
session.sawText = true;
|
|
415
|
+
return { type: 'text-delta', text, ...(messageId === undefined ? {} : { messageId }) };
|
|
416
|
+
}
|
|
417
|
+
// 某些版本只保留 turn.completed 快照,不发送 text_delta;只有当前回合
|
|
418
|
+
// 尚未输出正文时才使用该快照,避免把增量正文再追加一遍。
|
|
419
|
+
if (typeof params.type === 'string' && params.type === 'turn.completed' && !session.sawText) {
|
|
420
|
+
const text = firstText(payload.response, payload.content);
|
|
421
|
+
return text === null ? null : { type: 'text-snapshot', text };
|
|
422
|
+
}
|
|
423
|
+
return null;
|
|
424
|
+
}
|
|
425
|
+
if (method === 'state.updated') {
|
|
426
|
+
const reason = typeof params.reason === 'string' ? params.reason : '';
|
|
427
|
+
const patch = isRecord(params.patch) ? params.patch : {};
|
|
428
|
+
if (reason === 'prompt_started' || patch.status === 'running')
|
|
429
|
+
session.sawRunning = true;
|
|
430
|
+
if (reason.includes('failed')) {
|
|
431
|
+
session.failureCode = session.failureCode ?? 'prompt_failed';
|
|
432
|
+
}
|
|
433
|
+
return null;
|
|
434
|
+
}
|
|
435
|
+
// 其余消息类通知做保守的正文提取:params 里的 delta/text/content 字符串。
|
|
436
|
+
const text = firstText(params.delta, params.text, params.content);
|
|
437
|
+
if (text !== null) {
|
|
438
|
+
session.sawText = true;
|
|
439
|
+
return { type: 'text-delta', text };
|
|
440
|
+
}
|
|
441
|
+
return null;
|
|
442
|
+
}
|
|
443
|
+
/** 从通知流推定回合是否已终态;返回 null 表示回合仍在进行。 */
|
|
444
|
+
function readZcodeTerminalReason(message, session, input) {
|
|
445
|
+
if (input.signal?.aborted)
|
|
446
|
+
return 'cancel';
|
|
447
|
+
const method = typeof message.method === 'string' ? message.method : '';
|
|
448
|
+
const params = isRecord(message.params) ? message.params : {};
|
|
449
|
+
if (method === 'state.updated') {
|
|
450
|
+
const reason = typeof params.reason === 'string' ? params.reason : '';
|
|
451
|
+
const patch = isRecord(params.patch) ? params.patch : {};
|
|
452
|
+
if (reason.includes('failed'))
|
|
453
|
+
return 'error';
|
|
454
|
+
// 成功终态:回合进入过 running 后回到 idle。
|
|
455
|
+
if (session.sawRunning && patch.status === 'idle')
|
|
456
|
+
return 'stop';
|
|
457
|
+
}
|
|
458
|
+
if (method === 'computer-use/operation-event') {
|
|
459
|
+
const kind = typeof params.kind === 'string' ? params.kind : '';
|
|
460
|
+
if (kind === 'turn-failed' || kind.includes('fail'))
|
|
461
|
+
return 'error';
|
|
462
|
+
// desktop-continuous 的 turn.completed 事件可能稍晚于 computer-use
|
|
463
|
+
// 通知到达;没有正文增量时要等会话快照,避免丢掉最终回答。
|
|
464
|
+
if (kind.includes('complete') && (session.sawText || !session.subscribed))
|
|
465
|
+
return 'stop';
|
|
466
|
+
}
|
|
467
|
+
if (method === 'session/event' && params.type === 'turn.completed') {
|
|
468
|
+
return 'stop';
|
|
469
|
+
}
|
|
470
|
+
if (method === 'v4/telemetry/event') {
|
|
471
|
+
if (params.kind === 'turn.terminal') {
|
|
472
|
+
if (params.status === 'failed')
|
|
473
|
+
return 'error';
|
|
474
|
+
if (session.sawText || !session.subscribed)
|
|
475
|
+
return 'stop';
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
return null;
|
|
479
|
+
}
|
|
480
|
+
function failureChunk(session) {
|
|
481
|
+
const code = session.failureCode;
|
|
482
|
+
const detail = session.failureMessage;
|
|
483
|
+
const hint = code === 'provider_not_found'
|
|
484
|
+
? '(ZCode 独立运行时还没有可用的模型提供商:请在终端执行一次 zcode login 完成登录后重试)'
|
|
485
|
+
: code === '1113'
|
|
486
|
+
? '(ZCode 当前账号没有可用资源包,请检查套餐余额或切换有额度的账号)'
|
|
487
|
+
: '';
|
|
488
|
+
return {
|
|
489
|
+
type: 'text-snapshot',
|
|
490
|
+
text: `ZCode 回合失败${code ? ` [${code}]` : ''}${detail ? `:${detail}` : ''}${hint}`,
|
|
491
|
+
};
|
|
492
|
+
}
|
|
493
|
+
function zcodeFailure(session) {
|
|
494
|
+
const message = session.failureMessage?.trim() || 'ZCode Provider 未返回具体失败信息。';
|
|
495
|
+
const code = session.failureCode?.trim();
|
|
496
|
+
return code ? { message, code } : { message };
|
|
497
|
+
}
|
|
498
|
+
async function readSessionUsage(rpc, sessionId) {
|
|
499
|
+
try {
|
|
500
|
+
const controller = new AbortController();
|
|
501
|
+
const timer = setTimeout(() => controller.abort(), 3_000);
|
|
502
|
+
timer.unref?.();
|
|
503
|
+
const usage = await rpc.request('session/usage', { sessionId }, { signal: controller.signal });
|
|
504
|
+
clearTimeout(timer);
|
|
505
|
+
return usageChunk(usage);
|
|
506
|
+
}
|
|
507
|
+
catch {
|
|
508
|
+
return null;
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
function zcodeWorkspace(cwd) {
|
|
512
|
+
const workspacePath = cwd?.trim() !== '' && cwd !== undefined ? cwd : process.cwd();
|
|
513
|
+
return { workspacePath, workspaceKey: workspacePath };
|
|
514
|
+
}
|
|
515
|
+
function readSessionId(created) {
|
|
516
|
+
if (typeof created !== 'object' || created === null)
|
|
517
|
+
return undefined;
|
|
518
|
+
const session = created.session;
|
|
519
|
+
if (typeof session === 'object' && session !== null) {
|
|
520
|
+
const id = session.sessionId;
|
|
521
|
+
if (typeof id === 'string' && id !== '')
|
|
522
|
+
return id;
|
|
523
|
+
}
|
|
524
|
+
const direct = created.sessionId;
|
|
525
|
+
return typeof direct === 'string' && direct !== '' ? direct : undefined;
|
|
526
|
+
}
|
|
527
|
+
function firstText(...values) {
|
|
528
|
+
for (const value of values) {
|
|
529
|
+
if (typeof value === 'string' && value.trim() !== '')
|
|
530
|
+
return value;
|
|
531
|
+
}
|
|
532
|
+
return null;
|
|
533
|
+
}
|
|
534
|
+
/** Windows shell 拼接前的引号保护:安全字符集直接通过,其余成对引号包裹。 */
|
|
535
|
+
function quoteWindowsArg(value) {
|
|
536
|
+
if (process.platform !== 'win32')
|
|
537
|
+
return value;
|
|
538
|
+
if (/^[A-Za-z0-9_./\\:-]+$/u.test(value))
|
|
539
|
+
return value;
|
|
540
|
+
return `"${value.replace(/"/gu, '""')}"`;
|
|
541
|
+
}
|
|
542
|
+
function isRecord(value) { return typeof value === 'object' && value !== null && !Array.isArray(value); }
|
|
543
|
+
function catalogFromZcodeSnapshot(value) {
|
|
544
|
+
const root = isRecord(value) && isRecord(value.snapshot) ? value.snapshot : value;
|
|
545
|
+
const settings = isRecord(root) && isRecord(root.settings) ? root.settings : undefined;
|
|
546
|
+
const modelSettings = settings !== undefined && isRecord(settings.model) ? settings.model : undefined;
|
|
547
|
+
const available = modelSettings !== undefined && Array.isArray(modelSettings.available) ? modelSettings.available : [];
|
|
548
|
+
const groups = new Map();
|
|
549
|
+
for (const item of available) {
|
|
550
|
+
if (!isRecord(item) || !isRecord(item.ref))
|
|
551
|
+
continue;
|
|
552
|
+
const providerId = typeof item.ref.providerId === 'string' ? item.ref.providerId.trim() : '';
|
|
553
|
+
const modelId = typeof item.ref.modelId === 'string' ? item.ref.modelId.trim() : '';
|
|
554
|
+
if (!providerId || !modelId)
|
|
555
|
+
continue;
|
|
556
|
+
const efforts = isRecord(item.reasoning) && Array.isArray(item.reasoning.levels)
|
|
557
|
+
? item.reasoning.levels.flatMap((level) => isRecord(level) && typeof level.value === 'string' ? [level.value] : [])
|
|
558
|
+
: [];
|
|
559
|
+
const group = groups.get(providerId) ?? { name: typeof item.providerLabel === 'string' ? item.providerLabel : providerId, models: [] };
|
|
560
|
+
group.models.push({
|
|
561
|
+
id: `${providerId}/${modelId}`,
|
|
562
|
+
name: typeof item.label === 'string' && item.label.trim() !== '' ? item.label : modelId,
|
|
563
|
+
...(typeof item.description === 'string' ? { description: item.description } : {}),
|
|
564
|
+
efforts: [...new Set(efforts)],
|
|
565
|
+
});
|
|
566
|
+
groups.set(providerId, group);
|
|
567
|
+
}
|
|
568
|
+
const current = modelSettings !== undefined && isRecord(modelSettings.current) ? modelSettings.current : undefined;
|
|
569
|
+
const currentModel = current !== undefined && typeof current.providerId === 'string' && typeof current.modelId === 'string'
|
|
570
|
+
? `${current.providerId}/${current.modelId}` : null;
|
|
571
|
+
const currentEffort = current !== undefined && isRecord(current.options) && typeof current.options.reasoningLevel === 'string'
|
|
572
|
+
? current.options.reasoningLevel : null;
|
|
573
|
+
return {
|
|
574
|
+
groups: [...groups.entries()].map(([id, group]) => ({ id, name: group.name, models: group.models })),
|
|
575
|
+
currentModel,
|
|
576
|
+
currentEffort,
|
|
577
|
+
};
|
|
578
|
+
}
|
|
579
|
+
function resolveZcodeModelSelection(modelId, effortId, catalog) {
|
|
580
|
+
const requested = modelId?.trim() ?? '';
|
|
581
|
+
const effectiveRequested = !requested || requested === 'provider-default' ? catalog?.currentModel ?? '' : requested;
|
|
582
|
+
if (!effectiveRequested)
|
|
583
|
+
return null;
|
|
584
|
+
const entries = (catalog?.groups ?? []).flatMap((group) => group.models.map((model) => ({ group, model })));
|
|
585
|
+
const found = entries.find(({ model }) => model.id === effectiveRequested)
|
|
586
|
+
?? (entries.length > 0 && !effectiveRequested.includes('/') ? entries.find(({ model }) => model.id.endsWith(`/${effectiveRequested}`)) : undefined);
|
|
587
|
+
if (found === undefined)
|
|
588
|
+
return null;
|
|
589
|
+
const effort = effortId?.trim();
|
|
590
|
+
if (effort !== undefined && effort !== '' && !found.model.efforts.includes(effort)) {
|
|
591
|
+
throw new Error(`ZCode 思维强度不可用: ${effort}`);
|
|
592
|
+
}
|
|
593
|
+
return {
|
|
594
|
+
providerId: found.group.id,
|
|
595
|
+
modelId: found.model.id.slice(found.group.id.length + 1),
|
|
596
|
+
...(effort ? { options: { reasoningLevel: effort } } : {}),
|
|
597
|
+
};
|
|
598
|
+
}
|
|
599
|
+
function readZcodeAccountProviderSnapshot(runtime) {
|
|
600
|
+
const file = runtime.env.ZCODE_BUILTIN_PROVIDER_CONFIG_FILE;
|
|
601
|
+
if (typeof file !== 'string' || file.trim() === '')
|
|
602
|
+
return null;
|
|
603
|
+
try {
|
|
604
|
+
const document = JSON.parse(readFileSync(file, 'utf8'));
|
|
605
|
+
const rules = document.config?.providerConfigRules?.providerRules;
|
|
606
|
+
if (!Array.isArray(rules))
|
|
607
|
+
return null;
|
|
608
|
+
const settings = readJsonFile(join(homedir(), '.zcode', 'v2', 'setting.json'));
|
|
609
|
+
const preferred = resolvePreferredAccountProvider(rules, settings);
|
|
610
|
+
const providers = {};
|
|
611
|
+
const states = {};
|
|
612
|
+
for (const rule of rules) {
|
|
613
|
+
if (!isRecord(rule) || typeof rule.providerId !== 'string' || !rule.providerId.startsWith('account:'))
|
|
614
|
+
continue;
|
|
615
|
+
const config = isRecord(rule.config) ? rule.config : {};
|
|
616
|
+
// ZCode 的试用额度属于 start-plan,和设置中选中的 coding-plan 是两条
|
|
617
|
+
// 独立的 Provider。只把 preferred 标为 entitled 会把试用 Provider
|
|
618
|
+
// 错误地过滤掉,随后模型请求就会落到没有资源包的 BigModel API。
|
|
619
|
+
const entitled = accountProviderHasCredentials(rule) ?? rule.providerId === preferred;
|
|
620
|
+
const active = rule.providerId === preferred;
|
|
621
|
+
providers[rule.providerId] = {
|
|
622
|
+
access: { type: 'zhipu-account', entitled },
|
|
623
|
+
...(entitled && Array.isArray(config.builtinModelIds) ? { builtinModelIds: config.builtinModelIds } : {}),
|
|
624
|
+
};
|
|
625
|
+
states[rule.providerId] = {
|
|
626
|
+
availability: entitled ? 'available' : 'unavailable',
|
|
627
|
+
entitled,
|
|
628
|
+
current: active,
|
|
629
|
+
...(entitled ? {} : { unavailableReason: 'not-entitled' }),
|
|
630
|
+
};
|
|
631
|
+
}
|
|
632
|
+
if (preferred === null)
|
|
633
|
+
return null;
|
|
634
|
+
const basedOn = `zcode-builtin:${String(document.revision ?? 0)}:${createHash('sha256').update(file).digest('hex')}`;
|
|
635
|
+
return {
|
|
636
|
+
revision: `account:${JSON.stringify([basedOn, providers, states])}`,
|
|
637
|
+
basedOnZCodeBuiltinRevision: basedOn,
|
|
638
|
+
providers,
|
|
639
|
+
states,
|
|
640
|
+
};
|
|
641
|
+
}
|
|
642
|
+
catch {
|
|
643
|
+
return null;
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
/** 读取 ZCode 登录态 JWT;Start Plan 使用它作为模型请求凭据。 */
|
|
647
|
+
function readZcodeJwtToken() {
|
|
648
|
+
const path = join(homedir(), '.zcode', 'v2', 'credentials.json');
|
|
649
|
+
try {
|
|
650
|
+
const credentials = JSON.parse(readFileSync(path, 'utf8'));
|
|
651
|
+
const value = credentials.zcodejwttoken;
|
|
652
|
+
if (typeof value !== 'string')
|
|
653
|
+
return null;
|
|
654
|
+
const token = decryptZcodeCredential(value).trim();
|
|
655
|
+
return token === '' ? null : token;
|
|
656
|
+
}
|
|
657
|
+
catch {
|
|
658
|
+
return null;
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
/** 处理 ZCode Protocol 的客户端反向请求;模型请求必须提供账号 API Key。 */
|
|
662
|
+
function handleZcodeServerRequest(request) {
|
|
663
|
+
if (request.method === 'session/requestRuntimePreferences') {
|
|
664
|
+
return { nativeSearchEnhancementsEnabled: false, memoryEnabled: false, askUserQuestionAutoResolutionEnabled: true };
|
|
665
|
+
}
|
|
666
|
+
if (request.method === 'interaction/requestProviderRuntimeHeaders') {
|
|
667
|
+
const params = isRecord(request.params) ? request.params : {};
|
|
668
|
+
const providerId = typeof params.providerId === 'string' ? params.providerId.trim() : '';
|
|
669
|
+
if (providerId.endsWith('-start-plan') || providerId.endsWith('-offpeak-idle-plan')) {
|
|
670
|
+
const token = readZcodeJwtToken();
|
|
671
|
+
if (token !== null) {
|
|
672
|
+
const runtime = resolveZcodeRuntimeHeaders();
|
|
673
|
+
return {
|
|
674
|
+
headersApplied: true,
|
|
675
|
+
requestAuth: {
|
|
676
|
+
apiKey: token,
|
|
677
|
+
...(Object.keys(runtime).length > 0 ? { headers: runtime } : {}),
|
|
678
|
+
},
|
|
679
|
+
};
|
|
680
|
+
}
|
|
681
|
+
return { headersApplied: false, errorMessage: 'ZCode Start Plan 登录凭据不可用,请重新登录 ZCode' };
|
|
682
|
+
}
|
|
683
|
+
const apiKey = providerId === '' ? null : readZcodeProviderApiKey(providerId);
|
|
684
|
+
if (apiKey !== null)
|
|
685
|
+
return { headersApplied: true, requestAuth: { apiKey } };
|
|
686
|
+
return { headersApplied: false, errorMessage: 'ZCode Provider 账号凭据不可用,请重新登录 ZCode' };
|
|
687
|
+
}
|
|
688
|
+
// 旧版 app-server 可能发送尚未定义的可选请求;保持兼容,不阻断会话创建。
|
|
689
|
+
return {};
|
|
690
|
+
}
|
|
691
|
+
/** Start Plan 接口要求的客户端标识,值只用于请求头,不进入日志和持久化。 */
|
|
692
|
+
function resolveZcodeRuntimeHeaders() {
|
|
693
|
+
const headers = {};
|
|
694
|
+
try {
|
|
695
|
+
const telemetryPath = join(homedir(), '.zcode', 'v2', 'telemetry-state.json');
|
|
696
|
+
const telemetry = JSON.parse(readFileSync(telemetryPath, 'utf8'));
|
|
697
|
+
if (typeof telemetry.deviceMid === 'string' && telemetry.deviceMid.trim() !== '') {
|
|
698
|
+
headers['X-Device-Mid'] = telemetry.deviceMid.trim();
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
catch {
|
|
702
|
+
// 没有设备标识时仍允许协议尝试,服务端会返回稳定的鉴权错误。
|
|
703
|
+
}
|
|
704
|
+
const version = resolveZCodeDesktopRuntime()?.appVersion?.trim() ?? null;
|
|
705
|
+
if (version !== null)
|
|
706
|
+
headers['X-Client-Version'] = version;
|
|
707
|
+
return headers;
|
|
708
|
+
}
|
|
709
|
+
/** 从 ZCode 共享凭据文件读取指定账号 Provider 的 API Key;原文只留在 Host。 */
|
|
710
|
+
function readZcodeProviderApiKey(providerId) {
|
|
711
|
+
const path = join(homedir(), '.zcode', 'v2', 'credentials.json');
|
|
712
|
+
try {
|
|
713
|
+
const credentials = JSON.parse(readFileSync(path, 'utf8'));
|
|
714
|
+
const prefix = `account-provider:coding-plan:${providerId}:account:`;
|
|
715
|
+
const key = Object.keys(credentials).find((candidate) => candidate.startsWith(prefix) && candidate.endsWith(':api-key'));
|
|
716
|
+
if (key === undefined || typeof credentials[key] !== 'string')
|
|
717
|
+
return null;
|
|
718
|
+
const value = decryptZcodeCredential(credentials[key]);
|
|
719
|
+
return value.trim() === '' ? null : value.trim();
|
|
720
|
+
}
|
|
721
|
+
catch {
|
|
722
|
+
return null;
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
/** 根据 ZCode 内置 Provider 的套餐类型判断本机是否有对应凭据。 */
|
|
726
|
+
function accountProviderHasCredentials(rule) {
|
|
727
|
+
const providerId = typeof rule.providerId === 'string' ? rule.providerId : '';
|
|
728
|
+
const config = isRecord(rule.config) ? rule.config : {};
|
|
729
|
+
const access = isRecord(config.access) ? config.access : {};
|
|
730
|
+
const mode = typeof access.mode === 'string' ? access.mode : '';
|
|
731
|
+
if (mode === 'start-plan' || mode === 'off-peak')
|
|
732
|
+
return readZcodeJwtToken() !== null;
|
|
733
|
+
if (mode === 'individual-coding-plan' || mode === 'team-coding-plan') {
|
|
734
|
+
return readZcodeProviderApiKey(providerId) !== null;
|
|
735
|
+
}
|
|
736
|
+
return null;
|
|
737
|
+
}
|
|
738
|
+
function decryptZcodeCredential(value) {
|
|
739
|
+
if (!value.startsWith('enc:v1:'))
|
|
740
|
+
return value;
|
|
741
|
+
const [ivRaw, authTagRaw, cipherRaw] = value.slice('enc:v1:'.length).split('.');
|
|
742
|
+
if (!ivRaw || !authTagRaw || !cipherRaw)
|
|
743
|
+
return '';
|
|
744
|
+
try {
|
|
745
|
+
const iv = Buffer.from(ivRaw, 'base64url');
|
|
746
|
+
const authTag = Buffer.from(authTagRaw, 'base64url');
|
|
747
|
+
const cipherText = Buffer.from(cipherRaw, 'base64url');
|
|
748
|
+
if (iv.length !== 12 || authTag.length !== 16)
|
|
749
|
+
return '';
|
|
750
|
+
let username = 'unknown';
|
|
751
|
+
try {
|
|
752
|
+
username = userInfo().username;
|
|
753
|
+
}
|
|
754
|
+
catch { /* 沙箱环境可能无法读取用户名。 */ }
|
|
755
|
+
const secret = `zcode-credential-fallback:${process.platform}:${homedir()}:${username}`;
|
|
756
|
+
const decipher = createDecipheriv('aes-256-gcm', createHash('sha256').update(secret).digest(), iv);
|
|
757
|
+
decipher.setAuthTag(authTag);
|
|
758
|
+
return Buffer.concat([decipher.update(cipherText), decipher.final()]).toString('utf8');
|
|
759
|
+
}
|
|
760
|
+
catch {
|
|
761
|
+
return '';
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
function resolvePreferredAccountProvider(rules, settings) {
|
|
765
|
+
const ids = new Set(rules.flatMap((rule) => isRecord(rule) && typeof rule.providerId === 'string' && rule.providerId.startsWith('account:') ? [rule.providerId] : []));
|
|
766
|
+
const selections = settings?.providerFamilyConnectionSelections;
|
|
767
|
+
if (isRecord(selections)) {
|
|
768
|
+
for (const [family, selection] of Object.entries(selections)) {
|
|
769
|
+
const kind = isRecord(selection) && typeof selection.kind === 'string' ? selection.kind : '';
|
|
770
|
+
const candidate = `account:${family}-${kind}`;
|
|
771
|
+
if (ids.has(candidate)) {
|
|
772
|
+
const startPlan = `account:${family}-start-plan`;
|
|
773
|
+
// 设置中的套餐是用户的明确选择。只有选中的 Provider 没有对应凭据时,
|
|
774
|
+
// 才回退到仍有登录态的 Start Plan,避免普通套餐被 JWT 静默遮蔽。
|
|
775
|
+
const selectedRule = rules.find((rule) => isRecord(rule) && rule.providerId === candidate);
|
|
776
|
+
if (selectedRule !== undefined && accountProviderHasCredentials(selectedRule) === true)
|
|
777
|
+
return candidate;
|
|
778
|
+
if (kind === 'start-plan' || !ids.has(startPlan) || readZcodeJwtToken() === null)
|
|
779
|
+
return candidate;
|
|
780
|
+
return startPlan;
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
return null;
|
|
785
|
+
}
|
|
786
|
+
function readJsonFile(path) {
|
|
787
|
+
try {
|
|
788
|
+
const value = JSON.parse(readFileSync(path, 'utf8'));
|
|
789
|
+
return isRecord(value) ? value : null;
|
|
790
|
+
}
|
|
791
|
+
catch {
|
|
792
|
+
return null;
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
function isMethodUnavailable(error) {
|
|
796
|
+
return error instanceof JsonRpcRequestError && (error.code === -32601 || error.code === -32001);
|
|
797
|
+
}
|
|
798
|
+
async function readApplicationUsage(rpc) {
|
|
799
|
+
for (const method of ['v4/usage/stats', 'usage/stats']) {
|
|
800
|
+
const controller = new AbortController();
|
|
801
|
+
const timer = setTimeout(() => controller.abort(), 500);
|
|
802
|
+
try {
|
|
803
|
+
const value = await rpc.request(method, { range: 'all' }, { signal: controller.signal, killOnAbort: false });
|
|
804
|
+
const summary = isRecord(value) && isRecord(value.summary) ? value.summary : value;
|
|
805
|
+
return usageChunk(summary);
|
|
806
|
+
}
|
|
807
|
+
catch {
|
|
808
|
+
// 旧版只提供 session/usage;继续尝试兼容方法。
|
|
809
|
+
}
|
|
810
|
+
finally {
|
|
811
|
+
clearTimeout(timer);
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
return null;
|
|
815
|
+
}
|
|
816
|
+
function createZcodeTurnEventQueue() {
|
|
817
|
+
const pending = [];
|
|
818
|
+
let wake;
|
|
819
|
+
let closed = false;
|
|
820
|
+
return {
|
|
821
|
+
async next() {
|
|
822
|
+
if (pending.length > 0)
|
|
823
|
+
return { value: pending.shift(), done: false };
|
|
824
|
+
if (closed)
|
|
825
|
+
return { value: undefined, done: true };
|
|
826
|
+
await new Promise((resolve) => { wake = resolve; });
|
|
827
|
+
if (pending.length > 0)
|
|
828
|
+
return { value: pending.shift(), done: false };
|
|
829
|
+
return { value: undefined, done: true };
|
|
830
|
+
},
|
|
831
|
+
push(message) {
|
|
832
|
+
pending.push(message);
|
|
833
|
+
wake?.();
|
|
834
|
+
wake = undefined;
|
|
835
|
+
},
|
|
836
|
+
close() {
|
|
837
|
+
closed = true;
|
|
838
|
+
wake?.();
|
|
839
|
+
wake = undefined;
|
|
840
|
+
},
|
|
841
|
+
};
|
|
842
|
+
}
|
|
843
|
+
//# sourceMappingURL=zcode-driver.js.map
|