@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,361 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Codingns4DSH Relay Host 运行时。
|
|
3
|
+
*
|
|
4
|
+
* 这个模块把 Host 侧真正需要的运行时资源集中起来:DTLS 身份、Host 票据、
|
|
5
|
+
* Relay 信令 WebSocket 以及每个 Client 独立的 werift PeerConnection。业务层
|
|
6
|
+
* 只接收已经打开的 DataChannel Carrier,不接触 access token 或信令细节。
|
|
7
|
+
*/
|
|
8
|
+
import { mkdir, readFile, rename, writeFile } from 'node:fs/promises';
|
|
9
|
+
import { dirname } from 'node:path';
|
|
10
|
+
import { RTCCertificate, RTCDtlsTransport, RTCPeerConnection } from 'werift';
|
|
11
|
+
import { acceptWebRtcHost, createHostSignalingTicketRequest, } from '../transport/webrtc-host.js';
|
|
12
|
+
import { DshGateway } from '../transport/dsh-gateway.js';
|
|
13
|
+
import { createDshTransportDebugLogger } from '../transport/debug.js';
|
|
14
|
+
/** Relay Tunnel 规定的 DataChannel label,不允许使用插件自定义值。 */
|
|
15
|
+
export const CODINGNS_TUNNEL_DATA_CHANNEL_LABEL = 'codingns-tunnel';
|
|
16
|
+
/** 文件存储适用于 Host 桌面进程;先写临时文件再 rename,避免半截证书。 */
|
|
17
|
+
export class FileHostDtlsIdentityStore {
|
|
18
|
+
filePath;
|
|
19
|
+
constructor(filePath) {
|
|
20
|
+
this.filePath = filePath;
|
|
21
|
+
if (!filePath.trim())
|
|
22
|
+
throw new TypeError('DTLS identity file path 不能为空');
|
|
23
|
+
}
|
|
24
|
+
async read() {
|
|
25
|
+
try {
|
|
26
|
+
const raw = await readFile(this.filePath, 'utf8');
|
|
27
|
+
const parsed = JSON.parse(raw);
|
|
28
|
+
return parseIdentity(parsed);
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
if (isNodeError(error, 'ENOENT'))
|
|
32
|
+
return null;
|
|
33
|
+
throw error;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
async write(identity) {
|
|
37
|
+
await mkdir(dirname(this.filePath), { recursive: true });
|
|
38
|
+
const temporaryPath = `${this.filePath}.${process.pid}.tmp`;
|
|
39
|
+
await writeFile(temporaryPath, `${JSON.stringify(identity)}\n`, { encoding: 'utf8', mode: 0o600 });
|
|
40
|
+
await rename(temporaryPath, this.filePath);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/** 生成一张新的 werift DTLS 证书,并返回控制面约定的 sha-256 指纹。 */
|
|
44
|
+
export async function generateHostDtlsIdentity() {
|
|
45
|
+
const certificate = await RTCDtlsTransport.SetupCertificate();
|
|
46
|
+
const fingerprint = formatHostDtlsFingerprint(certificate);
|
|
47
|
+
const now = new Date().toISOString();
|
|
48
|
+
return {
|
|
49
|
+
privateKeyPem: certificate.privateKey,
|
|
50
|
+
certPem: certificate.certPem,
|
|
51
|
+
signatureHash: certificate.signatureHash,
|
|
52
|
+
fingerprint,
|
|
53
|
+
createdAt: now,
|
|
54
|
+
updatedAt: now,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
/** 读取已有身份,否则生成并持久化;指纹因此跨进程重启保持不变。 */
|
|
58
|
+
export async function ensureHostDtlsIdentity(store) {
|
|
59
|
+
const existing = await store.read();
|
|
60
|
+
if (existing)
|
|
61
|
+
return existing;
|
|
62
|
+
const generated = await generateHostDtlsIdentity();
|
|
63
|
+
await store.write(generated);
|
|
64
|
+
return generated;
|
|
65
|
+
}
|
|
66
|
+
export function formatHostDtlsFingerprint(certificate) {
|
|
67
|
+
const fingerprints = certificate.getFingerprints();
|
|
68
|
+
const selected = fingerprints.find((item) => item.algorithm.toLowerCase() === 'sha-256') ?? fingerprints[0];
|
|
69
|
+
if (!selected)
|
|
70
|
+
throw new Error('DTLS 证书缺少指纹');
|
|
71
|
+
const value = selected.value.split(':').map((part) => part.trim().toUpperCase().padStart(2, '0')).join(':');
|
|
72
|
+
return `${selected.algorithm.toLowerCase()} ${value}`;
|
|
73
|
+
}
|
|
74
|
+
/** 同一 Host 进程内只允许一个 Relay runtime,避免热重载留下旧 Gateway 和流。 */
|
|
75
|
+
const activeRelayRuntimes = new Map();
|
|
76
|
+
/**
|
|
77
|
+
* 启动一个可接收多个 Client 的 Host Relay runtime。
|
|
78
|
+
* `resources` 若提供,所有 WebSocket、PeerConnection、心跳和换票计时器都会登记。
|
|
79
|
+
*/
|
|
80
|
+
export async function startHostRelayRuntime(options) {
|
|
81
|
+
if (!options.accessToken.trim())
|
|
82
|
+
throw new TypeError('Host Relay accessToken 不能为空');
|
|
83
|
+
if (!options.bindingId?.trim() && options.createTicket === undefined)
|
|
84
|
+
throw new TypeError('Host Relay bindingId 或 createTicket 必须提供');
|
|
85
|
+
const bindingId = options.bindingId?.trim() ?? '';
|
|
86
|
+
const runtimeKey = (options.hostId?.trim() || bindingId) || null;
|
|
87
|
+
const previousRuntime = runtimeKey === null ? undefined : activeRelayRuntimes.get(runtimeKey);
|
|
88
|
+
if (previousRuntime)
|
|
89
|
+
await previousRuntime.close();
|
|
90
|
+
const debug = options.debug ?? createDshTransportDebugLogger({ side: 'host', component: 'relay-runtime' });
|
|
91
|
+
const identity = await ensureHostDtlsIdentity(options.dtlsStore);
|
|
92
|
+
const requestTicket = () => options.createTicket
|
|
93
|
+
? options.createTicket({ accessToken: options.accessToken, identity, ...(options.credentialVersion === undefined ? {} : { credentialVersion: options.credentialVersion }) })
|
|
94
|
+
: options.controlClient.createSignalingTicket(options.accessToken, createHostSignalingTicketRequest({
|
|
95
|
+
bindingId,
|
|
96
|
+
hostDtlsFingerprint: identity.fingerprint,
|
|
97
|
+
...(options.credentialVersion === undefined ? {} : { credentialVersion: options.credentialVersion }),
|
|
98
|
+
}));
|
|
99
|
+
let ticket = await requestTicket();
|
|
100
|
+
let closed = false;
|
|
101
|
+
let renewTimer = null;
|
|
102
|
+
let renewalInFlight = false;
|
|
103
|
+
let renewalResourceRegistered = false;
|
|
104
|
+
let acceptor = await createAcceptor(ticket);
|
|
105
|
+
const gateways = new Map();
|
|
106
|
+
const scheduleRenewal = () => {
|
|
107
|
+
if (renewTimer !== null)
|
|
108
|
+
clearTimeout(renewTimer);
|
|
109
|
+
if (closed)
|
|
110
|
+
return;
|
|
111
|
+
const expiresAt = Date.parse(ticket.expiresAt);
|
|
112
|
+
const skew = options.ticketRenewSkewMs ?? 30_000;
|
|
113
|
+
// 信令票据只在 WebSocket 建立时校验。连接仍然存活时不能因为票据
|
|
114
|
+
// 到期而替换 WebSocket,否则会在客户端 offer/answer 期间丢信令。
|
|
115
|
+
const signalingOpen = isSignalingOpen(acceptor.signaling);
|
|
116
|
+
const untilExpiry = Number.isFinite(expiresAt) ? expiresAt - Date.now() : 60_000;
|
|
117
|
+
const delay = signalingOpen
|
|
118
|
+
? Math.min(2_147_000_000, Math.max(30_000, untilExpiry - skew))
|
|
119
|
+
: Math.max(1_000, Math.min(30_000, untilExpiry - skew));
|
|
120
|
+
renewTimer = setTimeout(() => { void renew(); }, delay);
|
|
121
|
+
if (options.resources && !renewalResourceRegistered) {
|
|
122
|
+
renewalResourceRegistered = true;
|
|
123
|
+
options.resources.add(() => {
|
|
124
|
+
if (renewTimer !== null)
|
|
125
|
+
clearTimeout(renewTimer);
|
|
126
|
+
renewTimer = null;
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
const renew = async () => {
|
|
131
|
+
if (closed || renewalInFlight)
|
|
132
|
+
return;
|
|
133
|
+
if (isSignalingOpen(acceptor.signaling)) {
|
|
134
|
+
scheduleRenewal();
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
renewalInFlight = true;
|
|
138
|
+
try {
|
|
139
|
+
const nextTicket = await requestTicket();
|
|
140
|
+
const previous = acceptor;
|
|
141
|
+
ticket = nextTicket;
|
|
142
|
+
acceptor = await createAcceptor(nextTicket);
|
|
143
|
+
await previous.close();
|
|
144
|
+
scheduleRenewal();
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
if (!closed) {
|
|
148
|
+
renewTimer = setTimeout(() => { void renew(); }, 5_000);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
finally {
|
|
152
|
+
renewalInFlight = false;
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
scheduleRenewal();
|
|
156
|
+
options.resources?.add(() => runtimeClose());
|
|
157
|
+
async function createAcceptor(currentTicket) {
|
|
158
|
+
// acceptWebRtcHost 负责等待 registered;这里必须返回尚未消费注册事件的原始 socket。
|
|
159
|
+
const socketFactory = options.signalingSocketFactory ?? createRawHostSignalingSocket;
|
|
160
|
+
return acceptWebRtcHost({
|
|
161
|
+
signalingTicket: currentTicket,
|
|
162
|
+
signalingSocketFactory: socketFactory,
|
|
163
|
+
peerConnectionFactory: options.peerConnectionFactory ?? createWeriftPeerConnectionFactory(identity),
|
|
164
|
+
channelLabel: CODINGNS_TUNNEL_DATA_CHANNEL_LABEL,
|
|
165
|
+
debug,
|
|
166
|
+
onConnection: (session) => {
|
|
167
|
+
if (!session.carrier)
|
|
168
|
+
return;
|
|
169
|
+
const gateway = new DshGateway({
|
|
170
|
+
carrier: session.carrier,
|
|
171
|
+
generation: options.generation ?? '1',
|
|
172
|
+
hostScope: { hostId: options.hostId ?? bindingId, kind: 'local' },
|
|
173
|
+
...(options.gatewayFeatures === undefined ? {} : { features: options.gatewayFeatures }),
|
|
174
|
+
...(options.dshVersion === undefined ? {} : { dshVersion: options.dshVersion }),
|
|
175
|
+
...(options.gatewayRegistry === undefined ? {} : { registry: options.gatewayRegistry }),
|
|
176
|
+
debug,
|
|
177
|
+
});
|
|
178
|
+
gateway.start();
|
|
179
|
+
gateways.set(session.sessionId, gateway);
|
|
180
|
+
void options.onSession?.({
|
|
181
|
+
sessionId: session.sessionId,
|
|
182
|
+
peerConnection: session.peerConnection,
|
|
183
|
+
get carrier() { return session.carrier; },
|
|
184
|
+
close: async () => { await gateway.close(); await session.close(); },
|
|
185
|
+
tunnelDomain: currentTicket.tunnelDomain,
|
|
186
|
+
gateway,
|
|
187
|
+
});
|
|
188
|
+
},
|
|
189
|
+
onSessionClosed: async (sessionId) => {
|
|
190
|
+
const gateway = gateways.get(sessionId);
|
|
191
|
+
gateways.delete(sessionId);
|
|
192
|
+
await gateway?.close();
|
|
193
|
+
},
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
async function runtimeClose() {
|
|
197
|
+
if (closed)
|
|
198
|
+
return;
|
|
199
|
+
closed = true;
|
|
200
|
+
if (runtimeKey !== null && activeRelayRuntimes.get(runtimeKey) === registration)
|
|
201
|
+
activeRelayRuntimes.delete(runtimeKey);
|
|
202
|
+
if (renewTimer !== null)
|
|
203
|
+
clearTimeout(renewTimer);
|
|
204
|
+
renewTimer = null;
|
|
205
|
+
await acceptor.close();
|
|
206
|
+
for (const gateway of gateways.values())
|
|
207
|
+
await gateway.close();
|
|
208
|
+
gateways.clear();
|
|
209
|
+
}
|
|
210
|
+
const registration = { close: runtimeClose };
|
|
211
|
+
if (runtimeKey !== null)
|
|
212
|
+
activeRelayRuntimes.set(runtimeKey, registration);
|
|
213
|
+
return {
|
|
214
|
+
identity,
|
|
215
|
+
get ticket() { return ticket; },
|
|
216
|
+
get acceptor() { return acceptor; },
|
|
217
|
+
get sessions() { return acceptor.sessions; },
|
|
218
|
+
close: runtimeClose,
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
function isSignalingOpen(socket) {
|
|
222
|
+
if (!isRecord(socket) || typeof socket.readyState !== 'number')
|
|
223
|
+
return true;
|
|
224
|
+
return socket.readyState === 1;
|
|
225
|
+
}
|
|
226
|
+
/** 为 Host answerer 创建 werift PeerConnection,并适配到 transport 的注入接口。 */
|
|
227
|
+
export function createWeriftPeerConnectionFactory(identity) {
|
|
228
|
+
return ({ iceServers, iceTransportPolicy }) => {
|
|
229
|
+
const certificate = identity ? new RTCCertificate(identity.privateKeyPem, identity.certPem, identity.signatureHash) : undefined;
|
|
230
|
+
const peer = new RTCPeerConnection({ iceServers, iceTransportPolicy, ...(certificate ? { certificates: [certificate] } : {}) });
|
|
231
|
+
const adapted = {
|
|
232
|
+
get connectionState() { return peer.connectionState; },
|
|
233
|
+
get iceConnectionState() { return peer.iceConnectionState; },
|
|
234
|
+
get onicecandidate() { return peer.onicecandidate; },
|
|
235
|
+
set onicecandidate(value) { peer.onicecandidate = value; },
|
|
236
|
+
get ondatachannel() { return peer.ondatachannel; },
|
|
237
|
+
set ondatachannel(value) { peer.ondatachannel = value; },
|
|
238
|
+
addEventListener: (type, listener) => { peer.addEventListener(type, listener); },
|
|
239
|
+
removeEventListener: (type, listener) => { peer.removeEventListener(type, listener); },
|
|
240
|
+
createAnswer: async () => {
|
|
241
|
+
const answer = await peer.createAnswer();
|
|
242
|
+
return { type: 'answer', sdp: answer.sdp };
|
|
243
|
+
},
|
|
244
|
+
setRemoteDescription: (description) => peer.setRemoteDescription(description),
|
|
245
|
+
setLocalDescription: (description) => peer.setLocalDescription(description).then(() => undefined),
|
|
246
|
+
addIceCandidate: (candidate) => peer.addIceCandidate(candidate),
|
|
247
|
+
close: () => { void peer.close(); },
|
|
248
|
+
};
|
|
249
|
+
return adapted;
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
/** 建立 Host 信令并等待服务端 registered;registered 后每 20 秒发 ping。 */
|
|
253
|
+
export async function createRegisteredHostSignalingSocket(url, options = {}) {
|
|
254
|
+
const WebSocketCtor = globalThis.WebSocket;
|
|
255
|
+
if (!WebSocketCtor)
|
|
256
|
+
throw new Error('当前 Node 运行时没有 WebSocket 实现');
|
|
257
|
+
const socket = new WebSocketCtor(url);
|
|
258
|
+
const timeoutMs = options.registrationTimeoutMs ?? 15_000;
|
|
259
|
+
const heartbeatMs = options.heartbeatIntervalMs ?? 20_000;
|
|
260
|
+
return new Promise((resolve, reject) => {
|
|
261
|
+
let timer = setTimeout(() => finish(new Error('等待 Relay registered 超时')), timeoutMs);
|
|
262
|
+
let heartbeat = null;
|
|
263
|
+
let done = false;
|
|
264
|
+
let result = null;
|
|
265
|
+
const cleanup = () => {
|
|
266
|
+
if (timer !== null)
|
|
267
|
+
clearTimeout(timer);
|
|
268
|
+
if (heartbeat !== null)
|
|
269
|
+
clearInterval(heartbeat);
|
|
270
|
+
timer = null;
|
|
271
|
+
heartbeat = null;
|
|
272
|
+
};
|
|
273
|
+
const finish = (error) => {
|
|
274
|
+
if (done)
|
|
275
|
+
return;
|
|
276
|
+
done = true;
|
|
277
|
+
cleanup();
|
|
278
|
+
if (error) {
|
|
279
|
+
try {
|
|
280
|
+
socket.close(1000, 'registration_failed');
|
|
281
|
+
}
|
|
282
|
+
catch { /* ignore */ }
|
|
283
|
+
reject(error);
|
|
284
|
+
}
|
|
285
|
+
else {
|
|
286
|
+
heartbeat = heartbeatMs > 0 ? setInterval(() => {
|
|
287
|
+
if (socket.readyState === 1)
|
|
288
|
+
socket.send(JSON.stringify({ type: 'ping', at: new Date().toISOString() }));
|
|
289
|
+
}, heartbeatMs) : null;
|
|
290
|
+
result = {
|
|
291
|
+
get readyState() { return socket.readyState; },
|
|
292
|
+
send: (data) => socket.send(data),
|
|
293
|
+
close: (code, reason) => {
|
|
294
|
+
cleanup();
|
|
295
|
+
socket.close(code, reason);
|
|
296
|
+
},
|
|
297
|
+
addEventListener: (type, listener) => socket.addEventListener(type, listener),
|
|
298
|
+
removeEventListener: (type, listener) => socket.removeEventListener(type, listener),
|
|
299
|
+
};
|
|
300
|
+
resolve(result);
|
|
301
|
+
}
|
|
302
|
+
};
|
|
303
|
+
socket.onmessage = (event) => {
|
|
304
|
+
let message;
|
|
305
|
+
try {
|
|
306
|
+
message = JSON.parse(typeof event.data === 'string' ? event.data : '');
|
|
307
|
+
}
|
|
308
|
+
catch {
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
if (isRecord(message) && message.type === 'registered')
|
|
312
|
+
finish();
|
|
313
|
+
else if (isRecord(message) && message.type === 'error')
|
|
314
|
+
finish(new Error(`${String(message.errorCode)}: ${String(message.detail)}`));
|
|
315
|
+
};
|
|
316
|
+
socket.onerror = () => {
|
|
317
|
+
if (done) {
|
|
318
|
+
cleanup();
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
finish(new Error('Relay 信令 WebSocket 连接失败'));
|
|
322
|
+
};
|
|
323
|
+
socket.onclose = () => {
|
|
324
|
+
if (done) {
|
|
325
|
+
cleanup();
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
328
|
+
finish(new Error('Relay 信令 WebSocket 已关闭'));
|
|
329
|
+
};
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
/** 默认运行时使用的原始 WebSocket 工厂,注册握手交给 acceptWebRtcHost 统一处理。 */
|
|
333
|
+
async function createRawHostSignalingSocket(url) {
|
|
334
|
+
const WebSocketCtor = globalThis.WebSocket;
|
|
335
|
+
if (!WebSocketCtor)
|
|
336
|
+
throw new Error('当前 Node 运行时没有 WebSocket 实现');
|
|
337
|
+
const socket = new WebSocketCtor(url);
|
|
338
|
+
return socket;
|
|
339
|
+
}
|
|
340
|
+
function parseIdentity(value) {
|
|
341
|
+
if (!isRecord(value) || typeof value.privateKeyPem !== 'string' || typeof value.certPem !== 'string'
|
|
342
|
+
|| typeof value.fingerprint !== 'string' || typeof value.createdAt !== 'string' || typeof value.updatedAt !== 'string'
|
|
343
|
+
|| !isRecord(value.signatureHash) || typeof value.signatureHash.signature !== 'number' || typeof value.signatureHash.hash !== 'number') {
|
|
344
|
+
throw new TypeError('DTLS identity 文件格式无效');
|
|
345
|
+
}
|
|
346
|
+
return {
|
|
347
|
+
privateKeyPem: value.privateKeyPem,
|
|
348
|
+
certPem: value.certPem,
|
|
349
|
+
fingerprint: value.fingerprint,
|
|
350
|
+
createdAt: value.createdAt,
|
|
351
|
+
updatedAt: value.updatedAt,
|
|
352
|
+
signatureHash: { signature: value.signatureHash.signature, hash: value.signatureHash.hash },
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
function isRecord(value) {
|
|
356
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
357
|
+
}
|
|
358
|
+
function isNodeError(value, code) {
|
|
359
|
+
return value instanceof Error && value.code === code;
|
|
360
|
+
}
|
|
361
|
+
//# sourceMappingURL=relay-tunnel-runtime.js.map
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import type { DshGatewayFeature } from '../transport/dsh-gateway.js';
|
|
2
|
+
import { type DshTransportDebugLogger } from '../transport/debug.js';
|
|
3
|
+
/** 远程 DSH Web 资源;正文始终使用二进制,不经 Base64。 */
|
|
4
|
+
export interface DshWebAsset {
|
|
5
|
+
readonly contentType: string;
|
|
6
|
+
readonly body: Uint8Array;
|
|
7
|
+
readonly etag?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface DshWebBoot {
|
|
10
|
+
readonly dshVersion: string;
|
|
11
|
+
readonly contentType: string;
|
|
12
|
+
readonly html: string;
|
|
13
|
+
readonly entry?: string;
|
|
14
|
+
readonly styles?: readonly string[];
|
|
15
|
+
readonly scripts?: readonly string[];
|
|
16
|
+
readonly capabilities: readonly string[];
|
|
17
|
+
}
|
|
18
|
+
export interface DshWebSession {
|
|
19
|
+
readonly sessionId: string;
|
|
20
|
+
readonly workspaceId?: string;
|
|
21
|
+
readonly dshVersion: string;
|
|
22
|
+
}
|
|
23
|
+
export interface DshWebSocketLike {
|
|
24
|
+
readonly readyState?: number;
|
|
25
|
+
send(data: string | Uint8Array): void;
|
|
26
|
+
close(code?: number, reason?: string): void;
|
|
27
|
+
addEventListener(type: 'open' | 'message' | 'close' | 'error', listener: (event: Event) => void): void;
|
|
28
|
+
removeEventListener(type: 'open' | 'message' | 'close' | 'error', listener: (event: Event) => void): void;
|
|
29
|
+
}
|
|
30
|
+
export interface DshWebRuntimeProvider {
|
|
31
|
+
openSession(input: {
|
|
32
|
+
readonly workspaceId?: string;
|
|
33
|
+
readonly sessionId?: string;
|
|
34
|
+
}): Promise<DshWebSession>;
|
|
35
|
+
getBoot(session: DshWebSession): Promise<DshWebBoot>;
|
|
36
|
+
getAsset(session: DshWebSession, path: string): Promise<DshWebAsset>;
|
|
37
|
+
getPluginManifest(session: DshWebSession): Promise<unknown>;
|
|
38
|
+
getPluginBundle(session: DshWebSession, pluginId: string, path: string): Promise<DshWebAsset>;
|
|
39
|
+
openWebSocket(session: DshWebSession, path: string): Promise<DshWebSocketLike>;
|
|
40
|
+
request?(session: DshWebSession, input: {
|
|
41
|
+
readonly path: string;
|
|
42
|
+
readonly method?: string;
|
|
43
|
+
readonly headers?: readonly [string, string][];
|
|
44
|
+
readonly body?: string;
|
|
45
|
+
}): Promise<{
|
|
46
|
+
readonly status: number;
|
|
47
|
+
readonly headers: readonly [string, string][];
|
|
48
|
+
readonly body: string;
|
|
49
|
+
}>;
|
|
50
|
+
}
|
|
51
|
+
export interface RemoteWebRuntimeFeatureOptions {
|
|
52
|
+
readonly provider: DshWebRuntimeProvider;
|
|
53
|
+
readonly maxAssetBytes?: number;
|
|
54
|
+
readonly debug?: DshTransportDebugLogger;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* 把 Host 自己的 DSH Web 暴露为 DSH Gateway 的 web 频道。
|
|
58
|
+
*
|
|
59
|
+
* 这个模块不接受任意 URL,也不把 Host 凭据传给 Client;具体本地 DSH Web
|
|
60
|
+
* 访问由 provider 完成,便于真实运行时和 Fake 测试分别注入。
|
|
61
|
+
*/
|
|
62
|
+
export declare function createRemoteWebRuntimeFeature(options: RemoteWebRuntimeFeatureOptions): DshGatewayFeature;
|
|
63
|
+
export interface LocalDshWebRuntimeProviderOptions {
|
|
64
|
+
readonly port: number;
|
|
65
|
+
readonly dshVersion: string;
|
|
66
|
+
/** DSH 官方 Web 认证入口;首次请求只用于换取 HttpOnly Cookie。 */
|
|
67
|
+
readonly authenticatedUrl?: string;
|
|
68
|
+
readonly fetcher?: typeof fetch;
|
|
69
|
+
readonly websocketFactory?: (url: string, options?: {
|
|
70
|
+
readonly headers?: Readonly<Record<string, string>>;
|
|
71
|
+
}) => DshWebSocketLike;
|
|
72
|
+
readonly bootPath?: string;
|
|
73
|
+
readonly pluginManifestPath?: string;
|
|
74
|
+
readonly allowedPathPrefixes?: readonly string[];
|
|
75
|
+
}
|
|
76
|
+
/** 访问本机 DSH Web 的默认 provider;只允许 loopback 和明确的资源路径。 */
|
|
77
|
+
export declare function createLocalDshWebRuntimeProvider(options: LocalDshWebRuntimeProviderOptions): DshWebRuntimeProvider;
|
|
78
|
+
//# sourceMappingURL=remote-web-runtime.d.ts.map
|