@jingyi0605/codingns4dsh 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1114 -0
- package/assets/provider-icons/claude-code.png +0 -0
- package/assets/provider-icons/codex.png +0 -0
- package/assets/provider-icons/command-code.svg +5 -0
- package/assets/provider-icons/deepseek-harness.svg +9 -0
- package/assets/provider-icons/gemini.png +0 -0
- package/assets/provider-icons/grok.png +0 -0
- package/assets/provider-icons/kimi.png +0 -0
- package/assets/provider-icons/opencode.png +0 -0
- package/assets/provider-icons/pi.svg +7 -0
- package/data/build/dist/bootstrap/dsh-connection-adapter.d.ts +97 -0
- package/data/build/dist/bootstrap/dsh-connection-adapter.js +169 -0
- package/data/build/dist/bootstrap/index.d.ts +38 -0
- package/data/build/dist/bootstrap/index.js +44 -0
- package/data/build/dist/client/account-bar.d.ts +9 -0
- package/data/build/dist/client/account-bar.js +398 -0
- package/data/build/dist/client/bundle.js +26167 -0
- package/data/build/dist/client/cli-catalog.d.ts +24 -0
- package/data/build/dist/client/cli-catalog.js +108 -0
- package/data/build/dist/client/cli-slots.d.ts +38 -0
- package/data/build/dist/client/cli-slots.js +297 -0
- package/data/build/dist/client/debug/ui.d.ts +12 -0
- package/data/build/dist/client/debug/ui.js +451 -0
- package/data/build/dist/client/dsh-h5-bootstrap.d.ts +64 -0
- package/data/build/dist/client/dsh-h5-bootstrap.js +293 -0
- package/data/build/dist/client/dsh-runtime-version.d.ts +3 -0
- package/data/build/dist/client/dsh-runtime-version.js +11 -0
- package/data/build/dist/client/external-tool-stream.d.ts +24 -0
- package/data/build/dist/client/external-tool-stream.js +114 -0
- package/data/build/dist/client/features/cli-adapters.d.ts +7 -0
- package/data/build/dist/client/features/cli-adapters.js +215 -0
- package/data/build/dist/client/features/debug.d.ts +4 -0
- package/data/build/dist/client/features/debug.js +24 -0
- package/data/build/dist/client/features/index.d.ts +33 -0
- package/data/build/dist/client/features/index.js +44 -0
- package/data/build/dist/client/features/lan-access-panel.d.ts +5 -0
- package/data/build/dist/client/features/lan-access-panel.js +146 -0
- package/data/build/dist/client/features/lan-access.d.ts +9 -0
- package/data/build/dist/client/features/lan-access.js +30 -0
- package/data/build/dist/client/features/login-protection-panel.d.ts +5 -0
- package/data/build/dist/client/features/login-protection-panel.js +91 -0
- package/data/build/dist/client/features/login-protection-session.d.ts +6 -0
- package/data/build/dist/client/features/login-protection-session.js +25 -0
- package/data/build/dist/client/features/login-protection.d.ts +4 -0
- package/data/build/dist/client/features/login-protection.js +23 -0
- package/data/build/dist/client/features/reverse-proxy-panel.d.ts +9 -0
- package/data/build/dist/client/features/reverse-proxy-panel.js +159 -0
- package/data/build/dist/client/features/reverse-proxy.d.ts +12 -0
- package/data/build/dist/client/features/reverse-proxy.js +112 -0
- package/data/build/dist/client/features/terminal-enhancement-panel.d.ts +5 -0
- package/data/build/dist/client/features/terminal-enhancement-panel.js +160 -0
- package/data/build/dist/client/features/terminal-enhancement.d.ts +4 -0
- package/data/build/dist/client/features/terminal-enhancement.js +24 -0
- package/data/build/dist/client/features/types.d.ts +58 -0
- package/data/build/dist/client/features/types.js +2 -0
- package/data/build/dist/client/features/workspace-session-enhancement-panel.d.ts +5 -0
- package/data/build/dist/client/features/workspace-session-enhancement-panel.js +66 -0
- package/data/build/dist/client/features/workspace-session-enhancement.d.ts +4 -0
- package/data/build/dist/client/features/workspace-session-enhancement.js +101 -0
- package/data/build/dist/client/h5-bootstrap-entry.d.ts +2 -0
- package/data/build/dist/client/h5-bootstrap-entry.js +17 -0
- package/data/build/dist/client/index.d.ts +31 -0
- package/data/build/dist/client/index.js +98 -0
- package/data/build/dist/client/lan-access.d.ts +28 -0
- package/data/build/dist/client/lan-access.js +68 -0
- package/data/build/dist/client/locale.d.ts +20 -0
- package/data/build/dist/client/locale.js +393 -0
- package/data/build/dist/client/provider-icon-assets.d.ts +2 -0
- package/data/build/dist/client/provider-icon-assets.js +23 -0
- package/data/build/dist/client/provider-icons.d.ts +19 -0
- package/data/build/dist/client/provider-icons.js +39 -0
- package/data/build/dist/client/remote-web-context.d.ts +57 -0
- package/data/build/dist/client/remote-web-context.js +939 -0
- package/data/build/dist/client/session-adapter-cache.d.ts +18 -0
- package/data/build/dist/client/session-adapter-cache.js +84 -0
- package/data/build/dist/client/settings-bridge.d.ts +32 -0
- package/data/build/dist/client/settings-bridge.js +126 -0
- package/data/build/dist/client/settings-section.d.ts +30 -0
- package/data/build/dist/client/settings-section.js +93 -0
- package/data/build/dist/client/subscription-slot.d.ts +18 -0
- package/data/build/dist/client/subscription-slot.js +223 -0
- package/data/build/dist/client/terminal/index.d.ts +4 -0
- package/data/build/dist/client/terminal/index.js +3 -0
- package/data/build/dist/client/terminal/model.d.ts +116 -0
- package/data/build/dist/client/terminal/model.js +435 -0
- package/data/build/dist/client/terminal/styles.d.ts +21 -0
- package/data/build/dist/client/terminal/styles.js +51 -0
- package/data/build/dist/client/terminal/ui.d.ts +19 -0
- package/data/build/dist/client/terminal/ui.js +257 -0
- package/data/build/dist/client/terminal/xterm-view.d.ts +13 -0
- package/data/build/dist/client/terminal/xterm-view.js +213 -0
- package/data/build/dist/client/theme.d.ts +56 -0
- package/data/build/dist/client/theme.js +186 -0
- package/data/build/dist/client/workspace-session-archive-dom.d.ts +29 -0
- package/data/build/dist/client/workspace-session-archive-dom.js +525 -0
- package/data/build/dist/client/workspace-session-fiber.d.ts +3 -0
- package/data/build/dist/client/workspace-session-fiber.js +33 -0
- package/data/build/dist/client/workspace-session-logo-dom.d.ts +26 -0
- package/data/build/dist/client/workspace-session-logo-dom.js +128 -0
- package/data/build/dist/features/index.d.ts +3 -0
- package/data/build/dist/features/index.js +2 -0
- package/data/build/dist/features/registry.d.ts +74 -0
- package/data/build/dist/features/registry.js +382 -0
- package/data/build/dist/features/resource-scope/index.d.ts +39 -0
- package/data/build/dist/features/resource-scope/index.js +161 -0
- package/data/build/dist/host/auth-session.d.ts +42 -0
- package/data/build/dist/host/auth-session.js +186 -0
- package/data/build/dist/host/cli-adapters/claude-driver.d.ts +14 -0
- package/data/build/dist/host/cli-adapters/claude-driver.js +103 -0
- package/data/build/dist/host/cli-adapters/codex-driver.d.ts +45 -0
- package/data/build/dist/host/cli-adapters/codex-driver.js +534 -0
- package/data/build/dist/host/cli-adapters/command-code-driver.d.ts +38 -0
- package/data/build/dist/host/cli-adapters/command-code-driver.js +394 -0
- package/data/build/dist/host/cli-adapters/command-code-subscription.d.ts +19 -0
- package/data/build/dist/host/cli-adapters/command-code-subscription.js +126 -0
- package/data/build/dist/host/cli-adapters/driver.d.ts +41 -0
- package/data/build/dist/host/cli-adapters/driver.js +2 -0
- package/data/build/dist/host/cli-adapters/dsh-message-projector.d.ts +37 -0
- package/data/build/dist/host/cli-adapters/dsh-message-projector.js +180 -0
- package/data/build/dist/host/cli-adapters/dsh-tool-history.d.ts +48 -0
- package/data/build/dist/host/cli-adapters/dsh-tool-history.js +373 -0
- package/data/build/dist/host/cli-adapters/feature.d.ts +7 -0
- package/data/build/dist/host/cli-adapters/feature.js +335 -0
- package/data/build/dist/host/cli-adapters/gemini-driver.d.ts +24 -0
- package/data/build/dist/host/cli-adapters/gemini-driver.js +427 -0
- package/data/build/dist/host/cli-adapters/grok-driver.d.ts +38 -0
- package/data/build/dist/host/cli-adapters/grok-driver.js +372 -0
- package/data/build/dist/host/cli-adapters/http-sse-client.d.ts +22 -0
- package/data/build/dist/host/cli-adapters/http-sse-client.js +99 -0
- package/data/build/dist/host/cli-adapters/interaction-events.d.ts +11 -0
- package/data/build/dist/host/cli-adapters/interaction-events.js +80 -0
- package/data/build/dist/host/cli-adapters/json-rpc-process.d.ts +65 -0
- package/data/build/dist/host/cli-adapters/json-rpc-process.js +256 -0
- package/data/build/dist/host/cli-adapters/kimi-driver.d.ts +21 -0
- package/data/build/dist/host/cli-adapters/kimi-driver.js +382 -0
- package/data/build/dist/host/cli-adapters/model-catalog.d.ts +22 -0
- package/data/build/dist/host/cli-adapters/model-catalog.js +89 -0
- package/data/build/dist/host/cli-adapters/opencode-driver.d.ts +55 -0
- package/data/build/dist/host/cli-adapters/opencode-driver.js +728 -0
- package/data/build/dist/host/cli-adapters/pi-driver.d.ts +43 -0
- package/data/build/dist/host/cli-adapters/pi-driver.js +312 -0
- package/data/build/dist/host/cli-adapters/process-utils.d.ts +16 -0
- package/data/build/dist/host/cli-adapters/process-utils.js +27 -0
- package/data/build/dist/host/cli-adapters/provider-subscription.d.ts +82 -0
- package/data/build/dist/host/cli-adapters/provider-subscription.js +610 -0
- package/data/build/dist/host/cli-adapters/registry.d.ts +95 -0
- package/data/build/dist/host/cli-adapters/registry.js +659 -0
- package/data/build/dist/host/cli-adapters/rpc-driver-utils.d.ts +24 -0
- package/data/build/dist/host/cli-adapters/rpc-driver-utils.js +119 -0
- package/data/build/dist/host/cli-adapters/session-probe.d.ts +20 -0
- package/data/build/dist/host/cli-adapters/session-probe.js +139 -0
- package/data/build/dist/host/cli-adapters/session-store.d.ts +68 -0
- package/data/build/dist/host/cli-adapters/session-store.js +180 -0
- package/data/build/dist/host/cli-adapters/standard-stream-driver.d.ts +45 -0
- package/data/build/dist/host/cli-adapters/standard-stream-driver.js +205 -0
- package/data/build/dist/host/cli-adapters/stream-normalizer.d.ts +25 -0
- package/data/build/dist/host/cli-adapters/stream-normalizer.js +83 -0
- package/data/build/dist/host/cli-adapters/tool-observation.d.ts +9 -0
- package/data/build/dist/host/cli-adapters/tool-observation.js +39 -0
- package/data/build/dist/host/control-api-client.d.ts +84 -0
- package/data/build/dist/host/control-api-client.js +130 -0
- package/data/build/dist/host/credential-store.d.ts +54 -0
- package/data/build/dist/host/credential-store.js +114 -0
- package/data/build/dist/host/debug.d.ts +79 -0
- package/data/build/dist/host/debug.js +295 -0
- package/data/build/dist/host/dsh-device-runtime.d.ts +39 -0
- package/data/build/dist/host/dsh-device-runtime.js +118 -0
- package/data/build/dist/host/dsh-gateway-feature.d.ts +5 -0
- package/data/build/dist/host/dsh-gateway-feature.js +55 -0
- package/data/build/dist/host/dsh-runtime-version.d.ts +12 -0
- package/data/build/dist/host/dsh-runtime-version.js +69 -0
- package/data/build/dist/host/features/auth.d.ts +11 -0
- package/data/build/dist/host/features/auth.js +273 -0
- package/data/build/dist/host/features/debug.d.ts +5 -0
- package/data/build/dist/host/features/debug.js +90 -0
- package/data/build/dist/host/features/host-status.d.ts +12 -0
- package/data/build/dist/host/features/host-status.js +54 -0
- package/data/build/dist/host/features/index.d.ts +19 -0
- package/data/build/dist/host/features/index.js +29 -0
- package/data/build/dist/host/features/lan-access-dsh.d.ts +8 -0
- package/data/build/dist/host/features/lan-access-dsh.js +45 -0
- package/data/build/dist/host/features/terminal-process.d.ts +5 -0
- package/data/build/dist/host/features/terminal-process.js +110 -0
- package/data/build/dist/host/features/terminal-status.d.ts +18 -0
- package/data/build/dist/host/features/terminal-status.js +56 -0
- package/data/build/dist/host/features/types.d.ts +41 -0
- package/data/build/dist/host/features/types.js +2 -0
- package/data/build/dist/host/index.d.ts +43 -0
- package/data/build/dist/host/index.js +135 -0
- package/data/build/dist/host/lan-access-dsh.d.ts +83 -0
- package/data/build/dist/host/lan-access-dsh.js +831 -0
- package/data/build/dist/host/native-session-bridge.d.ts +130 -0
- package/data/build/dist/host/native-session-bridge.js +317 -0
- package/data/build/dist/host/relay-tunnel-runtime.d.ts +97 -0
- package/data/build/dist/host/relay-tunnel-runtime.js +361 -0
- package/data/build/dist/host/remote-web-runtime.d.ts +78 -0
- package/data/build/dist/host/remote-web-runtime.js +559 -0
- package/data/build/dist/host/rpc-table.d.ts +32 -0
- package/data/build/dist/host/rpc-table.js +47 -0
- package/data/build/dist/host/rpc.d.ts +18 -0
- package/data/build/dist/host/rpc.js +248 -0
- package/data/build/dist/host/settings.d.ts +19 -0
- package/data/build/dist/host/settings.js +80 -0
- package/data/build/dist/host/terminal/attachment-registry.d.ts +17 -0
- package/data/build/dist/host/terminal/attachment-registry.js +49 -0
- package/data/build/dist/host/terminal/backends/conpty-backend.d.ts +39 -0
- package/data/build/dist/host/terminal/backends/conpty-backend.js +160 -0
- package/data/build/dist/host/terminal/backends/local-pty-backend.d.ts +36 -0
- package/data/build/dist/host/terminal/backends/local-pty-backend.js +178 -0
- package/data/build/dist/host/terminal/backends/tmux-backend.d.ts +40 -0
- package/data/build/dist/host/terminal/backends/tmux-backend.js +191 -0
- package/data/build/dist/host/terminal/broker/conpty-broker-client.d.ts +27 -0
- package/data/build/dist/host/terminal/broker/conpty-broker-client.js +154 -0
- package/data/build/dist/host/terminal/broker/conpty-broker-process.d.ts +10 -0
- package/data/build/dist/host/terminal/broker/conpty-broker-process.js +147 -0
- package/data/build/dist/host/terminal/broker/conpty-broker-protocol.d.ts +92 -0
- package/data/build/dist/host/terminal/broker/conpty-broker-protocol.js +134 -0
- package/data/build/dist/host/terminal/controller-factory.d.ts +37 -0
- package/data/build/dist/host/terminal/controller-factory.js +82 -0
- package/data/build/dist/host/terminal/index.d.ts +17 -0
- package/data/build/dist/host/terminal/index.js +17 -0
- package/data/build/dist/host/terminal/runtime-adapter.d.ts +77 -0
- package/data/build/dist/host/terminal/runtime-adapter.js +18 -0
- package/data/build/dist/host/terminal/runtime-manager.d.ts +41 -0
- package/data/build/dist/host/terminal/runtime-manager.js +179 -0
- package/data/build/dist/host/terminal/shell-detection.d.ts +23 -0
- package/data/build/dist/host/terminal/shell-detection.js +105 -0
- package/data/build/dist/host/terminal/startup.d.ts +33 -0
- package/data/build/dist/host/terminal/startup.js +100 -0
- package/data/build/dist/host/terminal/terminal-controller.d.ts +78 -0
- package/data/build/dist/host/terminal/terminal-controller.js +324 -0
- package/data/build/dist/host/terminal/terminal-process-service.d.ts +30 -0
- package/data/build/dist/host/terminal/terminal-process-service.js +194 -0
- package/data/build/dist/host/terminal/terminal-process-store.d.ts +45 -0
- package/data/build/dist/host/terminal/terminal-process-store.js +183 -0
- package/data/build/dist/host/terminal/terminal-service.d.ts +87 -0
- package/data/build/dist/host/terminal/terminal-service.js +528 -0
- package/data/build/dist/host/terminal/terminal-store.d.ts +49 -0
- package/data/build/dist/host/terminal/terminal-store.js +242 -0
- package/data/build/dist/index.d.ts +37 -0
- package/data/build/dist/index.js +26 -0
- package/data/build/dist/shared/contracts/auth.d.ts +122 -0
- package/data/build/dist/shared/contracts/auth.js +8 -0
- package/data/build/dist/shared/contracts/cli-adapter.d.ts +192 -0
- package/data/build/dist/shared/contracts/cli-adapter.js +2 -0
- package/data/build/dist/shared/contracts/command-code.d.ts +5 -0
- package/data/build/dist/shared/contracts/command-code.js +2 -0
- package/data/build/dist/shared/contracts/config.d.ts +113 -0
- package/data/build/dist/shared/contracts/config.js +86 -0
- package/data/build/dist/shared/contracts/debug-config.d.ts +28 -0
- package/data/build/dist/shared/contracts/debug-config.js +78 -0
- package/data/build/dist/shared/contracts/debug.d.ts +75 -0
- package/data/build/dist/shared/contracts/debug.js +121 -0
- package/data/build/dist/shared/contracts/dsh-device.d.ts +72 -0
- package/data/build/dist/shared/contracts/dsh-device.js +2 -0
- package/data/build/dist/shared/contracts/errors.d.ts +33 -0
- package/data/build/dist/shared/contracts/errors.js +41 -0
- package/data/build/dist/shared/contracts/feature.d.ts +71 -0
- package/data/build/dist/shared/contracts/feature.js +2 -0
- package/data/build/dist/shared/contracts/host-status.d.ts +14 -0
- package/data/build/dist/shared/contracts/host-status.js +2 -0
- package/data/build/dist/shared/contracts/lan-access-dsh.d.ts +30 -0
- package/data/build/dist/shared/contracts/lan-access-dsh.js +2 -0
- package/data/build/dist/shared/contracts/peer-host.d.ts +37 -0
- package/data/build/dist/shared/contracts/peer-host.js +9 -0
- package/data/build/dist/shared/contracts/signaling.d.ts +67 -0
- package/data/build/dist/shared/contracts/signaling.js +2 -0
- package/data/build/dist/shared/contracts/subscription.d.ts +69 -0
- package/data/build/dist/shared/contracts/subscription.js +2 -0
- package/data/build/dist/shared/contracts/terminal-process.d.ts +65 -0
- package/data/build/dist/shared/contracts/terminal-process.js +2 -0
- package/data/build/dist/shared/contracts/terminal.d.ts +127 -0
- package/data/build/dist/shared/contracts/terminal.js +2 -0
- package/data/build/dist/shared/contracts/transport.d.ts +45 -0
- package/data/build/dist/shared/contracts/transport.js +3 -0
- package/data/build/dist/shared/contracts/version.d.ts +19 -0
- package/data/build/dist/shared/contracts/version.js +74 -0
- package/data/build/dist/shared/index.d.ts +22 -0
- package/data/build/dist/shared/index.js +9 -0
- package/data/build/dist/transport/carrier.d.ts +38 -0
- package/data/build/dist/transport/carrier.js +268 -0
- package/data/build/dist/transport/debug.d.ts +22 -0
- package/data/build/dist/transport/debug.js +57 -0
- package/data/build/dist/transport/dsh-envelope.d.ts +41 -0
- package/data/build/dist/transport/dsh-envelope.js +107 -0
- package/data/build/dist/transport/dsh-gateway.d.ts +64 -0
- package/data/build/dist/transport/dsh-gateway.js +254 -0
- package/data/build/dist/transport/dsh-session.d.ts +55 -0
- package/data/build/dist/transport/dsh-session.js +256 -0
- package/data/build/dist/transport/dsh-transport.d.ts +57 -0
- package/data/build/dist/transport/dsh-transport.js +125 -0
- package/data/build/dist/transport/frame.d.ts +132 -0
- package/data/build/dist/transport/frame.js +168 -0
- package/data/build/dist/transport/index.d.ts +11 -0
- package/data/build/dist/transport/index.js +11 -0
- package/data/build/dist/transport/multiplexer.d.ts +63 -0
- package/data/build/dist/transport/multiplexer.js +323 -0
- package/data/build/dist/transport/webrtc-client.d.ts +65 -0
- package/data/build/dist/transport/webrtc-client.js +255 -0
- package/data/build/dist/transport/webrtc-host.d.ts +58 -0
- package/data/build/dist/transport/webrtc-host.js +252 -0
- package/data/build/dist/typert.host.d.ts +25 -0
- package/data/build/dist/typert.host.js +150 -0
- package/dsh.bundle.patch +12 -0
- package/package.json +135 -0
- package/profile/README.md +27 -0
- package/profile/cordis.patch.yml +2 -0
- package/profile/package.json +20 -0
- package/profile/scripts/check-dsh-install.mjs +71 -0
- package/profile/version.json +5 -0
- package/scripts/check-dsh-install.mjs +88 -0
- package/version.json +6 -0
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import readline from 'node:readline';
|
|
3
|
+
import { terminateChildProcess, WINDOWS } from './process-utils.js';
|
|
4
|
+
/**
|
|
5
|
+
* 统一管理 stdio JSON-RPC 子进程:请求编号、逐行解码、取消和退出清理都在这里完成。
|
|
6
|
+
* 凭据不会被记录,也不会进入错误文本。
|
|
7
|
+
*/
|
|
8
|
+
export class JsonRpcProcess {
|
|
9
|
+
options;
|
|
10
|
+
runSpawn;
|
|
11
|
+
child = null;
|
|
12
|
+
nextId = 1;
|
|
13
|
+
pending = new Map();
|
|
14
|
+
closed = false;
|
|
15
|
+
lineLoop = null;
|
|
16
|
+
exitPromise = Promise.resolve();
|
|
17
|
+
notificationHandlers = new Set();
|
|
18
|
+
serverRequestHandler;
|
|
19
|
+
constructor(options) {
|
|
20
|
+
this.options = options;
|
|
21
|
+
this.runSpawn = options.spawn ?? spawn;
|
|
22
|
+
}
|
|
23
|
+
async request(method, params = {}, options = {}) {
|
|
24
|
+
this.ensureStarted();
|
|
25
|
+
const id = this.nextId++;
|
|
26
|
+
const promise = new Promise((resolve, reject) => this.pending.set(id, { resolve, reject }));
|
|
27
|
+
if (options.onNotification !== undefined)
|
|
28
|
+
this.notificationHandlers.add(options.onNotification);
|
|
29
|
+
const onAbort = () => {
|
|
30
|
+
this.cancel(id);
|
|
31
|
+
this.pending.get(id)?.reject(new Error('请求已取消'));
|
|
32
|
+
if (options.killOnAbort !== false) {
|
|
33
|
+
const child = this.child;
|
|
34
|
+
if (child !== null)
|
|
35
|
+
terminateChild(child, 'SIGTERM');
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
if (options.signal?.aborted)
|
|
39
|
+
onAbort();
|
|
40
|
+
else
|
|
41
|
+
options.signal?.addEventListener('abort', onAbort, { once: true });
|
|
42
|
+
try {
|
|
43
|
+
// Pi 的模型探测命令是自定义 RPC:请求体使用 `type`,不能包成 JSON-RPC
|
|
44
|
+
// method,否则 Pi 会回报 “Unknown command: undefined”。其余适配器仍走标准 JSON-RPC。
|
|
45
|
+
if (method === 'get_available_models') {
|
|
46
|
+
this.write({ id, type: method, ...(isRecord(params) ? params : {}) });
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
this.write({ jsonrpc: '2.0', id, method, params });
|
|
50
|
+
}
|
|
51
|
+
const result = await promise;
|
|
52
|
+
if (options.signal?.aborted)
|
|
53
|
+
throw new Error('请求已取消');
|
|
54
|
+
return result;
|
|
55
|
+
}
|
|
56
|
+
finally {
|
|
57
|
+
options.signal?.removeEventListener('abort', onAbort);
|
|
58
|
+
if (options.onNotification !== undefined)
|
|
59
|
+
this.notificationHandlers.delete(options.onNotification);
|
|
60
|
+
this.pending.delete(id);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/** 发送无需响应的 JSON-RPC 通知,例如 initialized 或 cancel。 */
|
|
64
|
+
notify(method, params = {}) {
|
|
65
|
+
this.ensureStarted();
|
|
66
|
+
this.write({ jsonrpc: '2.0', method, params });
|
|
67
|
+
}
|
|
68
|
+
/** 注册 Agent 发起的 JSON-RPC 服务端请求处理器,例如 Codex 权限审批。 */
|
|
69
|
+
setServerRequestHandler(handler) {
|
|
70
|
+
this.serverRequestHandler = handler;
|
|
71
|
+
}
|
|
72
|
+
/** 为一段流式请求注册独立监听器,响应先到时也不会提前移除。 */
|
|
73
|
+
addNotificationListener(listener) {
|
|
74
|
+
this.notificationHandlers.add(listener);
|
|
75
|
+
return () => this.notificationHandlers.delete(listener);
|
|
76
|
+
}
|
|
77
|
+
/** 回复由 Agent 发起的 JSON-RPC server request,保留原始 id。 */
|
|
78
|
+
respond(id, result) {
|
|
79
|
+
if (this.closed)
|
|
80
|
+
throw new Error('Agent 进程已关闭');
|
|
81
|
+
this.ensureStarted();
|
|
82
|
+
this.write({ jsonrpc: '2.0', id, result });
|
|
83
|
+
}
|
|
84
|
+
/** 回复 JSON-RPC server request 的错误结果。错误文本不回传 Provider 原文。 */
|
|
85
|
+
respondError(id, code = -32000, message = '请求被拒绝') {
|
|
86
|
+
if (this.closed)
|
|
87
|
+
throw new Error('Agent 进程已关闭');
|
|
88
|
+
this.ensureStarted();
|
|
89
|
+
this.write({ jsonrpc: '2.0', id, error: { code, message } });
|
|
90
|
+
}
|
|
91
|
+
cancel(id) {
|
|
92
|
+
if (this.closed || this.child === null)
|
|
93
|
+
return;
|
|
94
|
+
try {
|
|
95
|
+
this.write({ jsonrpc: '2.0', method: '$/cancelRequest', params: { id } });
|
|
96
|
+
}
|
|
97
|
+
catch { /* 尽力取消 */ }
|
|
98
|
+
}
|
|
99
|
+
dispose() {
|
|
100
|
+
if (this.closed)
|
|
101
|
+
return;
|
|
102
|
+
this.closed = true;
|
|
103
|
+
for (const pending of this.pending.values())
|
|
104
|
+
pending.reject(new Error('Agent 进程已退出'));
|
|
105
|
+
this.pending.clear();
|
|
106
|
+
const child = this.child;
|
|
107
|
+
this.child = null;
|
|
108
|
+
if (child === null)
|
|
109
|
+
return;
|
|
110
|
+
terminateChild(child, 'SIGTERM');
|
|
111
|
+
const forceKill = setTimeout(() => terminateChild(child, 'SIGKILL'), 500);
|
|
112
|
+
forceKill.unref?.();
|
|
113
|
+
}
|
|
114
|
+
/** 销毁并等待子进程退出,避免下一轮恢复与上一轮残留进程交叉。 */
|
|
115
|
+
async disposeAndWait(timeoutMs = 2_000) {
|
|
116
|
+
this.dispose();
|
|
117
|
+
let timer;
|
|
118
|
+
try {
|
|
119
|
+
await Promise.race([this.exitPromise, new Promise((resolve) => {
|
|
120
|
+
timer = setTimeout(resolve, timeoutMs);
|
|
121
|
+
timer.unref?.();
|
|
122
|
+
})]);
|
|
123
|
+
}
|
|
124
|
+
finally {
|
|
125
|
+
if (timer !== undefined)
|
|
126
|
+
clearTimeout(timer);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
ensureStarted() {
|
|
130
|
+
if (this.closed)
|
|
131
|
+
throw new Error('Agent 进程已关闭');
|
|
132
|
+
if (this.child !== null)
|
|
133
|
+
return;
|
|
134
|
+
const child = this.runSpawn(this.options.command, this.options.args ?? [], {
|
|
135
|
+
cwd: this.options.cwd,
|
|
136
|
+
env: { ...process.env, ...(this.options.env ?? {}) },
|
|
137
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
138
|
+
windowsHide: true,
|
|
139
|
+
shell: WINDOWS,
|
|
140
|
+
// CLI 可能是 Node 包装脚本,直接 kill 包装进程不会连带真正的 Node 子进程。
|
|
141
|
+
// POSIX 下单独进程组后才能可靠地一次清理整棵进程树。
|
|
142
|
+
detached: process.platform !== 'win32',
|
|
143
|
+
});
|
|
144
|
+
this.child = child;
|
|
145
|
+
this.exitPromise = childExitPromise(child);
|
|
146
|
+
// stderr 必须持续消费,但绝不能把命令参数、环境变量或文件片段回传给 DSH。
|
|
147
|
+
child.stderr.on('data', () => undefined);
|
|
148
|
+
this.lineLoop = this.consumeLines(child).catch((error) => this.fail(error));
|
|
149
|
+
}
|
|
150
|
+
async consumeLines(child) {
|
|
151
|
+
const lines = readline.createInterface({ input: child.stdout });
|
|
152
|
+
try {
|
|
153
|
+
for await (const line of lines) {
|
|
154
|
+
if (!line.trim())
|
|
155
|
+
continue;
|
|
156
|
+
let value;
|
|
157
|
+
try {
|
|
158
|
+
value = JSON.parse(line);
|
|
159
|
+
}
|
|
160
|
+
catch {
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
if (!isRecord(value))
|
|
164
|
+
continue;
|
|
165
|
+
if (typeof value.method === 'string' && value.id !== undefined && value.id !== null) {
|
|
166
|
+
const handler = this.serverRequestHandler;
|
|
167
|
+
if (handler === undefined) {
|
|
168
|
+
this.write({ jsonrpc: '2.0', id: value.id, error: { code: -32601, message: '请求不受支持' } });
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
// 先通知流消费者,再等待上层审批结果;通知内容只包含标准协议字段。
|
|
172
|
+
for (const listener of this.notificationHandlers)
|
|
173
|
+
listener(value);
|
|
174
|
+
const requestId = value.id;
|
|
175
|
+
void Promise.resolve(handler(value)).then((result) => this.write({ jsonrpc: '2.0', id: requestId, result }), () => this.write({ jsonrpc: '2.0', id: requestId, error: { code: -32000, message: '请求被拒绝' } }));
|
|
176
|
+
}
|
|
177
|
+
continue;
|
|
178
|
+
}
|
|
179
|
+
// Pi 的 RPC 线协议沿用 request id,但响应字段是 success/data,而不是
|
|
180
|
+
// JSON-RPC 的 result/error;两种形状都必须收敛到同一个 pending 请求。
|
|
181
|
+
if (value.id !== undefined && value.id !== null && value.type === 'response' && typeof value.success === 'boolean') {
|
|
182
|
+
const pending = this.pending.get(value.id);
|
|
183
|
+
if (pending === undefined)
|
|
184
|
+
continue;
|
|
185
|
+
if (value.success === false)
|
|
186
|
+
pending.reject(new Error('JSON-RPC 请求失败'));
|
|
187
|
+
else
|
|
188
|
+
pending.resolve(value.data);
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
if (value.id !== undefined && value.id !== null && (value.result !== undefined || value.error !== undefined)) {
|
|
192
|
+
const pending = this.pending.get(value.id);
|
|
193
|
+
if (pending === undefined)
|
|
194
|
+
continue;
|
|
195
|
+
// Provider 错误可能带命令行、路径或凭据片段,只向上层暴露稳定错误,不回传原文。
|
|
196
|
+
if (isRecord(value.error))
|
|
197
|
+
pending.reject(new Error('JSON-RPC 请求失败'));
|
|
198
|
+
else
|
|
199
|
+
pending.resolve(value.result);
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
for (const listener of this.notificationHandlers)
|
|
203
|
+
listener(value);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
finally {
|
|
207
|
+
lines.close();
|
|
208
|
+
if (!this.closed && this.child === child)
|
|
209
|
+
this.fail(new Error('Agent 进程已退出'));
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
write(message) {
|
|
213
|
+
const stdin = this.child?.stdin;
|
|
214
|
+
if (stdin === undefined)
|
|
215
|
+
throw new Error('Agent 进程不支持 stdin');
|
|
216
|
+
stdin.write(`${JSON.stringify(message)}\n`);
|
|
217
|
+
}
|
|
218
|
+
fail(error) {
|
|
219
|
+
const failure = error instanceof Error ? error : new Error('Agent 进程读取失败');
|
|
220
|
+
for (const pending of this.pending.values())
|
|
221
|
+
pending.reject(failure);
|
|
222
|
+
this.pending.clear();
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
function isRecord(value) {
|
|
226
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
227
|
+
}
|
|
228
|
+
function childExitPromise(child) {
|
|
229
|
+
return new Promise((resolve) => {
|
|
230
|
+
const eventChild = child;
|
|
231
|
+
if (typeof eventChild.once !== 'function') {
|
|
232
|
+
resolve();
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
let settled = false;
|
|
236
|
+
const settle = () => {
|
|
237
|
+
if (settled)
|
|
238
|
+
return;
|
|
239
|
+
settled = true;
|
|
240
|
+
resolve();
|
|
241
|
+
};
|
|
242
|
+
eventChild.once('close', settle);
|
|
243
|
+
eventChild.once('error', settle);
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
function terminateChild(child, signal) {
|
|
247
|
+
const pid = child.pid;
|
|
248
|
+
if (process.platform !== 'win32' && typeof pid === 'number' && pid > 0) {
|
|
249
|
+
try {
|
|
250
|
+
process.kill(-pid, signal);
|
|
251
|
+
}
|
|
252
|
+
catch { /* 进程组可能已经退出 */ }
|
|
253
|
+
}
|
|
254
|
+
terminateChildProcess(child, signal);
|
|
255
|
+
}
|
|
256
|
+
//# sourceMappingURL=json-rpc-process.js.map
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { CodingNsAgentEvent, CodingNsAgentQuestionResponse, CodingNsAgentPermissionResponse, CodingNsCliTurnInput } from '../../shared/contracts/cli-adapter.js';
|
|
2
|
+
import type { CodingNsCliSessionProbeInput, CodingNsCliSessionProbeResult } from './driver.js';
|
|
3
|
+
import { StandardStreamDriver, type StandardStreamDriverOptions } from './standard-stream-driver.js';
|
|
4
|
+
/** Kimi 的 wire 协议优先,旧版 CLI 不支持时自动回退 stream-json。 */
|
|
5
|
+
export declare class KimiCliDriver extends StandardStreamDriver {
|
|
6
|
+
private legacySyntax;
|
|
7
|
+
private readonly sessionRoots;
|
|
8
|
+
private readonly interactions;
|
|
9
|
+
constructor(options?: StandardStreamDriverOptions);
|
|
10
|
+
listModels(): Promise<import("../../shared/contracts/cli-adapter.js").CodingNsCliModelCatalog>;
|
|
11
|
+
probeSession(input: CodingNsCliSessionProbeInput): Promise<CodingNsCliSessionProbeResult>;
|
|
12
|
+
protected buildArgs(input: CodingNsCliTurnInput): readonly string[];
|
|
13
|
+
respondPermission(sessionId: string, response: CodingNsAgentPermissionResponse): void;
|
|
14
|
+
respondQuestion(sessionId: string, response: CodingNsAgentQuestionResponse): void;
|
|
15
|
+
dispose(): void;
|
|
16
|
+
executeTurn(input: CodingNsCliTurnInput): AsyncIterable<CodingNsAgentEvent>;
|
|
17
|
+
private executeWireTurn;
|
|
18
|
+
private detectSyntax;
|
|
19
|
+
}
|
|
20
|
+
export { KimiCliDriver as KimiDriver };
|
|
21
|
+
//# sourceMappingURL=kimi-driver.d.ts.map
|
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
import readline from 'node:readline';
|
|
2
|
+
import { homedir } from 'node:os';
|
|
3
|
+
import { basename, join } from 'node:path';
|
|
4
|
+
import { StandardStreamDriver, emptyCatalog } from './standard-stream-driver.js';
|
|
5
|
+
import { KIMI_CATALOG, enrichEfforts, isProviderDefaultModel } from './model-catalog.js';
|
|
6
|
+
import { probeStoredSession, readFirstJsonRecord, resolveSessionDirectory } from './session-probe.js';
|
|
7
|
+
import { firstToolText, isToolRecord, normalizeToolStatus, serializeToolValue } from './tool-observation.js';
|
|
8
|
+
import { isQuestionEvent, readAgentQuestions } from './interaction-events.js';
|
|
9
|
+
import { usageChunk } from './rpc-driver-utils.js';
|
|
10
|
+
import { terminateChildProcess } from './process-utils.js';
|
|
11
|
+
/** Kimi 的 wire 协议优先,旧版 CLI 不支持时自动回退 stream-json。 */
|
|
12
|
+
export class KimiCliDriver extends StandardStreamDriver {
|
|
13
|
+
legacySyntax = false;
|
|
14
|
+
sessionRoots;
|
|
15
|
+
interactions = new Map();
|
|
16
|
+
constructor(options = {}) {
|
|
17
|
+
super({ id: 'kimi', name: 'Kimi CLI', protocol: 'stream-json', capabilities: ['models', 'stream', 'resume', 'interrupt', 'tool-events', 'reasoning', 'usage', 'permission', 'questions', 'steer'] }, { binaries: ['kimi', 'kimi-cli'] }, options);
|
|
18
|
+
this.sessionRoots = options.sessionRoots ?? [join(process.env.KIMI_HOME ?? join(homedir(), '.kimi'), 'sessions')];
|
|
19
|
+
}
|
|
20
|
+
async listModels() {
|
|
21
|
+
if (!(await this.detect()).installed)
|
|
22
|
+
return emptyCatalog();
|
|
23
|
+
const catalog = await super.listModels();
|
|
24
|
+
return catalog.groups.length > 0 ? enrichEfforts(catalog, KIMI_CATALOG) : KIMI_CATALOG;
|
|
25
|
+
}
|
|
26
|
+
async probeSession(input) {
|
|
27
|
+
return probeStoredSession(input, {
|
|
28
|
+
roots: this.sessionRoots,
|
|
29
|
+
matches: (path, entry, id) => entry.isDirectory() && basename(path) === id,
|
|
30
|
+
validate: async (path) => {
|
|
31
|
+
const directory = await resolveSessionDirectory(path);
|
|
32
|
+
return await readFirstJsonRecord(join(directory, 'context.jsonl')) !== null;
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
buildArgs(input) {
|
|
37
|
+
const args = ['--print', '--output-format', 'stream-json', '--input-format', 'stream-json'];
|
|
38
|
+
if (input.providerSessionId)
|
|
39
|
+
args.push(this.legacySyntax ? '--resume' : '--session', input.providerSessionId);
|
|
40
|
+
if (this.legacySyntax) {
|
|
41
|
+
if (input.cwd)
|
|
42
|
+
args.push('--cwd', input.cwd);
|
|
43
|
+
}
|
|
44
|
+
else if (input.cwd)
|
|
45
|
+
args.push('--work-dir', input.cwd);
|
|
46
|
+
if (input.modelId && !isProviderDefaultModel(input.modelId))
|
|
47
|
+
args.push('--model', input.modelId);
|
|
48
|
+
return args;
|
|
49
|
+
}
|
|
50
|
+
respondPermission(sessionId, response) {
|
|
51
|
+
const state = this.interactions.get(sessionId);
|
|
52
|
+
const pending = state?.pending.get(response.requestId);
|
|
53
|
+
if (state === undefined || pending?.kind !== 'permission')
|
|
54
|
+
throw new Error('Kimi 权限请求已结束');
|
|
55
|
+
state.pending.delete(response.requestId);
|
|
56
|
+
state.write(`${JSON.stringify({
|
|
57
|
+
jsonrpc: '2.0',
|
|
58
|
+
id: pending.rpcId,
|
|
59
|
+
result: {
|
|
60
|
+
request_id: response.requestId,
|
|
61
|
+
response: response.approved ? 'approve' : 'reject',
|
|
62
|
+
...(response.reason ? { feedback: response.reason } : {}),
|
|
63
|
+
},
|
|
64
|
+
})}\n`);
|
|
65
|
+
}
|
|
66
|
+
respondQuestion(sessionId, response) {
|
|
67
|
+
const state = this.interactions.get(sessionId);
|
|
68
|
+
const pending = state?.pending.get(response.requestId);
|
|
69
|
+
if (state === undefined || pending?.kind !== 'question')
|
|
70
|
+
throw new Error('Kimi 问题请求已结束');
|
|
71
|
+
state.pending.delete(response.requestId);
|
|
72
|
+
const answers = Object.fromEntries(response.answers.map((answer) => [
|
|
73
|
+
pending.questions?.get(answer.id) ?? answer.id,
|
|
74
|
+
[...answer.selected, ...(answer.custom?.trim() ? [answer.custom.trim()] : [])].join(', '),
|
|
75
|
+
]));
|
|
76
|
+
state.write(`${JSON.stringify({
|
|
77
|
+
jsonrpc: '2.0',
|
|
78
|
+
id: pending.rpcId,
|
|
79
|
+
result: { request_id: response.requestId, answers },
|
|
80
|
+
})}\n`);
|
|
81
|
+
}
|
|
82
|
+
dispose() {
|
|
83
|
+
this.interactions.clear();
|
|
84
|
+
super.dispose();
|
|
85
|
+
}
|
|
86
|
+
async *executeTurn(input) {
|
|
87
|
+
try {
|
|
88
|
+
yield* this.executeWireTurn(input);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
if (input.signal?.aborted) {
|
|
93
|
+
yield { type: 'finish', reason: 'cancel' };
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
for await (const chunk of super.executeTurn(input))
|
|
97
|
+
yield chunk;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
async *executeWireTurn(input) {
|
|
101
|
+
const detection = await this.detect();
|
|
102
|
+
const command = detection.command;
|
|
103
|
+
if (command === null)
|
|
104
|
+
throw new Error('Kimi CLI 未安装');
|
|
105
|
+
this.detectSyntax(command);
|
|
106
|
+
const args = this.legacySyntax ? ['wire', '--output-format', 'stream-json'] : ['--wire'];
|
|
107
|
+
if (input.providerSessionId)
|
|
108
|
+
args.push(this.legacySyntax ? '--resume' : '--session', input.providerSessionId);
|
|
109
|
+
else if (this.legacySyntax)
|
|
110
|
+
args.push('--new-session');
|
|
111
|
+
if (input.cwd)
|
|
112
|
+
args.push(this.legacySyntax ? '--cwd' : '--work-dir', input.cwd);
|
|
113
|
+
if (input.modelId && !isProviderDefaultModel(input.modelId))
|
|
114
|
+
args.push('--model', input.modelId);
|
|
115
|
+
const child = this.runSpawn(command, args, {
|
|
116
|
+
cwd: input.cwd ?? process.cwd(), env: { ...process.env }, stdio: ['pipe', 'pipe', 'pipe'], windowsHide: true, shell: process.platform === 'win32',
|
|
117
|
+
});
|
|
118
|
+
const stdin = child.stdin;
|
|
119
|
+
const interaction = {
|
|
120
|
+
write: (data) => stdin.write(data),
|
|
121
|
+
pending: new Map(),
|
|
122
|
+
};
|
|
123
|
+
this.interactions.set(input.sessionId, interaction);
|
|
124
|
+
let finished = false;
|
|
125
|
+
let sawProtocol = false;
|
|
126
|
+
const onAbort = () => { terminateChildProcess(child); };
|
|
127
|
+
input.signal?.addEventListener('abort', onAbort, { once: true });
|
|
128
|
+
if (input.signal?.aborted)
|
|
129
|
+
onAbort();
|
|
130
|
+
child.stderr.on('data', () => undefined);
|
|
131
|
+
try {
|
|
132
|
+
const initializeId = `initialize:${input.sessionId}`;
|
|
133
|
+
const promptId = `prompt:${input.sessionId}`;
|
|
134
|
+
stdin.write(`${JSON.stringify({
|
|
135
|
+
jsonrpc: '2.0',
|
|
136
|
+
id: initializeId,
|
|
137
|
+
method: 'initialize',
|
|
138
|
+
params: {
|
|
139
|
+
protocol_version: '1.10',
|
|
140
|
+
client: { name: 'codingns4dsh', version: '0.1.0' },
|
|
141
|
+
capabilities: { supports_question: true },
|
|
142
|
+
},
|
|
143
|
+
})}\n`);
|
|
144
|
+
let promptSent = false;
|
|
145
|
+
const sendPrompt = () => {
|
|
146
|
+
if (promptSent)
|
|
147
|
+
return;
|
|
148
|
+
promptSent = true;
|
|
149
|
+
stdin.write(`${JSON.stringify({
|
|
150
|
+
jsonrpc: '2.0',
|
|
151
|
+
id: promptId,
|
|
152
|
+
method: 'prompt',
|
|
153
|
+
params: { user_input: input.prompt },
|
|
154
|
+
})}\n`);
|
|
155
|
+
};
|
|
156
|
+
const lines = readline.createInterface({ input: child.stdout });
|
|
157
|
+
try {
|
|
158
|
+
for await (const line of lines) {
|
|
159
|
+
if (!line.trim())
|
|
160
|
+
continue;
|
|
161
|
+
let value;
|
|
162
|
+
try {
|
|
163
|
+
value = JSON.parse(line);
|
|
164
|
+
}
|
|
165
|
+
catch {
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
if (!isRecord(value))
|
|
169
|
+
continue;
|
|
170
|
+
if (value.id === initializeId && (value.result !== undefined || value.error !== undefined)) {
|
|
171
|
+
// initialize 是可选握手;旧版返回 method not found 时仍可直接 prompt。
|
|
172
|
+
sendPrompt();
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
if (!promptSent)
|
|
176
|
+
sendPrompt();
|
|
177
|
+
const request = kimiInteractionRequest(value);
|
|
178
|
+
if (request !== null) {
|
|
179
|
+
interaction.pending.set(request.event.requestId, request.pending);
|
|
180
|
+
sawProtocol = true;
|
|
181
|
+
yield request.event;
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
if (value.id === promptId && value.result !== undefined) {
|
|
185
|
+
const result = isRecord(value.result) ? value.result : null;
|
|
186
|
+
yield { type: 'finish', reason: input.signal?.aborted || result?.status === 'cancelled' ? 'cancel' : 'stop' };
|
|
187
|
+
finished = true;
|
|
188
|
+
break;
|
|
189
|
+
}
|
|
190
|
+
if (value.id === promptId && value.error !== undefined)
|
|
191
|
+
throw new Error('Kimi wire 请求失败');
|
|
192
|
+
const result = mapKimiWireEvent(value, input.signal?.aborted ?? false);
|
|
193
|
+
if (result.protocol)
|
|
194
|
+
sawProtocol = true;
|
|
195
|
+
if (result.error)
|
|
196
|
+
throw new Error('Kimi wire 请求失败');
|
|
197
|
+
for (const chunk of result.chunks) {
|
|
198
|
+
if (chunk.type === 'finish')
|
|
199
|
+
finished = true;
|
|
200
|
+
yield chunk;
|
|
201
|
+
}
|
|
202
|
+
if (finished)
|
|
203
|
+
break;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
finally {
|
|
207
|
+
lines.close();
|
|
208
|
+
}
|
|
209
|
+
if (input.signal?.aborted) {
|
|
210
|
+
if (!finished)
|
|
211
|
+
yield { type: 'finish', reason: 'cancel' };
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
if (!finished)
|
|
215
|
+
throw new Error(sawProtocol ? 'Kimi wire 未返回完成事件' : 'Kimi wire 不可用');
|
|
216
|
+
}
|
|
217
|
+
finally {
|
|
218
|
+
if (this.interactions.get(input.sessionId) === interaction)
|
|
219
|
+
this.interactions.delete(input.sessionId);
|
|
220
|
+
input.signal?.removeEventListener('abort', onAbort);
|
|
221
|
+
terminateChildProcess(child);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
detectSyntax(command) {
|
|
225
|
+
try {
|
|
226
|
+
const result = this.runSpawnSync(command, ['--help'], { encoding: 'utf8', timeout: 5_000, windowsHide: true, shell: process.platform === 'win32' });
|
|
227
|
+
const output = `${result.stdout ?? ''}\n${result.stderr ?? ''}`.toLowerCase();
|
|
228
|
+
this.legacySyntax = /(?:^|\s)wire(?:\s|$)/u.test(output) && !output.includes('--wire');
|
|
229
|
+
}
|
|
230
|
+
catch {
|
|
231
|
+
this.legacySyntax = false;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
function mapKimiWireEvent(value, cancelled) {
|
|
236
|
+
const params = isRecord(value.params) ? value.params : null;
|
|
237
|
+
const event = isRecord(params?.payload)
|
|
238
|
+
? params.payload
|
|
239
|
+
: isRecord(value.event)
|
|
240
|
+
? value.event
|
|
241
|
+
: isRecord(value.payload)
|
|
242
|
+
? value.payload
|
|
243
|
+
: value;
|
|
244
|
+
const envelopeType = params?.type ?? value.type ?? event.type ?? value.event ?? '';
|
|
245
|
+
const type = `${envelopeType}`.toLowerCase();
|
|
246
|
+
const isToolEvent = type.includes('tool') || type.includes('command') || type.includes('function');
|
|
247
|
+
const chunks = [];
|
|
248
|
+
const sessionId = firstString(value, event, ['session_id', 'sessionId', 'id']);
|
|
249
|
+
if (sessionId && (type.includes('session') || type.includes('ready')))
|
|
250
|
+
chunks.push({ type: 'session-binding', providerSessionId: sessionId });
|
|
251
|
+
if (isQuestionEvent(type)) {
|
|
252
|
+
const requestId = firstString(event, value, ['request_id', 'requestId', 'question_id', 'id']);
|
|
253
|
+
const questions = readAgentQuestions(event.questions ?? value.questions ?? event);
|
|
254
|
+
if (requestId && questions.length > 0)
|
|
255
|
+
chunks.push({ type: 'question-request', requestId, questions });
|
|
256
|
+
}
|
|
257
|
+
const permissionId = firstString(event, value, ['request_id', 'requestId', 'permission_id']);
|
|
258
|
+
if (permissionId && type.includes('permission'))
|
|
259
|
+
chunks.push({ type: 'permission-request', requestId: permissionId, kind: firstString(event, value, ['kind', 'type']) ?? 'unknown' });
|
|
260
|
+
const contentType = typeof event.type === 'string' ? event.type.toLowerCase() : '';
|
|
261
|
+
const text = isQuestionEvent(type) || type.includes('permission')
|
|
262
|
+
? ''
|
|
263
|
+
: type === 'contentpart' && contentType === 'think'
|
|
264
|
+
? firstString(event, event, ['think'])
|
|
265
|
+
: textFrom(event);
|
|
266
|
+
if (text) {
|
|
267
|
+
if (type.includes('think') || type.includes('reason') || contentType === 'think')
|
|
268
|
+
chunks.push({ type: 'reasoning-delta', text });
|
|
269
|
+
else if (!type.includes('result') && !type.includes('complete') && !type.includes('done'))
|
|
270
|
+
chunks.push({ type: 'text-delta', text });
|
|
271
|
+
}
|
|
272
|
+
const nestedTool = isToolRecord(event.tool_call)
|
|
273
|
+
? event.tool_call
|
|
274
|
+
: isToolRecord(event.tool_result)
|
|
275
|
+
? event.tool_result
|
|
276
|
+
: isToolRecord(event.function)
|
|
277
|
+
? event.function
|
|
278
|
+
: event;
|
|
279
|
+
const toolName = firstToolText(nestedTool.tool_name, nestedTool.toolName, nestedTool.name, event.tool_name, event.toolName, event.name);
|
|
280
|
+
if ((toolName || firstToolText(nestedTool.call_id, nestedTool.callId, event.tool_call_id, event.tool_use_id)) && isToolEvent) {
|
|
281
|
+
const callId = firstToolText(nestedTool.call_id, nestedTool.callId, nestedTool.id, event.tool_call_id, event.tool_use_id, event.toolUseId, event.id);
|
|
282
|
+
const input = serializeToolValue(nestedTool.input ?? nestedTool.arguments ?? nestedTool.args ?? nestedTool.parameters ?? event.input ?? event.arguments);
|
|
283
|
+
const returnValue = isRecord(event.return_value) ? event.return_value : null;
|
|
284
|
+
const output = serializeToolValue(nestedTool.output ?? nestedTool.result ?? event.output ?? event.result ?? returnValue?.output ?? returnValue?.message);
|
|
285
|
+
const error = serializeToolValue(nestedTool.error ?? event.error ?? (returnValue?.is_error === true ? returnValue.message : undefined));
|
|
286
|
+
const fallback = error !== undefined || type.includes('error') || type.includes('fail')
|
|
287
|
+
? 'failed'
|
|
288
|
+
: output !== undefined || type.includes('result') || type.includes('complete') || type.includes('return')
|
|
289
|
+
? 'completed'
|
|
290
|
+
: 'running';
|
|
291
|
+
chunks.push({
|
|
292
|
+
type: 'tool-event',
|
|
293
|
+
toolName: toolName ?? 'tool',
|
|
294
|
+
status: normalizeToolStatus(nestedTool.status ?? event.status, fallback),
|
|
295
|
+
...(callId ? { callId } : {}),
|
|
296
|
+
...(input !== undefined ? { input } : {}),
|
|
297
|
+
...(output !== undefined ? { output } : {}),
|
|
298
|
+
...(output !== undefined ? { outputMode: type.includes('delta') ? 'delta' : 'snapshot' } : {}),
|
|
299
|
+
...(error !== undefined ? { error } : {}),
|
|
300
|
+
...(firstToolText(nestedTool.agent_id, nestedTool.agentId, event.agent_id, event.agentId) ? { agentId: firstToolText(nestedTool.agent_id, nestedTool.agentId, event.agent_id, event.agentId) } : {}),
|
|
301
|
+
...(serializeToolValue(nestedTool.detail ?? event.detail) !== undefined ? { detail: serializeToolValue(nestedTool.detail ?? event.detail) } : {}),
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
const usage = isRecord(event.usage) ? event.usage : isRecord(value.usage) ? value.usage : null;
|
|
305
|
+
const usageEvent = usageChunk(usage);
|
|
306
|
+
if (usageEvent)
|
|
307
|
+
chunks.push(usageEvent);
|
|
308
|
+
if ((type.includes('error') || type.includes('failed')) && !isToolEvent)
|
|
309
|
+
return { protocol: true, error: true, chunks };
|
|
310
|
+
if (type.includes('turnend') || type.includes('turn_end') || type.includes('completed') || type.includes('complete') || type === 'done' || type === 'result' || type.includes('session.completed'))
|
|
311
|
+
chunks.push({ type: 'finish', reason: cancelled ? 'cancel' : 'stop' });
|
|
312
|
+
return { protocol: true, error: false, chunks };
|
|
313
|
+
}
|
|
314
|
+
function kimiInteractionRequest(value) {
|
|
315
|
+
if (value.method !== 'request' || (typeof value.id !== 'string' && typeof value.id !== 'number'))
|
|
316
|
+
return null;
|
|
317
|
+
const params = isRecord(value.params) ? value.params : null;
|
|
318
|
+
const payload = isRecord(params?.payload) ? params.payload : null;
|
|
319
|
+
const type = typeof params?.type === 'string' ? params.type.toLowerCase() : '';
|
|
320
|
+
const requestId = firstString(payload ?? {}, payload ?? {}, ['id']);
|
|
321
|
+
if (payload === null || requestId === null)
|
|
322
|
+
return null;
|
|
323
|
+
if (type === 'approvalrequest') {
|
|
324
|
+
const toolName = firstString(payload, payload, ['sender']) ?? 'external-agent';
|
|
325
|
+
const detail = firstString(payload, payload, ['description', 'action']);
|
|
326
|
+
const callId = firstString(payload, payload, ['tool_call_id']);
|
|
327
|
+
return {
|
|
328
|
+
event: {
|
|
329
|
+
type: 'permission-request',
|
|
330
|
+
requestId,
|
|
331
|
+
kind: firstString(payload, payload, ['action']) ?? toolName,
|
|
332
|
+
toolName,
|
|
333
|
+
...(callId ? { callId } : {}),
|
|
334
|
+
...(detail ? { detail } : {}),
|
|
335
|
+
},
|
|
336
|
+
pending: { rpcId: value.id, kind: 'permission' },
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
if (type === 'questionrequest') {
|
|
340
|
+
const questions = readAgentQuestions(payload.questions);
|
|
341
|
+
if (questions.length === 0)
|
|
342
|
+
return null;
|
|
343
|
+
return {
|
|
344
|
+
event: { type: 'question-request', requestId, questions },
|
|
345
|
+
pending: {
|
|
346
|
+
rpcId: value.id,
|
|
347
|
+
kind: 'question',
|
|
348
|
+
questions: new Map(questions.map((question) => [question.id, question.question])),
|
|
349
|
+
},
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
return null;
|
|
353
|
+
}
|
|
354
|
+
function textFrom(value) {
|
|
355
|
+
for (const key of ['text', 'delta', 'content', 'message']) {
|
|
356
|
+
const item = value[key];
|
|
357
|
+
if (typeof item === 'string' && item.trim())
|
|
358
|
+
return item;
|
|
359
|
+
if (Array.isArray(item)) {
|
|
360
|
+
const parts = item.flatMap((part) => typeof part === 'string' ? [part] : isRecord(part) ? [textFrom(part) ?? ''] : []);
|
|
361
|
+
const joined = parts.join('');
|
|
362
|
+
if (joined.trim())
|
|
363
|
+
return joined;
|
|
364
|
+
}
|
|
365
|
+
if (isRecord(item)) {
|
|
366
|
+
const nested = textFrom(item);
|
|
367
|
+
if (nested)
|
|
368
|
+
return nested;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
return null;
|
|
372
|
+
}
|
|
373
|
+
function firstString(a, b, keys) {
|
|
374
|
+
for (const key of keys)
|
|
375
|
+
for (const source of [a, b])
|
|
376
|
+
if (typeof source[key] === 'string' && source[key].trim())
|
|
377
|
+
return source[key];
|
|
378
|
+
return null;
|
|
379
|
+
}
|
|
380
|
+
function isRecord(value) { return typeof value === 'object' && value !== null && !Array.isArray(value); }
|
|
381
|
+
export { KimiCliDriver as KimiDriver };
|
|
382
|
+
//# sourceMappingURL=kimi-driver.js.map
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { CodingNsCliModelCatalog } from '../../shared/contracts/cli-adapter.js';
|
|
2
|
+
/**
|
|
3
|
+
* 外部 CLI 没有稳定的模型目录接口时,使用随适配器验证过的最小目录。
|
|
4
|
+
* 目录只保存模型 id 和 CLI 接受的思考档位,不包含凭据或远端响应。
|
|
5
|
+
*/
|
|
6
|
+
export declare function staticCatalog(groupId: string, groupName: string, models: readonly {
|
|
7
|
+
id: string;
|
|
8
|
+
name?: string;
|
|
9
|
+
efforts: readonly string[];
|
|
10
|
+
}[]): CodingNsCliModelCatalog;
|
|
11
|
+
/** Gemini ACP 只返回模型标识;思考档位需按 Gemini 官方能力表补齐。 */
|
|
12
|
+
export declare function resolveGeminiEfforts(modelId: string): readonly string[];
|
|
13
|
+
export declare const CLAUDE_CATALOG: CodingNsCliModelCatalog;
|
|
14
|
+
export declare const KIMI_CATALOG: CodingNsCliModelCatalog;
|
|
15
|
+
export declare const GEMINI_CATALOG: CodingNsCliModelCatalog;
|
|
16
|
+
export declare const CODEX_CATALOG: CodingNsCliModelCatalog;
|
|
17
|
+
export declare const GROK_CATALOG: CodingNsCliModelCatalog;
|
|
18
|
+
export declare const PI_CATALOG: CodingNsCliModelCatalog;
|
|
19
|
+
/** 把 CLI 帮助解析到的模型补上已知档位,未知模型保持空数组。 */
|
|
20
|
+
export declare function enrichEfforts(catalog: CodingNsCliModelCatalog, known: CodingNsCliModelCatalog): CodingNsCliModelCatalog;
|
|
21
|
+
export declare function isProviderDefaultModel(modelId: string | undefined): boolean;
|
|
22
|
+
//# sourceMappingURL=model-catalog.d.ts.map
|