@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,55 @@
|
|
|
1
|
+
/** 将 Host 已登记的 RPC 命名空间接到 DSH Gateway。 */
|
|
2
|
+
export function createDshRpcGatewayFeature(rpc) {
|
|
3
|
+
return {
|
|
4
|
+
channel: 'rpc',
|
|
5
|
+
operation: 'rpc.request',
|
|
6
|
+
handleStream: async (context) => {
|
|
7
|
+
try {
|
|
8
|
+
const request = readJson(context);
|
|
9
|
+
if (!isRecord(request) || typeof request.method !== 'string' || request.method.trim() === '') {
|
|
10
|
+
throw new DshGatewayRequestError('MESSAGE_INVALID', 'DSH RPC 请求缺少 method');
|
|
11
|
+
}
|
|
12
|
+
const target = rpc.resolve(request.method);
|
|
13
|
+
if (target === null)
|
|
14
|
+
throw new DshGatewayRequestError('FEATURE_DISABLED', 'DSH RPC 未启用');
|
|
15
|
+
const value = await target.handler(target.action, request.payload);
|
|
16
|
+
context.send('rpc.response', { encoding: 'json' }, encodeJson(value));
|
|
17
|
+
}
|
|
18
|
+
catch (error) {
|
|
19
|
+
// 业务异常可能包含命令行、路径或凭据片段,跨隧道只返回稳定的短描述。
|
|
20
|
+
const detail = error instanceof DshGatewayRequestError ? error.message : 'DSH RPC 执行失败';
|
|
21
|
+
const errorCode = error instanceof DshGatewayRequestError ? error.code : 'DSH_RPC_FAILED';
|
|
22
|
+
context.send('stream.error', { errorCode, detail, retryable: false });
|
|
23
|
+
}
|
|
24
|
+
finally {
|
|
25
|
+
context.close();
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function readJson(context) {
|
|
31
|
+
const body = context.envelope.body;
|
|
32
|
+
if (body === undefined || context.envelope.meta.encoding !== 'json')
|
|
33
|
+
return undefined;
|
|
34
|
+
try {
|
|
35
|
+
return JSON.parse(new TextDecoder().decode(body));
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
throw new DshGatewayRequestError('MESSAGE_INVALID', 'DSH RPC 请求正文不是有效 JSON');
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function encodeJson(value) {
|
|
42
|
+
return new TextEncoder().encode(JSON.stringify(value === undefined ? null : value));
|
|
43
|
+
}
|
|
44
|
+
function isRecord(value) {
|
|
45
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
46
|
+
}
|
|
47
|
+
class DshGatewayRequestError extends Error {
|
|
48
|
+
code;
|
|
49
|
+
constructor(code, message) {
|
|
50
|
+
super(message);
|
|
51
|
+
this.code = code;
|
|
52
|
+
this.name = code;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=dsh-gateway-feature.js.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 读取当前 DSH 进程真正加载的 @deepseek-ai/dsh 版本。
|
|
3
|
+
*
|
|
4
|
+
* DSH 0.1.6 尚未把启动器版本作为 Cordis 服务暴露给插件,因此不能从
|
|
5
|
+
* 插件自身的 DSH_VERSION 常量推断宿主版本。优先沿当前 dsh 可执行入口
|
|
6
|
+
* 向上查找 @deepseek-ai/dsh/package.json,只有开发环境无法提供入口时才
|
|
7
|
+
* 回退到 PATH 中的 `dsh --version`。
|
|
8
|
+
*/
|
|
9
|
+
export declare function detectRuntimeDshVersion(): string;
|
|
10
|
+
/** Host 启动后供 Web Client 复用的版本注入名称。 */
|
|
11
|
+
export declare const DSH_VERSION_INJECTION_NAME: "__CODINGNS_DSH_VERSION__";
|
|
12
|
+
//# sourceMappingURL=dsh-runtime-version.d.ts.map
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { dirname, join } from 'node:path';
|
|
3
|
+
import { spawnSync } from 'node:child_process';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
import { assertSupportedDshVersion, CODINGNS_DSH_VERSION_GLOBAL, CODINGNS_DSH_ERROR_CODES, CodingNsDshError, } from '../shared/index.js';
|
|
6
|
+
const VERSION_PATTERN = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/u;
|
|
7
|
+
/**
|
|
8
|
+
* 读取当前 DSH 进程真正加载的 @deepseek-ai/dsh 版本。
|
|
9
|
+
*
|
|
10
|
+
* DSH 0.1.6 尚未把启动器版本作为 Cordis 服务暴露给插件,因此不能从
|
|
11
|
+
* 插件自身的 DSH_VERSION 常量推断宿主版本。优先沿当前 dsh 可执行入口
|
|
12
|
+
* 向上查找 @deepseek-ai/dsh/package.json,只有开发环境无法提供入口时才
|
|
13
|
+
* 回退到 PATH 中的 `dsh --version`。
|
|
14
|
+
*/
|
|
15
|
+
export function detectRuntimeDshVersion() {
|
|
16
|
+
const candidates = [
|
|
17
|
+
process.env.DSH_RUNTIME_VERSION,
|
|
18
|
+
process.env.DSH_VERSION,
|
|
19
|
+
readDshPackageVersion(process.argv[1]),
|
|
20
|
+
readDshPackageVersion(fileURLToPath(import.meta.url)),
|
|
21
|
+
readDshVersionFromCommand(),
|
|
22
|
+
];
|
|
23
|
+
const version = candidates.find((candidate) => candidate !== undefined && VERSION_PATTERN.test(candidate));
|
|
24
|
+
if (version === undefined) {
|
|
25
|
+
throw new CodingNsDshError(CODINGNS_DSH_ERROR_CODES.DSH_VERSION_UNSUPPORTED, '无法读取当前 DSH 版本;为避免 API 不兼容,已拒绝启用 codingns4dsh');
|
|
26
|
+
}
|
|
27
|
+
assertSupportedDshVersion(version);
|
|
28
|
+
return version;
|
|
29
|
+
}
|
|
30
|
+
/** Host 启动后供 Web Client 复用的版本注入名称。 */
|
|
31
|
+
export const DSH_VERSION_INJECTION_NAME = CODINGNS_DSH_VERSION_GLOBAL;
|
|
32
|
+
function readDshPackageVersion(entryPath) {
|
|
33
|
+
if (entryPath === undefined || entryPath.trim() === '')
|
|
34
|
+
return undefined;
|
|
35
|
+
let current = dirname(entryPath);
|
|
36
|
+
for (let depth = 0; depth < 10; depth += 1) {
|
|
37
|
+
const manifestPath = join(current, 'package.json');
|
|
38
|
+
try {
|
|
39
|
+
const manifest = JSON.parse(readFileSync(manifestPath, 'utf8'));
|
|
40
|
+
if (manifest.name === '@deepseek-ai/dsh' && typeof manifest.version === 'string')
|
|
41
|
+
return manifest.version;
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
// 当前目录不是 DSH 包时继续向上查找;读取失败不应掩盖后续探测路径。
|
|
45
|
+
}
|
|
46
|
+
const parent = dirname(current);
|
|
47
|
+
if (parent === current)
|
|
48
|
+
break;
|
|
49
|
+
current = parent;
|
|
50
|
+
}
|
|
51
|
+
return undefined;
|
|
52
|
+
}
|
|
53
|
+
function readDshVersionFromCommand() {
|
|
54
|
+
try {
|
|
55
|
+
const result = spawnSync(process.platform === 'win32' ? 'dsh.cmd' : 'dsh', ['--version'], {
|
|
56
|
+
encoding: 'utf8',
|
|
57
|
+
timeout: 2_000,
|
|
58
|
+
windowsHide: true,
|
|
59
|
+
});
|
|
60
|
+
if (result.status !== 0)
|
|
61
|
+
return undefined;
|
|
62
|
+
const output = `${result.stdout ?? ''}\n${result.stderr ?? ''}`.trim();
|
|
63
|
+
return output.match(VERSION_PATTERN)?.[0];
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return undefined;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=dsh-runtime-version.js.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { FeatureModule } from '../../shared/contracts/feature.js';
|
|
2
|
+
import type { CodingNsHostServices } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* 认证模块:登录、凭据、设备查询和 Host 绑定。
|
|
5
|
+
*
|
|
6
|
+
* 它是唯一持有 CodingNsAuthSession 和凭据存储的地方,并以 `auth/*` 命名空间
|
|
7
|
+
* 暴露 RPC。refresh token 只存在于这里,所有响应都不包含它。模块没有界面:
|
|
8
|
+
* 这些设置由「中转访问服务」卡片承载。
|
|
9
|
+
*/
|
|
10
|
+
export declare function createAuthFeature(): FeatureModule<CodingNsHostServices>;
|
|
11
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
import { homedir } from 'node:os';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { CodingNsAuthSession } from '../auth-session.js';
|
|
4
|
+
import { HttpCodingNsControlApiClient } from '../control-api-client.js';
|
|
5
|
+
import { FileCodingNsCredentialStore, FileDshDeviceCredentialStore } from '../credential-store.js';
|
|
6
|
+
import { startDshHostDeviceRuntime } from '../dsh-device-runtime.js';
|
|
7
|
+
import { CodingNsRpcError } from '../rpc-table.js';
|
|
8
|
+
import { createDshRpcGatewayFeature } from '../dsh-gateway-feature.js';
|
|
9
|
+
import { createLocalDshWebRuntimeProvider, createRemoteWebRuntimeFeature } from '../remote-web-runtime.js';
|
|
10
|
+
import { DSH_VERSION } from '../../shared/contracts/version.js';
|
|
11
|
+
import { FileLanAccessDshLoginStore, verifyLoginProtectionSession } from '../lan-access-dsh.js';
|
|
12
|
+
/** 未登录时的稳定快照;Client 首次读取 `auth/snapshot` 会拿到它。 */
|
|
13
|
+
const LOGGED_OUT_SNAPSHOT = {
|
|
14
|
+
status: 'logged_out',
|
|
15
|
+
account: null,
|
|
16
|
+
currentDevice: null,
|
|
17
|
+
binding: null,
|
|
18
|
+
expiresAt: null,
|
|
19
|
+
errorCode: null,
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* 认证模块:登录、凭据、设备查询和 Host 绑定。
|
|
23
|
+
*
|
|
24
|
+
* 它是唯一持有 CodingNsAuthSession 和凭据存储的地方,并以 `auth/*` 命名空间
|
|
25
|
+
* 暴露 RPC。refresh token 只存在于这里,所有响应都不包含它。模块没有界面:
|
|
26
|
+
* 这些设置由「中转访问服务」卡片承载。
|
|
27
|
+
*/
|
|
28
|
+
export function createAuthFeature() {
|
|
29
|
+
return {
|
|
30
|
+
descriptor: {
|
|
31
|
+
name: 'auth',
|
|
32
|
+
version: '0.1.0',
|
|
33
|
+
enabledByDefault: true,
|
|
34
|
+
dependencies: [],
|
|
35
|
+
runtime: 'host',
|
|
36
|
+
},
|
|
37
|
+
start(context) {
|
|
38
|
+
const stateDirectory = process.env.CODINGNS4DSH_STATE_DIR?.trim() || join(homedir(), '.config', 'codingns4dsh');
|
|
39
|
+
const credentials = new FileCodingNsCredentialStore(join(stateDirectory, 'codingns-credentials.json'));
|
|
40
|
+
const dshCredentials = new FileDshDeviceCredentialStore(join(stateDirectory, 'device-credential.json'));
|
|
41
|
+
const loginProtectionStore = new FileLanAccessDshLoginStore(join(stateDirectory, 'lan-access-login.json'));
|
|
42
|
+
let session = null;
|
|
43
|
+
let sessionBaseUrl = null;
|
|
44
|
+
let dshRuntime = null;
|
|
45
|
+
let dshStartPromise = null;
|
|
46
|
+
let keepAliveTimer;
|
|
47
|
+
let keepAlivePromise = null;
|
|
48
|
+
let disposed = false;
|
|
49
|
+
const ensureSession = async (controlBaseUrl) => {
|
|
50
|
+
if (session && sessionBaseUrl === controlBaseUrl)
|
|
51
|
+
return session;
|
|
52
|
+
if (session)
|
|
53
|
+
await session.logout();
|
|
54
|
+
session = new CodingNsAuthSession(new HttpCodingNsControlApiClient({ controlBaseUrl }), credentials, controlBaseUrl);
|
|
55
|
+
sessionBaseUrl = controlBaseUrl;
|
|
56
|
+
return session;
|
|
57
|
+
};
|
|
58
|
+
const requireSession = () => {
|
|
59
|
+
if (!session)
|
|
60
|
+
throw new CodingNsRpcError('CODINGNS_RPC_UNAUTHENTICATED', 'Codingns4DSH 尚未登录');
|
|
61
|
+
return session;
|
|
62
|
+
};
|
|
63
|
+
const startDsh = async (target) => {
|
|
64
|
+
if (disposed || context.resources.disposed)
|
|
65
|
+
return;
|
|
66
|
+
if (dshRuntime !== null)
|
|
67
|
+
return;
|
|
68
|
+
if (dshStartPromise !== null)
|
|
69
|
+
return dshStartPromise;
|
|
70
|
+
const accessToken = target.getAccessToken();
|
|
71
|
+
if (!accessToken)
|
|
72
|
+
return;
|
|
73
|
+
dshStartPromise = (async () => {
|
|
74
|
+
try {
|
|
75
|
+
const gatewayFeatures = [createDshRpcGatewayFeature(context.services.rpc)];
|
|
76
|
+
if (context.services.dshWebPort !== undefined) {
|
|
77
|
+
gatewayFeatures.push(createRemoteWebRuntimeFeature({
|
|
78
|
+
provider: createLocalDshWebRuntimeProvider({
|
|
79
|
+
port: context.services.dshWebPort,
|
|
80
|
+
dshVersion: context.services.dshVersion ?? DSH_VERSION,
|
|
81
|
+
...(context.services.dshWebAuthenticatedUrl === undefined ? {} : { authenticatedUrl: context.services.dshWebAuthenticatedUrl }),
|
|
82
|
+
}),
|
|
83
|
+
}));
|
|
84
|
+
}
|
|
85
|
+
if (disposed || context.resources.disposed)
|
|
86
|
+
return;
|
|
87
|
+
const runtime = await startDshHostDeviceRuntime({
|
|
88
|
+
controlClient: target.getControlClient(),
|
|
89
|
+
accessToken,
|
|
90
|
+
credentialStore: dshCredentials,
|
|
91
|
+
accessTokenProvider: () => target.getAccessToken(),
|
|
92
|
+
...(context.services.dshVersion === undefined ? {} : { dshVersion: context.services.dshVersion }),
|
|
93
|
+
resources: context.resources,
|
|
94
|
+
gatewayFeatures,
|
|
95
|
+
});
|
|
96
|
+
if (disposed || context.resources.disposed) {
|
|
97
|
+
await runtime.stop();
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
dshRuntime = runtime;
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
// DSH 设备服务不可用时不应破坏已有 Codingns4DSH 登录;下次登录/显式 start 会重试。
|
|
104
|
+
console.error('codingns4dsh: DSH Host runtime 启动失败', error);
|
|
105
|
+
}
|
|
106
|
+
finally {
|
|
107
|
+
dshStartPromise = null;
|
|
108
|
+
}
|
|
109
|
+
})();
|
|
110
|
+
return dshStartPromise;
|
|
111
|
+
};
|
|
112
|
+
const actions = {
|
|
113
|
+
snapshot: () => session?.snapshot() ?? LOGGED_OUT_SNAPSHOT,
|
|
114
|
+
login: async (payload) => {
|
|
115
|
+
const input = parseLogin(payload);
|
|
116
|
+
const target = await ensureSession(input.controlBaseUrl);
|
|
117
|
+
await target.login({ email: input.email, password: input.password });
|
|
118
|
+
await startDsh(target);
|
|
119
|
+
return target.snapshot();
|
|
120
|
+
},
|
|
121
|
+
logout: async () => {
|
|
122
|
+
// DSH 设备注册凭据独立保存在 device-credential.json;注销中继站
|
|
123
|
+
// 登录只停止当前运行时并清理 Codingns4DSH refresh token,不得清除设备注册。
|
|
124
|
+
await dshRuntime?.stop();
|
|
125
|
+
dshRuntime = null;
|
|
126
|
+
if (session)
|
|
127
|
+
await session.logout();
|
|
128
|
+
return { status: 'logged_out' };
|
|
129
|
+
},
|
|
130
|
+
devices: () => requireSession().getDevices(),
|
|
131
|
+
bind: (payload) => requireSession().bindHost(parseHostBind(payload)),
|
|
132
|
+
unbind: (payload) => requireSession().unbindHost(parseStringField(payload, 'bindingId')),
|
|
133
|
+
signalingTicket: (payload) => requireSession().createClientSignalingTicket(parseOptionalStringField(payload, 'tunnelDomain')),
|
|
134
|
+
'dsh/device/list': () => requireSession().getControlClient().listDshDevices(requireSession().getAccessToken() ?? ''),
|
|
135
|
+
'dsh/device/start': async () => { await startDsh(requireSession()); return dshRuntime?.device ?? null; },
|
|
136
|
+
'dsh/device/stop': async () => { await dshRuntime?.stop(); dshRuntime = null; return { stopped: true }; },
|
|
137
|
+
'dsh/device/status': () => dshRuntime ? { device: dshRuntime.device, online: true } : { device: null, online: false },
|
|
138
|
+
'dsh/relayTicket': async (payload) => {
|
|
139
|
+
const loginProtectionToken = isRecord(payload) && typeof payload.loginProtectionToken === 'string' ? payload.loginProtectionToken : undefined;
|
|
140
|
+
if (!await verifyLoginProtectionSession(loginProtectionStore, loginProtectionToken, 'relay')) {
|
|
141
|
+
throw new CodingNsRpcError('CODINGNS_RPC_UNAUTHENTICATED', '需要先完成登录保护验证');
|
|
142
|
+
}
|
|
143
|
+
const target = requireSession();
|
|
144
|
+
if (!dshRuntime)
|
|
145
|
+
await startDsh(target);
|
|
146
|
+
if (!dshRuntime)
|
|
147
|
+
throw new CodingNsRpcError('DSH_DEVICE_OFFLINE', 'DSH Host 尚未上线');
|
|
148
|
+
const input = isRecord(payload) && typeof payload.dshDeviceId === 'string' ? payload.dshDeviceId.trim() : '';
|
|
149
|
+
if (!input || input !== dshRuntime.credential.deviceId)
|
|
150
|
+
throw new CodingNsRpcError('DSH_DEVICE_NOT_FOUND', '请求的 DSH 设备不是当前 Host');
|
|
151
|
+
const accessToken = target.getAccessToken();
|
|
152
|
+
if (!accessToken)
|
|
153
|
+
throw new CodingNsRpcError('CODINGNS_RPC_UNAUTHENTICATED', 'Codingns4DSH 尚未登录');
|
|
154
|
+
const request = {
|
|
155
|
+
dshDeviceId: dshRuntime.credential.deviceId,
|
|
156
|
+
deviceCredential: dshRuntime.credential.deviceCredential,
|
|
157
|
+
hostDtlsFingerprint: dshRuntime.runtime.identity.fingerprint,
|
|
158
|
+
credentialVersion: dshRuntime.credential.credentialVersion,
|
|
159
|
+
role: 'client',
|
|
160
|
+
};
|
|
161
|
+
return target.getControlClient().createDshRelayTicket(accessToken, request);
|
|
162
|
+
},
|
|
163
|
+
};
|
|
164
|
+
context.resources.add(context.services.rpc.register('auth', (action, payload) => {
|
|
165
|
+
const handler = actions[action];
|
|
166
|
+
if (handler === undefined) {
|
|
167
|
+
throw new CodingNsRpcError('CODINGNS_RPC_NOT_FOUND', `未知 Codingns4DSH RPC: auth/${action}`);
|
|
168
|
+
}
|
|
169
|
+
return handler(payload);
|
|
170
|
+
}));
|
|
171
|
+
// 设备心跳维持在线状态;认证 token 临近过期时提前续期,运行时通过
|
|
172
|
+
// accessTokenProvider 自动使用新 token,不需要重建隧道。
|
|
173
|
+
const keepAlive = async () => {
|
|
174
|
+
if (disposed || keepAlivePromise !== null || session === null)
|
|
175
|
+
return;
|
|
176
|
+
const target = session;
|
|
177
|
+
if (target.getAccessToken() === null)
|
|
178
|
+
return;
|
|
179
|
+
keepAlivePromise = (async () => {
|
|
180
|
+
const expiresAt = Date.parse(target.snapshot().expiresAt ?? '');
|
|
181
|
+
if (!Number.isFinite(expiresAt) || expiresAt - Date.now() <= 120_000) {
|
|
182
|
+
try {
|
|
183
|
+
await target.refresh();
|
|
184
|
+
}
|
|
185
|
+
catch (error) {
|
|
186
|
+
console.error('codingns4dsh: 后台刷新 Codingns4DSH 会话失败', error);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
if (dshRuntime === null)
|
|
190
|
+
await startDsh(target);
|
|
191
|
+
})().finally(() => { keepAlivePromise = null; });
|
|
192
|
+
await keepAlivePromise;
|
|
193
|
+
};
|
|
194
|
+
keepAliveTimer = setInterval(() => { void keepAlive(); }, 30_000);
|
|
195
|
+
context.resources.add(() => {
|
|
196
|
+
if (keepAliveTimer !== undefined)
|
|
197
|
+
clearInterval(keepAliveTimer);
|
|
198
|
+
keepAliveTimer = undefined;
|
|
199
|
+
});
|
|
200
|
+
// Host 重启后优先恢复 refresh token,并尝试把已注册的 DSH 设备重新上线。
|
|
201
|
+
void (async () => {
|
|
202
|
+
try {
|
|
203
|
+
const saved = await credentials.read();
|
|
204
|
+
if (!saved)
|
|
205
|
+
return;
|
|
206
|
+
const target = await ensureSession(saved.controlBaseUrl);
|
|
207
|
+
await target.restore();
|
|
208
|
+
await startDsh(target);
|
|
209
|
+
}
|
|
210
|
+
catch (error) {
|
|
211
|
+
console.error('codingns4dsh: 恢复 DSH Host 会话失败', error);
|
|
212
|
+
}
|
|
213
|
+
})();
|
|
214
|
+
context.resources.add(async () => {
|
|
215
|
+
disposed = true;
|
|
216
|
+
await dshRuntime?.stop();
|
|
217
|
+
dshRuntime = null;
|
|
218
|
+
await session?.logout();
|
|
219
|
+
session = null;
|
|
220
|
+
sessionBaseUrl = null;
|
|
221
|
+
});
|
|
222
|
+
},
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
function parseLogin(value) {
|
|
226
|
+
if (!isRecord(value))
|
|
227
|
+
throw new TypeError('登录参数必须是对象');
|
|
228
|
+
return {
|
|
229
|
+
controlBaseUrl: requireUrl(value.controlBaseUrl),
|
|
230
|
+
email: requireString(value.email, 'email'),
|
|
231
|
+
password: requireString(value.password, 'password'),
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
function parseHostBind(value) {
|
|
235
|
+
if (!isRecord(value))
|
|
236
|
+
throw new TypeError('Host 绑定参数必须是对象');
|
|
237
|
+
return {
|
|
238
|
+
hostLabel: requireString(value.hostLabel, 'hostLabel'),
|
|
239
|
+
hostPublicKey: requireString(value.hostPublicKey, 'hostPublicKey'),
|
|
240
|
+
hostFingerprint: requireString(value.hostFingerprint, 'hostFingerprint'),
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
function parseStringField(value, field) {
|
|
244
|
+
if (!isRecord(value))
|
|
245
|
+
throw new TypeError(`${field} 参数必须是对象`);
|
|
246
|
+
return requireString(value[field], field);
|
|
247
|
+
}
|
|
248
|
+
function parseOptionalStringField(value, field) {
|
|
249
|
+
if (value === undefined || value === null)
|
|
250
|
+
return undefined;
|
|
251
|
+
if (!isRecord(value))
|
|
252
|
+
throw new TypeError(`${field} 参数必须是对象`);
|
|
253
|
+
const raw = value[field];
|
|
254
|
+
if (raw === undefined || raw === null || raw === '')
|
|
255
|
+
return undefined;
|
|
256
|
+
return requireString(raw, field);
|
|
257
|
+
}
|
|
258
|
+
function requireString(value, field) {
|
|
259
|
+
if (typeof value !== 'string' || value.trim() === '')
|
|
260
|
+
throw new TypeError(`${field} 不能为空`);
|
|
261
|
+
return value.trim();
|
|
262
|
+
}
|
|
263
|
+
function requireUrl(value) {
|
|
264
|
+
const raw = requireString(value, 'controlBaseUrl');
|
|
265
|
+
const parsed = new URL(raw);
|
|
266
|
+
if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:')
|
|
267
|
+
throw new TypeError('controlBaseUrl 必须使用 HTTP(S)');
|
|
268
|
+
return parsed.toString().replace(/\/$/u, '');
|
|
269
|
+
}
|
|
270
|
+
function isRecord(value) {
|
|
271
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
272
|
+
}
|
|
273
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { FeatureModule } from '../../shared/contracts/feature.js';
|
|
2
|
+
import type { CodingNsHostServices } from './types.js';
|
|
3
|
+
/** Spec003 Host 模块:配置、PTY、端口检查和插件内部代理。 */
|
|
4
|
+
export declare function createDebugFeature(): FeatureModule<CodingNsHostServices>;
|
|
5
|
+
//# sourceMappingURL=debug.d.ts.map
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { CodingNsRpcError } from '../rpc-table.js';
|
|
2
|
+
/** Spec003 Host 模块:配置、PTY、端口检查和插件内部代理。 */
|
|
3
|
+
export function createDebugFeature() {
|
|
4
|
+
return {
|
|
5
|
+
descriptor: {
|
|
6
|
+
name: 'debug',
|
|
7
|
+
version: '0.1.0',
|
|
8
|
+
enabledByDefault: true,
|
|
9
|
+
dependencies: ['terminalProcess'],
|
|
10
|
+
runtime: 'host',
|
|
11
|
+
},
|
|
12
|
+
start(context) {
|
|
13
|
+
const service = context.services.debug;
|
|
14
|
+
if (service === undefined)
|
|
15
|
+
throw new CodingNsRpcError('CODINGNS_DEBUG_UNAVAILABLE', 'Spec003 调试服务未装配');
|
|
16
|
+
context.resources.add(context.services.rpc.register('debug', async (action, payload) => {
|
|
17
|
+
const input = objectFields(payload);
|
|
18
|
+
const workspaceId = requiredString(input.workspaceId, 'workspaceId');
|
|
19
|
+
requiredString(input.sessionId, 'sessionId');
|
|
20
|
+
generation(input.generation);
|
|
21
|
+
switch (action) {
|
|
22
|
+
case 'config/get':
|
|
23
|
+
return service.getConfig(workspaceId);
|
|
24
|
+
case 'config/save':
|
|
25
|
+
return service.saveConfig(workspaceId, input.config);
|
|
26
|
+
case 'config/update':
|
|
27
|
+
return service.updateProfile(workspaceId, requiredString(input.profileId, 'profileId'), input.profile);
|
|
28
|
+
case 'config/delete':
|
|
29
|
+
return service.deleteProfile(workspaceId, requiredString(input.profileId, 'profileId'));
|
|
30
|
+
case 'profile/list':
|
|
31
|
+
return (await service.getConfig(workspaceId)).profiles;
|
|
32
|
+
case 'profile/launch':
|
|
33
|
+
return service.launch({ workspaceId, profileId: requiredString(input.profileId, 'profileId'), ...(input.dshSessionId === undefined ? {} : { dshSessionId: requiredString(input.dshSessionId, 'dshSessionId') }), cols: integer(input.cols, 'cols'), rows: integer(input.rows, 'rows') });
|
|
34
|
+
case 'runtime/get':
|
|
35
|
+
return scopedInstance(service.getInstance(requiredString(input.instanceId, 'instanceId')), workspaceId);
|
|
36
|
+
case 'runtime/list':
|
|
37
|
+
return service.listInstances(workspaceId);
|
|
38
|
+
case 'runtime/stop':
|
|
39
|
+
scopedInstance(service.getInstance(requiredString(input.instanceId, 'instanceId')), workspaceId);
|
|
40
|
+
return service.stop(requiredString(input.instanceId, 'instanceId'));
|
|
41
|
+
case 'port/check':
|
|
42
|
+
return service.checkPort(workspaceId, requiredString(input.profileId, 'profileId'));
|
|
43
|
+
case 'port/terminate':
|
|
44
|
+
return service.terminatePort(workspaceId, requiredString(input.checkId, 'checkId'));
|
|
45
|
+
case 'port/kill':
|
|
46
|
+
return service.killPortProcess(workspaceId, requiredString(input.checkId, 'checkId'));
|
|
47
|
+
case 'proxy/get':
|
|
48
|
+
return service.getProxy(requiredString(input.bindingId, 'bindingId'));
|
|
49
|
+
case 'proxy/enable':
|
|
50
|
+
return service.enableProxy(workspaceId, requiredString(input.profileId, 'profileId'), requiredString(input.instanceId, 'instanceId'));
|
|
51
|
+
case 'proxy/disable':
|
|
52
|
+
return service.disableProxy(workspaceId, requiredString(input.bindingId, 'bindingId'));
|
|
53
|
+
default:
|
|
54
|
+
throw new CodingNsRpcError('CODINGNS_RPC_NOT_FOUND', `未知 Spec003 RPC: debug/${action}`);
|
|
55
|
+
}
|
|
56
|
+
}));
|
|
57
|
+
const registerProxyRoute = context.services.registerDebugProxyRoute;
|
|
58
|
+
if (registerProxyRoute !== undefined)
|
|
59
|
+
context.resources.add(registerProxyRoute((request) => service.handleProxyRequest(request)));
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
function objectFields(value) {
|
|
64
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value))
|
|
65
|
+
throw new TypeError('Spec003 RPC 参数必须是对象');
|
|
66
|
+
return value;
|
|
67
|
+
}
|
|
68
|
+
function requiredString(value, field) {
|
|
69
|
+
if (typeof value !== 'string' || value.trim() === '')
|
|
70
|
+
throw new TypeError(`${field} 必须是非空字符串`);
|
|
71
|
+
return value.trim();
|
|
72
|
+
}
|
|
73
|
+
function integer(value, field) {
|
|
74
|
+
if (typeof value !== 'number' || !Number.isSafeInteger(value) || value <= 0)
|
|
75
|
+
throw new TypeError(`${field} 必须是正整数`);
|
|
76
|
+
return value;
|
|
77
|
+
}
|
|
78
|
+
function generation(value) {
|
|
79
|
+
if (typeof value !== 'number' || !Number.isSafeInteger(value) || value < 0)
|
|
80
|
+
throw new TypeError('generation 必须是非负整数');
|
|
81
|
+
return value;
|
|
82
|
+
}
|
|
83
|
+
function scopedInstance(instance, workspaceId) {
|
|
84
|
+
if (instance === undefined)
|
|
85
|
+
return null;
|
|
86
|
+
if (instance.workspaceId !== workspaceId)
|
|
87
|
+
throw new Error('运行实例不属于当前 Workspace');
|
|
88
|
+
return instance;
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=debug.js.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { FeatureModule } from '../../shared/contracts/feature.js';
|
|
2
|
+
import type { CodingNsHostServices } from './types.js';
|
|
3
|
+
/** 暴露 Host 资源采样;状态保留在模块内,不写入设置和磁盘。 */
|
|
4
|
+
export declare function createHostStatusFeature(): FeatureModule<CodingNsHostServices>;
|
|
5
|
+
interface CpuSample {
|
|
6
|
+
idle: number;
|
|
7
|
+
total: number;
|
|
8
|
+
}
|
|
9
|
+
declare function readCpuSample(): CpuSample;
|
|
10
|
+
declare function cpuUsage(previous: CpuSample, current: CpuSample): number;
|
|
11
|
+
export { cpuUsage, readCpuSample };
|
|
12
|
+
//# sourceMappingURL=host-status.d.ts.map
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { cpus, freemem, totalmem } from 'node:os';
|
|
2
|
+
/** 暴露 Host 资源采样;状态保留在模块内,不写入设置和磁盘。 */
|
|
3
|
+
export function createHostStatusFeature() {
|
|
4
|
+
let previous;
|
|
5
|
+
return {
|
|
6
|
+
descriptor: {
|
|
7
|
+
name: 'hostStatus',
|
|
8
|
+
version: '0.1.0',
|
|
9
|
+
enabledByDefault: true,
|
|
10
|
+
dependencies: [],
|
|
11
|
+
runtime: 'host',
|
|
12
|
+
},
|
|
13
|
+
start(context) {
|
|
14
|
+
context.resources.add(context.services.rpc.register('host', async (action) => {
|
|
15
|
+
if (action !== 'status')
|
|
16
|
+
throw new Error(`未知 Host RPC: host/${action}`);
|
|
17
|
+
const current = readCpuSample();
|
|
18
|
+
const cpuPercent = previous === undefined ? 0 : cpuUsage(previous, current);
|
|
19
|
+
previous = current;
|
|
20
|
+
const memoryTotalBytes = totalmem();
|
|
21
|
+
const memoryUsedBytes = Math.max(0, memoryTotalBytes - freemem());
|
|
22
|
+
const value = {
|
|
23
|
+
cpuPercent,
|
|
24
|
+
memoryPercent: memoryTotalBytes > 0 ? (memoryUsedBytes / memoryTotalBytes) * 100 : 0,
|
|
25
|
+
memoryUsedBytes,
|
|
26
|
+
memoryTotalBytes,
|
|
27
|
+
sampledAt: Date.now(),
|
|
28
|
+
};
|
|
29
|
+
return value;
|
|
30
|
+
}));
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
function readCpuSample() {
|
|
35
|
+
let idle = 0;
|
|
36
|
+
let total = 0;
|
|
37
|
+
for (const cpu of cpus()) {
|
|
38
|
+
idle += cpu.times.idle;
|
|
39
|
+
total += cpu.times.user + cpu.times.nice + cpu.times.sys + cpu.times.idle + cpu.times.irq;
|
|
40
|
+
}
|
|
41
|
+
return { idle, total };
|
|
42
|
+
}
|
|
43
|
+
function cpuUsage(previous, current) {
|
|
44
|
+
const idleDelta = Math.max(0, current.idle - previous.idle);
|
|
45
|
+
const totalDelta = Math.max(0, current.total - previous.total);
|
|
46
|
+
if (totalDelta === 0)
|
|
47
|
+
return 0;
|
|
48
|
+
return clamp((1 - idleDelta / totalDelta) * 100);
|
|
49
|
+
}
|
|
50
|
+
function clamp(value) {
|
|
51
|
+
return Math.min(100, Math.max(0, Number.isFinite(value) ? value : 0));
|
|
52
|
+
}
|
|
53
|
+
export { cpuUsage, readCpuSample };
|
|
54
|
+
//# sourceMappingURL=host-status.js.map
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { FeatureModule } from '../../shared/contracts/feature.js';
|
|
2
|
+
import { createTerminalStatusFeature } from './terminal-status.js';
|
|
3
|
+
import type { CodingNsHostServices } from './types.js';
|
|
4
|
+
export interface HostFeatureOptions {
|
|
5
|
+
readonly terminalStatus?: Parameters<typeof createTerminalStatusFeature>[0];
|
|
6
|
+
}
|
|
7
|
+
/** 生产启动可把实际 controller 模式注入状态模块,避免向设置页报告默认占位值。 */
|
|
8
|
+
export declare function createHostFeatures(options?: HostFeatureOptions): readonly FeatureModule<CodingNsHostServices>[];
|
|
9
|
+
/** Host 侧功能模块清单:新增模块在这里登记一行,不需要改动入口或 RPC 分发。 */
|
|
10
|
+
export declare const HOST_FEATURES: readonly FeatureModule<CodingNsHostServices>[];
|
|
11
|
+
export { createAuthFeature } from './auth.js';
|
|
12
|
+
export { createLanAccessDshFeature } from './lan-access-dsh.js';
|
|
13
|
+
export { createTerminalStatusFeature } from './terminal-status.js';
|
|
14
|
+
export { createCliAdaptersFeature } from '../cli-adapters/feature.js';
|
|
15
|
+
export { createTerminalProcessFeature } from './terminal-process.js';
|
|
16
|
+
export { createDebugFeature } from './debug.js';
|
|
17
|
+
export { createHostStatusFeature } from './host-status.js';
|
|
18
|
+
export type { CodingNsHostServices } from './types.js';
|
|
19
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { createAuthFeature } from './auth.js';
|
|
2
|
+
import { createLanAccessDshFeature } from './lan-access-dsh.js';
|
|
3
|
+
import { createTerminalStatusFeature } from './terminal-status.js';
|
|
4
|
+
import { createCliAdaptersFeature } from '../cli-adapters/feature.js';
|
|
5
|
+
import { createTerminalProcessFeature } from './terminal-process.js';
|
|
6
|
+
import { createDebugFeature } from './debug.js';
|
|
7
|
+
import { createHostStatusFeature } from './host-status.js';
|
|
8
|
+
/** 生产启动可把实际 controller 模式注入状态模块,避免向设置页报告默认占位值。 */
|
|
9
|
+
export function createHostFeatures(options = {}) {
|
|
10
|
+
return [
|
|
11
|
+
createAuthFeature(),
|
|
12
|
+
createLanAccessDshFeature(),
|
|
13
|
+
createTerminalStatusFeature(options.terminalStatus),
|
|
14
|
+
createCliAdaptersFeature(),
|
|
15
|
+
createTerminalProcessFeature(),
|
|
16
|
+
createDebugFeature(),
|
|
17
|
+
createHostStatusFeature(),
|
|
18
|
+
];
|
|
19
|
+
}
|
|
20
|
+
/** Host 侧功能模块清单:新增模块在这里登记一行,不需要改动入口或 RPC 分发。 */
|
|
21
|
+
export const HOST_FEATURES = createHostFeatures();
|
|
22
|
+
export { createAuthFeature } from './auth.js';
|
|
23
|
+
export { createLanAccessDshFeature } from './lan-access-dsh.js';
|
|
24
|
+
export { createTerminalStatusFeature } from './terminal-status.js';
|
|
25
|
+
export { createCliAdaptersFeature } from '../cli-adapters/feature.js';
|
|
26
|
+
export { createTerminalProcessFeature } from './terminal-process.js';
|
|
27
|
+
export { createDebugFeature } from './debug.js';
|
|
28
|
+
export { createHostStatusFeature } from './host-status.js';
|
|
29
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { FeatureModule } from '../../shared/contracts/feature.js';
|
|
2
|
+
import { type LanAccessDshRuntime } from '../lan-access-dsh.js';
|
|
3
|
+
import type { CodingNsHostServices } from './types.js';
|
|
4
|
+
/** Host 侧“局域网访问 DSH”模块,只管理一条 DSH Web 监听映射。 */
|
|
5
|
+
export declare function createLanAccessDshFeature(options?: {
|
|
6
|
+
runtime?: LanAccessDshRuntime;
|
|
7
|
+
}): FeatureModule<CodingNsHostServices>;
|
|
8
|
+
//# sourceMappingURL=lan-access-dsh.d.ts.map
|