@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,125 @@
|
|
|
1
|
+
import { DshTunnelMultiplexer } from './multiplexer.js';
|
|
2
|
+
/** 将 Tunnel Multiplexer 映射为 DSH ClientTransportHooks。 */
|
|
3
|
+
export class DshCodingNsTransport {
|
|
4
|
+
options;
|
|
5
|
+
listeners = new Set();
|
|
6
|
+
multiplexer;
|
|
7
|
+
currentCarrier;
|
|
8
|
+
generation;
|
|
9
|
+
constructor(options) {
|
|
10
|
+
this.options = options;
|
|
11
|
+
this.currentCarrier = options.carrier;
|
|
12
|
+
this.generation = options.generation;
|
|
13
|
+
this.multiplexer = new DshTunnelMultiplexer(options.carrier, {
|
|
14
|
+
idPrefix: `g${options.generation.id}`,
|
|
15
|
+
generation: String(options.generation.id),
|
|
16
|
+
...(options.hostScope ? { hostScope: options.hostScope } : {}),
|
|
17
|
+
...(options.session ? { session: options.session } : {}),
|
|
18
|
+
...(options.requireSessionReady === undefined ? {} : { requireSessionReady: options.requireSessionReady }),
|
|
19
|
+
...(options.flowControl ? { flowControl: options.flowControl } : {}),
|
|
20
|
+
...(options.debug ? { debug: options.debug } : {}),
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
rpc(request) {
|
|
24
|
+
return this.multiplexer.request('rpc', request, request.signal);
|
|
25
|
+
}
|
|
26
|
+
async fetch(input, init) {
|
|
27
|
+
const result = await this.multiplexer.request('fetch', {
|
|
28
|
+
input: String(input),
|
|
29
|
+
init: init ? { method: init.method, headers: [...new Headers(init.headers).entries()], body: typeof init.body === 'string' ? init.body : undefined } : undefined,
|
|
30
|
+
}, init?.signal ?? undefined);
|
|
31
|
+
return new Response(result.body, { status: result.status, headers: result.headers });
|
|
32
|
+
}
|
|
33
|
+
/** 向 Host 的 Remote Web Runtime 发送带明确 operation 的请求。 */
|
|
34
|
+
webRequest(operation, payload, signal) {
|
|
35
|
+
return this.multiplexer.requestOperation('web', operation, payload, signal);
|
|
36
|
+
}
|
|
37
|
+
/** 打开一个由 Remote Web Runtime 管理的 Web 流。 */
|
|
38
|
+
openWebStream(operation, payload, signal) {
|
|
39
|
+
return this.multiplexer.openStreamOperation('web', operation, payload, signal);
|
|
40
|
+
}
|
|
41
|
+
openWebStreamWithId(operation, payload, signal) {
|
|
42
|
+
return this.multiplexer.openStreamOperationWithId('web', operation, payload, signal);
|
|
43
|
+
}
|
|
44
|
+
sendWebStream(streamId, type, body, meta = {}) {
|
|
45
|
+
this.multiplexer.sendStreamMessage(streamId, 'web', type, meta, body);
|
|
46
|
+
}
|
|
47
|
+
closeWebStream(streamId) {
|
|
48
|
+
this.multiplexer.closeStream(streamId, 'web');
|
|
49
|
+
}
|
|
50
|
+
openStream(request) {
|
|
51
|
+
return this.multiplexer.openStream(request, request.signal);
|
|
52
|
+
}
|
|
53
|
+
loadBundle(url) {
|
|
54
|
+
return this.multiplexer.request('control', { method: 'loadBundle', url }).then(() => undefined);
|
|
55
|
+
}
|
|
56
|
+
getGeneration() { return this.generation; }
|
|
57
|
+
onGenerationChange(listener) {
|
|
58
|
+
this.listeners.add(listener);
|
|
59
|
+
return () => this.listeners.delete(listener);
|
|
60
|
+
}
|
|
61
|
+
async reconnect(signal) {
|
|
62
|
+
if (!this.options.reconnect)
|
|
63
|
+
throw new Error('未配置 Transport reconnect');
|
|
64
|
+
const nextGeneration = await this.options.reconnect(signal);
|
|
65
|
+
if (nextGeneration)
|
|
66
|
+
this.updateGeneration(nextGeneration);
|
|
67
|
+
}
|
|
68
|
+
/** 由启动胶水在建立新物理连接后提交新 generation。旧请求会立即失效。 */
|
|
69
|
+
updateGeneration(generation) {
|
|
70
|
+
const previous = this.generation;
|
|
71
|
+
if (previous?.id === generation.id)
|
|
72
|
+
return;
|
|
73
|
+
this.multiplexer.rotateGeneration(`g${generation.id}`);
|
|
74
|
+
this.generation = generation;
|
|
75
|
+
for (const listener of [...this.listeners])
|
|
76
|
+
listener(generation);
|
|
77
|
+
}
|
|
78
|
+
/** 物理 WebRTC 重连后替换 carrier/session,并让 DSH Connection 看见新 generation。 */
|
|
79
|
+
replaceConnection(carrier, session, generation) {
|
|
80
|
+
this.multiplexer.replaceCarrier(carrier);
|
|
81
|
+
this.multiplexer.setSession(session);
|
|
82
|
+
this.currentCarrier = carrier;
|
|
83
|
+
this.updateGeneration(generation);
|
|
84
|
+
}
|
|
85
|
+
/** 物理连接失效时立即结束旧请求和旧 generation。 */
|
|
86
|
+
invalidateConnection(error = new Error('WebRTC connection closed')) {
|
|
87
|
+
this.multiplexer.invalidate(error);
|
|
88
|
+
const previous = this.generation;
|
|
89
|
+
this.generation = undefined;
|
|
90
|
+
if (previous)
|
|
91
|
+
for (const listener of [...this.listeners])
|
|
92
|
+
listener(undefined);
|
|
93
|
+
}
|
|
94
|
+
close() {
|
|
95
|
+
this.multiplexer.close();
|
|
96
|
+
const previous = this.generation;
|
|
97
|
+
this.generation = undefined;
|
|
98
|
+
if (previous)
|
|
99
|
+
for (const listener of [...this.listeners])
|
|
100
|
+
listener(undefined);
|
|
101
|
+
return this.currentCarrier.close();
|
|
102
|
+
}
|
|
103
|
+
/** 给 pre-Cordis 启动胶水使用,不直接安装 DSH Connection。 */
|
|
104
|
+
asTransportHooks() {
|
|
105
|
+
// DSH 0.1.6-alpha.2 的 ClientTransportHooks.rpc 是 ClientConnectionRpc
|
|
106
|
+
// 对象,不是插件内部的 `rpc(request)` 函数。具体适配在 dsh-connection-adapter
|
|
107
|
+
// 中完成;这里仅保留旧的内部 hooks 形状,避免把未确认的线路协议写进核心传输。
|
|
108
|
+
const hooks = {
|
|
109
|
+
rpc: this.rpc.bind(this),
|
|
110
|
+
fetch: this.fetch.bind(this),
|
|
111
|
+
openStream: this.openStream.bind(this),
|
|
112
|
+
loadBundle: this.loadBundle.bind(this),
|
|
113
|
+
generation: this.getGeneration.bind(this),
|
|
114
|
+
onGenerationChange: this.onGenerationChange.bind(this),
|
|
115
|
+
reconnect: this.reconnect.bind(this),
|
|
116
|
+
close: this.close.bind(this),
|
|
117
|
+
};
|
|
118
|
+
if (this.options.ownsHost !== undefined)
|
|
119
|
+
hooks.ownsHost = this.options.ownsHost;
|
|
120
|
+
if (this.options.streamBaseUrl !== undefined)
|
|
121
|
+
hooks.streamBaseUrl = this.options.streamBaseUrl;
|
|
122
|
+
return hooks;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=dsh-transport.js.map
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
export declare const TUNNEL_WIRE_VERSION = 1;
|
|
2
|
+
export declare const TUNNEL_PROTOCOL_VERSION = 1;
|
|
3
|
+
export declare const TUNNEL_FRAME_HEADER_BYTES = 10;
|
|
4
|
+
export declare const TUNNEL_MAX_META_BYTES: number;
|
|
5
|
+
export declare const TUNNEL_MAX_FRAME_BODY_BYTES: number;
|
|
6
|
+
export declare const DEFAULT_MAX_TUNNEL_FRAME_BYTES: number;
|
|
7
|
+
export declare const TUNNEL_FRAME_TYPE_CODES: {
|
|
8
|
+
readonly 'http.request': 1;
|
|
9
|
+
readonly 'http.response.start': 2;
|
|
10
|
+
readonly 'http.response.chunk': 3;
|
|
11
|
+
readonly 'http.response.end': 4;
|
|
12
|
+
readonly 'ws.open': 5;
|
|
13
|
+
readonly 'ws.opened': 6;
|
|
14
|
+
readonly 'ws.message': 7;
|
|
15
|
+
readonly 'ws.closed': 8;
|
|
16
|
+
readonly error: 9;
|
|
17
|
+
readonly hello: 10;
|
|
18
|
+
readonly ping: 11;
|
|
19
|
+
readonly pong: 12;
|
|
20
|
+
readonly 'http.request.chunk': 13;
|
|
21
|
+
readonly 'http.request.end': 14;
|
|
22
|
+
readonly 'ws.message.chunk': 15;
|
|
23
|
+
readonly 'ws.message.end': 16;
|
|
24
|
+
};
|
|
25
|
+
export type TunnelFrameType = keyof typeof TUNNEL_FRAME_TYPE_CODES;
|
|
26
|
+
export type TunnelFrameCode = (typeof TUNNEL_FRAME_TYPE_CODES)[TunnelFrameType];
|
|
27
|
+
export type TunnelChannel = never;
|
|
28
|
+
export type TunnelFrameKind = never;
|
|
29
|
+
export interface TunnelFrameCodecOptions {
|
|
30
|
+
maxBytes?: number;
|
|
31
|
+
}
|
|
32
|
+
export interface TunnelClientContext {
|
|
33
|
+
userAgent: string | null;
|
|
34
|
+
runtimePlatform: string | null;
|
|
35
|
+
systemPlatform: string | null;
|
|
36
|
+
language: string | null;
|
|
37
|
+
timezone: string | null;
|
|
38
|
+
forwardedFor: string | null;
|
|
39
|
+
}
|
|
40
|
+
interface Base {
|
|
41
|
+
streamId: string;
|
|
42
|
+
}
|
|
43
|
+
export type TunnelFrame = (Base & {
|
|
44
|
+
type: 'http.request';
|
|
45
|
+
method: string;
|
|
46
|
+
path: string;
|
|
47
|
+
headers: Record<string, string>;
|
|
48
|
+
body: Uint8Array;
|
|
49
|
+
}) | (Base & {
|
|
50
|
+
type: 'http.request.chunk';
|
|
51
|
+
body: Uint8Array;
|
|
52
|
+
}) | (Base & {
|
|
53
|
+
type: 'http.request.end';
|
|
54
|
+
}) | (Base & {
|
|
55
|
+
type: 'http.response.start';
|
|
56
|
+
status: number;
|
|
57
|
+
headers: Record<string, string>;
|
|
58
|
+
}) | (Base & {
|
|
59
|
+
type: 'http.response.chunk';
|
|
60
|
+
body: Uint8Array;
|
|
61
|
+
}) | (Base & {
|
|
62
|
+
type: 'http.response.end';
|
|
63
|
+
}) | (Base & {
|
|
64
|
+
type: 'ws.open';
|
|
65
|
+
path: string;
|
|
66
|
+
headers: Record<string, string>;
|
|
67
|
+
protocols: string[];
|
|
68
|
+
}) | (Base & {
|
|
69
|
+
type: 'ws.opened';
|
|
70
|
+
selectedProtocol: string | null;
|
|
71
|
+
}) | (Base & {
|
|
72
|
+
type: 'ws.message';
|
|
73
|
+
binary: boolean;
|
|
74
|
+
body: Uint8Array;
|
|
75
|
+
}) | (Base & {
|
|
76
|
+
type: 'ws.message.chunk';
|
|
77
|
+
binary: boolean;
|
|
78
|
+
body: Uint8Array;
|
|
79
|
+
}) | (Base & {
|
|
80
|
+
type: 'ws.message.end';
|
|
81
|
+
}) | (Base & {
|
|
82
|
+
type: 'ws.closed';
|
|
83
|
+
code: number;
|
|
84
|
+
reason: string | null;
|
|
85
|
+
}) | {
|
|
86
|
+
type: 'error';
|
|
87
|
+
streamId: string | null;
|
|
88
|
+
errorCode: string;
|
|
89
|
+
detail: string;
|
|
90
|
+
} | {
|
|
91
|
+
type: 'hello';
|
|
92
|
+
clientContext: TunnelClientContext | null;
|
|
93
|
+
protocolVersion: string;
|
|
94
|
+
} | {
|
|
95
|
+
type: 'ping' | 'pong';
|
|
96
|
+
at: string;
|
|
97
|
+
};
|
|
98
|
+
export declare class TunnelFrameError extends Error {
|
|
99
|
+
readonly code: 'FRAME_TOO_SHORT' | 'UNSUPPORTED_VERSION' | 'UNKNOWN_FRAME_TYPE' | 'META_TOO_LARGE' | 'META_NOT_JSON' | 'META_INVALID' | 'BODY_NOT_ALLOWED' | 'BODY_TOO_LARGE';
|
|
100
|
+
constructor(message: string, code: 'FRAME_TOO_SHORT' | 'UNSUPPORTED_VERSION' | 'UNKNOWN_FRAME_TYPE' | 'META_TOO_LARGE' | 'META_NOT_JSON' | 'META_INVALID' | 'BODY_NOT_ALLOWED' | 'BODY_TOO_LARGE');
|
|
101
|
+
}
|
|
102
|
+
export declare function encodeFrame(frame: TunnelFrame): Uint8Array;
|
|
103
|
+
export declare function decodeFrame(bytes: Uint8Array): TunnelFrame | null;
|
|
104
|
+
export declare function decodeFrames(bytes: Uint8Array): {
|
|
105
|
+
frames: TunnelFrame[];
|
|
106
|
+
rest: Uint8Array;
|
|
107
|
+
};
|
|
108
|
+
export interface TunnelFrameDecoder {
|
|
109
|
+
push(chunk: Uint8Array): TunnelFrame[];
|
|
110
|
+
readonly bufferedBytes: number;
|
|
111
|
+
reset(): void;
|
|
112
|
+
}
|
|
113
|
+
export declare function createFrameDecoder(): TunnelFrameDecoder;
|
|
114
|
+
/** 旧 API 的兼容形状;仅用于升级期间的调用方,不是 Connect 数据面格式。 */
|
|
115
|
+
interface LegacyTunnelFrame {
|
|
116
|
+
version: number;
|
|
117
|
+
channel: 'rpc' | 'fetch' | 'control' | 'stream' | 'event';
|
|
118
|
+
id: string;
|
|
119
|
+
sequence: number;
|
|
120
|
+
kind: 'open' | 'data' | 'close' | 'cancel' | 'window' | 'error';
|
|
121
|
+
payload?: unknown;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* 旧函数名的二进制兼容入口。
|
|
125
|
+
* 新代码必须使用 encodeFrame;这里把旧对象转换成 DSH Envelope 字节,绝不恢复 JSON 字符串帧。
|
|
126
|
+
*/
|
|
127
|
+
export declare function encodeTunnelFrame(frame: TunnelFrame | LegacyTunnelFrame, options?: TunnelFrameCodecOptions): Uint8Array | string;
|
|
128
|
+
export declare function decodeTunnelFrame(data: Uint8Array | string, options?: TunnelFrameCodecOptions): TunnelFrame | LegacyTunnelFrame;
|
|
129
|
+
export declare function tunnelFrameByteLength(value: Uint8Array): number;
|
|
130
|
+
export declare function validateTunnelFrame(value: unknown): asserts value is TunnelFrame;
|
|
131
|
+
export {};
|
|
132
|
+
//# sourceMappingURL=frame.d.ts.map
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/** Codingns4DSH Relay Tunnel 二进制线协议(与父仓库 relay-tunnel-wire 一致)。 */
|
|
2
|
+
import { decodeDshEnvelope } from './dsh-envelope.js';
|
|
3
|
+
export const TUNNEL_WIRE_VERSION = 1;
|
|
4
|
+
export const TUNNEL_PROTOCOL_VERSION = TUNNEL_WIRE_VERSION;
|
|
5
|
+
export const TUNNEL_FRAME_HEADER_BYTES = 10;
|
|
6
|
+
export const TUNNEL_MAX_META_BYTES = 1024 * 1024;
|
|
7
|
+
export const TUNNEL_MAX_FRAME_BODY_BYTES = 48 * 1024;
|
|
8
|
+
export const DEFAULT_MAX_TUNNEL_FRAME_BYTES = TUNNEL_MAX_FRAME_BODY_BYTES;
|
|
9
|
+
export const TUNNEL_FRAME_TYPE_CODES = {
|
|
10
|
+
'http.request': 1, 'http.response.start': 2, 'http.response.chunk': 3, 'http.response.end': 4,
|
|
11
|
+
'ws.open': 5, 'ws.opened': 6, 'ws.message': 7, 'ws.closed': 8, error: 9, hello: 10, ping: 11, pong: 12,
|
|
12
|
+
'http.request.chunk': 13, 'http.request.end': 14, 'ws.message.chunk': 15, 'ws.message.end': 16,
|
|
13
|
+
};
|
|
14
|
+
export class TunnelFrameError extends Error {
|
|
15
|
+
code;
|
|
16
|
+
constructor(message, code) {
|
|
17
|
+
super(message);
|
|
18
|
+
this.code = code;
|
|
19
|
+
this.name = 'TunnelFrameError';
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
const byCode = new Map(Object.entries(TUNNEL_FRAME_TYPE_CODES).map(([k, v]) => [v, k]));
|
|
23
|
+
const encoder = new TextEncoder();
|
|
24
|
+
const decoder = new TextDecoder('utf-8');
|
|
25
|
+
const empty = new Uint8Array(0);
|
|
26
|
+
export function encodeFrame(frame) {
|
|
27
|
+
const code = TUNNEL_FRAME_TYPE_CODES[frame.type];
|
|
28
|
+
if (typeof code !== 'number')
|
|
29
|
+
throw new TunnelFrameError(`未知的帧类型:${String(frame.type)}`, 'UNKNOWN_FRAME_TYPE');
|
|
30
|
+
const meta = encoder.encode(JSON.stringify(metaOf(frame)));
|
|
31
|
+
const body = bodyOf(frame);
|
|
32
|
+
if (meta.byteLength > TUNNEL_MAX_META_BYTES)
|
|
33
|
+
throw new TunnelFrameError(`帧 ${frame.type} 的 meta 超过上限`, 'META_TOO_LARGE');
|
|
34
|
+
if (body.byteLength > TUNNEL_MAX_FRAME_BODY_BYTES)
|
|
35
|
+
throw new TunnelFrameError(`帧 ${frame.type} 的 body 超过单帧上限`, 'BODY_TOO_LARGE');
|
|
36
|
+
const output = new Uint8Array(TUNNEL_FRAME_HEADER_BYTES + meta.byteLength + body.byteLength);
|
|
37
|
+
const view = new DataView(output.buffer);
|
|
38
|
+
view.setUint8(0, TUNNEL_WIRE_VERSION);
|
|
39
|
+
view.setUint8(1, code);
|
|
40
|
+
view.setUint32(2, meta.byteLength);
|
|
41
|
+
view.setUint32(6, body.byteLength);
|
|
42
|
+
output.set(meta, TUNNEL_FRAME_HEADER_BYTES);
|
|
43
|
+
output.set(body, TUNNEL_FRAME_HEADER_BYTES + meta.byteLength);
|
|
44
|
+
return output;
|
|
45
|
+
}
|
|
46
|
+
export function decodeFrame(bytes) { return readFrame(bytes)?.frame ?? null; }
|
|
47
|
+
export function decodeFrames(bytes) { const frames = []; let offset = 0; while (offset < bytes.byteLength) {
|
|
48
|
+
const parsed = readFrame(bytes.subarray(offset));
|
|
49
|
+
if (!parsed)
|
|
50
|
+
break;
|
|
51
|
+
frames.push(parsed.frame);
|
|
52
|
+
offset += parsed.consumed;
|
|
53
|
+
} return { frames, rest: offset === 0 ? bytes : bytes.subarray(offset) }; }
|
|
54
|
+
export function createFrameDecoder() { let pending = new Uint8Array(0); return { push(chunk) { if (chunk.byteLength)
|
|
55
|
+
pending = concat(pending, chunk); const result = decodeFrames(pending); if (result.frames.length)
|
|
56
|
+
pending = new Uint8Array(result.rest); return result.frames; }, get bufferedBytes() { return pending.byteLength; }, reset() { pending = new Uint8Array(0); } }; }
|
|
57
|
+
function readFrame(bytes) { if (bytes.byteLength < TUNNEL_FRAME_HEADER_BYTES)
|
|
58
|
+
return null; const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength); if (view.getUint8(0) !== TUNNEL_WIRE_VERSION)
|
|
59
|
+
throw new TunnelFrameError('线协议版本不支持', 'UNSUPPORTED_VERSION'); const type = byCode.get(view.getUint8(1)); if (!type)
|
|
60
|
+
throw new TunnelFrameError('未知的帧类型编号', 'UNKNOWN_FRAME_TYPE'); const metaLength = view.getUint32(2); const bodyLength = view.getUint32(6); if (metaLength > TUNNEL_MAX_META_BYTES)
|
|
61
|
+
throw new TunnelFrameError('meta 超过上限', 'META_TOO_LARGE'); const total = TUNNEL_FRAME_HEADER_BYTES + metaLength + bodyLength; if (bytes.byteLength < total)
|
|
62
|
+
return null; const metaBytes = bytes.subarray(TUNNEL_FRAME_HEADER_BYTES, TUNNEL_FRAME_HEADER_BYTES + metaLength); const body = new Uint8Array(bytes.subarray(TUNNEL_FRAME_HEADER_BYTES + metaLength, total)); return { frame: frameFromMeta(type, metaBytes, body), consumed: total }; }
|
|
63
|
+
function metaOf(frame) { switch (frame.type) {
|
|
64
|
+
case 'http.request': return { streamId: frame.streamId, method: frame.method, path: frame.path, headers: frame.headers };
|
|
65
|
+
case 'http.response.start': return { streamId: frame.streamId, status: frame.status, headers: frame.headers };
|
|
66
|
+
case 'http.request.chunk':
|
|
67
|
+
case 'http.request.end':
|
|
68
|
+
case 'http.response.chunk':
|
|
69
|
+
case 'http.response.end':
|
|
70
|
+
case 'ws.message.end': return { streamId: frame.streamId };
|
|
71
|
+
case 'ws.open': return { streamId: frame.streamId, path: frame.path, headers: frame.headers, protocols: frame.protocols };
|
|
72
|
+
case 'ws.opened': return { streamId: frame.streamId, selectedProtocol: frame.selectedProtocol };
|
|
73
|
+
case 'ws.message':
|
|
74
|
+
case 'ws.message.chunk': return { streamId: frame.streamId, binary: frame.binary };
|
|
75
|
+
case 'ws.closed': return { streamId: frame.streamId, code: frame.code, reason: frame.reason };
|
|
76
|
+
case 'error': return { streamId: frame.streamId, errorCode: frame.errorCode, detail: frame.detail };
|
|
77
|
+
case 'hello': return { clientContext: frame.clientContext, protocolVersion: frame.protocolVersion };
|
|
78
|
+
case 'ping':
|
|
79
|
+
case 'pong': return { at: frame.at };
|
|
80
|
+
} }
|
|
81
|
+
function bodyOf(frame) { return 'body' in frame ? frame.body : empty; }
|
|
82
|
+
function frameFromMeta(type, bytes, body) { let meta; try {
|
|
83
|
+
const parsed = JSON.parse(decoder.decode(bytes));
|
|
84
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed))
|
|
85
|
+
throw new Error('对象');
|
|
86
|
+
meta = parsed;
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
throw new TunnelFrameError(`帧 ${type} 的 meta 不是合法 JSON`, 'META_NOT_JSON');
|
|
90
|
+
} const str = (name) => { const value = meta[name]; if (typeof value !== 'string')
|
|
91
|
+
throw new TunnelFrameError(`帧 ${type} 的 meta.${name} 无效`, 'META_INVALID'); return value; }; const headers = () => (meta.headers && typeof meta.headers === 'object' && !Array.isArray(meta.headers)) ? meta.headers : {}; switch (type) {
|
|
92
|
+
case 'http.request': return { type, streamId: str('streamId'), method: str('method'), path: str('path'), headers: headers(), body };
|
|
93
|
+
case 'http.request.chunk': return { type, streamId: str('streamId'), body };
|
|
94
|
+
case 'http.request.end': return { type, streamId: str('streamId') };
|
|
95
|
+
case 'http.response.start': return { type, streamId: str('streamId'), status: Number(meta.status), headers: headers() };
|
|
96
|
+
case 'http.response.chunk': return { type, streamId: str('streamId'), body };
|
|
97
|
+
case 'http.response.end': return { type, streamId: str('streamId') };
|
|
98
|
+
case 'ws.open': return { type, streamId: str('streamId'), path: str('path'), headers: headers(), protocols: Array.isArray(meta.protocols) ? meta.protocols.filter((v) => typeof v === 'string') : [] };
|
|
99
|
+
case 'ws.opened': return { type, streamId: str('streamId'), selectedProtocol: typeof meta.selectedProtocol === 'string' ? meta.selectedProtocol : null };
|
|
100
|
+
case 'ws.message':
|
|
101
|
+
case 'ws.message.chunk': return { type, streamId: str('streamId'), binary: meta.binary === true, body };
|
|
102
|
+
case 'ws.message.end': return { type, streamId: str('streamId') };
|
|
103
|
+
case 'ws.closed': return { type, streamId: str('streamId'), code: Number(meta.code), reason: typeof meta.reason === 'string' ? meta.reason : null };
|
|
104
|
+
case 'error': return { type, streamId: typeof meta.streamId === 'string' ? meta.streamId : null, errorCode: str('errorCode'), detail: typeof meta.detail === 'string' ? meta.detail : '' };
|
|
105
|
+
case 'hello': return { type, clientContext: parseContext(meta.clientContext), protocolVersion: typeof meta.protocolVersion === 'string' ? meta.protocolVersion : '1' };
|
|
106
|
+
case 'ping':
|
|
107
|
+
case 'pong': return { type, at: str('at') };
|
|
108
|
+
} }
|
|
109
|
+
function parseContext(value) { if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
110
|
+
return null; const r = value; const pick = (k) => typeof r[k] === 'string' && r[k].trim() ? r[k] : null; return { userAgent: pick('userAgent'), runtimePlatform: pick('runtimePlatform'), systemPlatform: pick('systemPlatform'), language: pick('language'), timezone: pick('timezone'), forwardedFor: pick('forwardedFor') }; }
|
|
111
|
+
function concat(a, b) { const out = new Uint8Array(a.byteLength + b.byteLength); out.set(a); out.set(b, a.byteLength); return out; }
|
|
112
|
+
/**
|
|
113
|
+
* 旧函数名的二进制兼容入口。
|
|
114
|
+
* 新代码必须使用 encodeFrame;这里把旧对象转换成 DSH Envelope 字节,绝不恢复 JSON 字符串帧。
|
|
115
|
+
*/
|
|
116
|
+
export function encodeTunnelFrame(frame, options = {}) {
|
|
117
|
+
if (isLegacyFrame(frame)) {
|
|
118
|
+
const encoded = JSON.stringify(frame);
|
|
119
|
+
if (options.maxBytes !== undefined && encoder.encode(encoded).byteLength > options.maxBytes)
|
|
120
|
+
throw new Error('Tunnel Frame 超过大小限制');
|
|
121
|
+
return encoded;
|
|
122
|
+
}
|
|
123
|
+
return encodeFrame(frame);
|
|
124
|
+
}
|
|
125
|
+
export function decodeTunnelFrame(data, options = {}) {
|
|
126
|
+
if (typeof data === 'string') {
|
|
127
|
+
if (options.maxBytes !== undefined && encoder.encode(data).byteLength > options.maxBytes)
|
|
128
|
+
throw new Error('Tunnel Frame 超过大小限制');
|
|
129
|
+
const parsed = JSON.parse(data);
|
|
130
|
+
if (!isLegacyFrame(parsed))
|
|
131
|
+
throw new TunnelFrameError('Tunnel Frame 无效', 'META_INVALID');
|
|
132
|
+
if (parsed.version !== TUNNEL_WIRE_VERSION)
|
|
133
|
+
throw new TunnelFrameError('Tunnel Frame 版本不兼容', 'UNSUPPORTED_VERSION');
|
|
134
|
+
return parsed;
|
|
135
|
+
}
|
|
136
|
+
if (!(data instanceof Uint8Array))
|
|
137
|
+
throw new TypeError('Tunnel Frame 必须是 Uint8Array');
|
|
138
|
+
if (data[0] === 0x44 && data[1] === 0x53 && data[2] === 0x48 && data[3] === 0x01) {
|
|
139
|
+
const envelope = decodeDshEnvelope(data, options.maxBytes === undefined ? {} : { maxBytes: options.maxBytes });
|
|
140
|
+
const payload = envelope.body && envelope.body.byteLength > 0
|
|
141
|
+
? JSON.parse(new TextDecoder().decode(envelope.body))
|
|
142
|
+
: undefined;
|
|
143
|
+
const [channel, kind] = envelope.type.split('.', 2);
|
|
144
|
+
if (!['rpc', 'fetch', 'control', 'stream', 'event'].includes(channel ?? '')
|
|
145
|
+
|| !['open', 'data', 'close', 'cancel', 'window', 'error'].includes(kind ?? '')) {
|
|
146
|
+
throw new TunnelFrameError('兼容 Tunnel Frame 类型无效', 'META_INVALID');
|
|
147
|
+
}
|
|
148
|
+
return {
|
|
149
|
+
version: 1,
|
|
150
|
+
channel: channel,
|
|
151
|
+
id: envelope.streamId,
|
|
152
|
+
sequence: envelope.sequence,
|
|
153
|
+
kind: kind,
|
|
154
|
+
...(payload === undefined ? {} : { payload }),
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
const decoded = decodeFrame(data);
|
|
158
|
+
if (decoded === null)
|
|
159
|
+
throw new TunnelFrameError('Tunnel Frame 数据不完整', 'FRAME_TOO_SHORT');
|
|
160
|
+
return decoded;
|
|
161
|
+
}
|
|
162
|
+
function isLegacyFrame(value) {
|
|
163
|
+
return typeof value === 'object' && value !== null && 'kind' in value && 'channel' in value;
|
|
164
|
+
}
|
|
165
|
+
export function tunnelFrameByteLength(value) { return value.byteLength; }
|
|
166
|
+
export function validateTunnelFrame(value) { if (!value || typeof value !== 'object' || !('type' in value))
|
|
167
|
+
throw new TunnelFrameError('Tunnel Frame 无效', 'META_INVALID'); }
|
|
168
|
+
//# sourceMappingURL=frame.js.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export { createDataChannelCarrier, createRelayTunnelHostCarrier, TUNNEL_DATA_CHANNEL_LABEL, DATA_CHANNEL_FRAGMENT_PAYLOAD_BYTES, DATA_CHANNEL_FRAGMENT_HEADER_BYTES, DATA_CHANNEL_MAX_REASSEMBLY_BYTES, type CodingNsCarrier, type DataChannelLike, type DataChannelCarrierOptions } from './carrier.js';
|
|
2
|
+
export { encodeFrame, decodeFrame, decodeFrames, createFrameDecoder, decodeTunnelFrame, encodeTunnelFrame, TUNNEL_WIRE_VERSION, TUNNEL_FRAME_HEADER_BYTES, TUNNEL_MAX_META_BYTES, TUNNEL_MAX_FRAME_BODY_BYTES, TUNNEL_FRAME_TYPE_CODES, TUNNEL_PROTOCOL_VERSION, validateTunnelFrame, tunnelFrameByteLength, DEFAULT_MAX_TUNNEL_FRAME_BYTES, type TunnelChannel, type TunnelFrame, type TunnelFrameKind, type TunnelFrameCodecOptions, type TunnelFrameType, type TunnelClientContext, } from './frame.js';
|
|
3
|
+
export { DshTunnelMultiplexer, type DshTunnelMultiplexerOptions, type TunnelFlowControl } from './multiplexer.js';
|
|
4
|
+
export { createDshTransportDebugLogger, resolveDshTransportDebugEnabled, type DshTransportDebugLogger, type DshTransportDebugOptions, type DshTransportDebugSide } from './debug.js';
|
|
5
|
+
export { DshCodingNsTransport, type DshCodingNsTransportOptions } from './dsh-transport.js';
|
|
6
|
+
export { DSH_ENVELOPE_PROTOCOL, DSH_ENVELOPE_VERSION, DEFAULT_MAX_DSH_ENVELOPE_BYTES, DEFAULT_MAX_DSH_META_BYTES, decodeDshEnvelope, encodeDshEnvelope, validateDshEnvelope, type DshChannel, type DshEnvelope, type DshEnvelopeCodecOptions, type DshEnvelopeFlags, type DshHostScope, } from './dsh-envelope.js';
|
|
7
|
+
export { DshSession, type DshSessionOptions, type DshSessionRole, type DshSessionState, } from './dsh-session.js';
|
|
8
|
+
export { DshGateway, DSH_GATEWAY_PATH, type DshGatewayFeature, type DshGatewayOptions, type DshStreamContext, } from './dsh-gateway.js';
|
|
9
|
+
export { assertDtlsFingerprint, connectWebRtcClient, createSignalingUrl, extractDtlsFingerprint, waitForSignalingRegistered, waitForPeerReady, type PeerConnectionLike, type SignalingSocketLike, type WebRtcClientConnection, type WebRtcClientConnectorOptions, } from './webrtc-client.js';
|
|
10
|
+
export { acceptWebRtcHost, createHostSignalingTicketRequest, requestHostSignalingTicket, type HostPeerConnectionLike, type HostSignalingTicketRequest, type WebRtcHostAcceptor, type WebRtcHostAcceptorOptions, type WebRtcHostSession, } from './webrtc-host.js';
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export { createDataChannelCarrier, createRelayTunnelHostCarrier, TUNNEL_DATA_CHANNEL_LABEL, DATA_CHANNEL_FRAGMENT_PAYLOAD_BYTES, DATA_CHANNEL_FRAGMENT_HEADER_BYTES, DATA_CHANNEL_MAX_REASSEMBLY_BYTES } from './carrier.js';
|
|
2
|
+
export { encodeFrame, decodeFrame, decodeFrames, createFrameDecoder, decodeTunnelFrame, encodeTunnelFrame, TUNNEL_WIRE_VERSION, TUNNEL_FRAME_HEADER_BYTES, TUNNEL_MAX_META_BYTES, TUNNEL_MAX_FRAME_BODY_BYTES, TUNNEL_FRAME_TYPE_CODES, TUNNEL_PROTOCOL_VERSION, validateTunnelFrame, tunnelFrameByteLength, DEFAULT_MAX_TUNNEL_FRAME_BYTES, } from './frame.js';
|
|
3
|
+
export { DshTunnelMultiplexer } from './multiplexer.js';
|
|
4
|
+
export { createDshTransportDebugLogger, resolveDshTransportDebugEnabled } from './debug.js';
|
|
5
|
+
export { DshCodingNsTransport } from './dsh-transport.js';
|
|
6
|
+
export { DSH_ENVELOPE_PROTOCOL, DSH_ENVELOPE_VERSION, DEFAULT_MAX_DSH_ENVELOPE_BYTES, DEFAULT_MAX_DSH_META_BYTES, decodeDshEnvelope, encodeDshEnvelope, validateDshEnvelope, } from './dsh-envelope.js';
|
|
7
|
+
export { DshSession, } from './dsh-session.js';
|
|
8
|
+
export { DshGateway, DSH_GATEWAY_PATH, } from './dsh-gateway.js';
|
|
9
|
+
export { assertDtlsFingerprint, connectWebRtcClient, createSignalingUrl, extractDtlsFingerprint, waitForSignalingRegistered, waitForPeerReady, } from './webrtc-client.js';
|
|
10
|
+
export { acceptWebRtcHost, createHostSignalingTicketRequest, requestHostSignalingTicket, } from './webrtc-host.js';
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { CodingNsCarrier } from './carrier.js';
|
|
2
|
+
import { type DshEnvelope, type DshHostScope } from './dsh-envelope.js';
|
|
3
|
+
import type { DshSession } from './dsh-session.js';
|
|
4
|
+
import { type DshTransportDebugLogger } from './debug.js';
|
|
5
|
+
export interface TunnelFlowControl {
|
|
6
|
+
maxFrameBytes?: number;
|
|
7
|
+
maxQueueBytes?: number;
|
|
8
|
+
canSend?(bytes: number, frame: DshEnvelope): boolean;
|
|
9
|
+
onSend?(bytes: number, frame: DshEnvelope): void;
|
|
10
|
+
onReceive?(bytes: number, frame: DshEnvelope): void;
|
|
11
|
+
}
|
|
12
|
+
export interface DshTunnelMultiplexerOptions {
|
|
13
|
+
idPrefix?: string;
|
|
14
|
+
generation?: string;
|
|
15
|
+
hostScope?: DshHostScope;
|
|
16
|
+
session?: DshSession;
|
|
17
|
+
requireSessionReady?: boolean;
|
|
18
|
+
flowControl?: TunnelFlowControl;
|
|
19
|
+
debug?: DshTransportDebugLogger;
|
|
20
|
+
}
|
|
21
|
+
/** DSH Envelope 层多路复用器;逻辑 API 保持 rpc/openStream,物理线路只发送二进制 Envelope。 */
|
|
22
|
+
export declare class DshTunnelMultiplexer {
|
|
23
|
+
private carrier;
|
|
24
|
+
private readonly pending;
|
|
25
|
+
private readonly streams;
|
|
26
|
+
private sequence;
|
|
27
|
+
private nextId;
|
|
28
|
+
private disposed;
|
|
29
|
+
private unsubscribe;
|
|
30
|
+
private idPrefix;
|
|
31
|
+
private readonly flowControl;
|
|
32
|
+
private generation;
|
|
33
|
+
private readonly hostScope;
|
|
34
|
+
private session;
|
|
35
|
+
private readonly requireSessionReady;
|
|
36
|
+
private readonly debug;
|
|
37
|
+
constructor(carrier: CodingNsCarrier, options?: DshTunnelMultiplexerOptions);
|
|
38
|
+
request<T>(channel: 'rpc' | 'fetch' | 'control', payload: unknown, signal?: AbortSignal): Promise<T>;
|
|
39
|
+
requestOperation<T>(channel: 'rpc' | 'fetch' | 'control' | 'web', operation: string, payload: unknown, signal?: AbortSignal): Promise<T>;
|
|
40
|
+
openStream<T>(payload: unknown, signal?: AbortSignal): AsyncIterable<T>;
|
|
41
|
+
openStreamOperation<T>(channel: 'rpc' | 'web', operation: string, payload: unknown, signal?: AbortSignal): AsyncIterable<T>;
|
|
42
|
+
openStreamOperationWithId<T>(channel: 'rpc' | 'web', operation: string, payload: unknown, signal?: AbortSignal): {
|
|
43
|
+
streamId: string;
|
|
44
|
+
stream: AsyncIterable<T>;
|
|
45
|
+
};
|
|
46
|
+
sendStreamMessage(streamId: string, channel: 'rpc' | 'web', type: string, meta?: Record<string, unknown>, body?: Uint8Array): void;
|
|
47
|
+
closeStream(streamId: string, channel?: 'rpc' | 'web'): void;
|
|
48
|
+
close(error?: Error): void;
|
|
49
|
+
invalidate(error?: Error): void;
|
|
50
|
+
/** 替换物理 carrier;逻辑请求已在 invalidate 中失败,后续请求使用新线路。 */
|
|
51
|
+
replaceCarrier(carrier: CodingNsCarrier): void;
|
|
52
|
+
setSession(session: DshSession | undefined): void;
|
|
53
|
+
rotateGeneration(idPrefix: string, error?: Error): void;
|
|
54
|
+
private receive;
|
|
55
|
+
private receiveStream;
|
|
56
|
+
private finishStream;
|
|
57
|
+
private send;
|
|
58
|
+
private nextSequence;
|
|
59
|
+
private nextRequestId;
|
|
60
|
+
private closedStream;
|
|
61
|
+
private ensureOpen;
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=multiplexer.d.ts.map
|