super-dsh 0.1.3 → 0.1.5
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 +3 -3
- package/agent-agy/cordis.patch.yml +8 -4
- package/agent-agy/dist/agent-preset-agy.d.ts +23 -43
- package/agent-agy/dist/agent-preset-agy.js +29 -166
- package/agent-agy/dist/agent.d.ts +2 -1
- package/agent-agy/dist/agent.js +3 -2
- package/agent-agy/dist/agy-sessions.d.ts +2 -1
- package/agent-agy/dist/agy-sessions.js +2 -11
- package/agent-agy/dist/index.js +13 -12
- package/agent-agy/dist/world-plugin.d.ts +2 -1
- package/agent-agy/dist/world-plugin.js +31 -51
- package/agent-agy/package.json +6 -6
- package/agent-claude/cordis.patch.yml +8 -4
- package/agent-claude/dist/agent-preset-claude.js +29 -166
- package/agent-claude/dist/agent.js +10 -10
- package/agent-claude/dist/claude-client.js +22 -3
- package/agent-claude/dist/claude-home.js +0 -8
- package/agent-claude/dist/index.js +12 -15
- package/agent-claude/dist/session-map.js +2 -5
- package/agent-claude/dist/world-plugin.js +3 -3
- package/agent-claude/package.json +9 -9
- package/agent-codex/README.md +8 -8
- package/agent-codex/cordis.patch.yml +9 -5
- package/agent-codex/dist/agent-preset-codex.js +29 -168
- package/agent-codex/dist/agent.js +17 -12
- package/agent-codex/dist/codex-store.js +0 -9
- package/agent-codex/dist/index.js +13 -16
- package/agent-codex/dist/session-map.js +2 -5
- package/agent-codex/dist/world-plugin.js +31 -51
- package/agent-codex/package.json +14 -11
- package/agent-hermes/README.md +9 -8
- package/agent-hermes/cordis.patch.yml +8 -4
- package/agent-hermes/dist/agent-preset-hermes.js +29 -168
- package/agent-hermes/dist/agent.js +33 -19
- package/agent-hermes/dist/hermes-client.js +5 -5
- package/agent-hermes/dist/hermes-store.js +2 -11
- package/agent-hermes/dist/index.js +13 -12
- package/agent-hermes/dist/world-plugin.js +31 -52
- package/agent-hermes/package.json +14 -11
- package/agent-omp/README.md +2 -2
- package/agent-omp/cordis.patch.yml +12 -7
- package/agent-omp/dist/agent-preset-omp.js +30 -169
- package/agent-omp/dist/agent.js +13 -5
- package/agent-omp/dist/index.js +12 -22
- package/agent-omp/dist/mobile/gesture.js +2 -2
- package/agent-omp/dist/mobile/zoom-guard.js +4 -4
- package/agent-omp/dist/mobile-boot.js +2 -2
- package/agent-omp/dist/omp-cli.js +1 -1
- package/agent-omp/dist/omp-disk-discovery.js +1 -1
- package/agent-omp/dist/protocol.js +1 -1
- package/agent-omp/dist/sidecar-client.js +1 -1
- package/agent-omp/dist/world-plugin.js +37 -50
- package/agent-omp/package.json +18 -14
- package/agent-omp/sidecar/main.ts +2 -2
- package/agent-pi/README.md +5 -5
- package/agent-pi/cordis.patch.yml +8 -4
- package/agent-pi/dist/agent-preset-pi.js +29 -166
- package/agent-pi/dist/agent.js +18 -12
- package/agent-pi/dist/index.js +14 -16
- package/agent-pi/dist/pi-home.js +2 -12
- package/agent-pi/dist/world-plugin.js +31 -51
- package/agent-pi/package.json +14 -11
- package/client/index.js +1994 -150
- package/cordis.patch.yml +38 -15
- package/package.json +32 -30
- package/{agent-hub → superd-hub}/cordis.patch.yml +3 -3
- package/{agent-hub → superd-hub}/dist/agent-roster.d.ts +3 -1
- package/{agent-hub → superd-hub}/dist/agent-roster.js +4 -2
- package/superd-hub/dist/carrier.d.ts +62 -0
- package/superd-hub/dist/carrier.js +213 -0
- package/superd-hub/dist/fusion-transport.d.ts +148 -0
- package/superd-hub/dist/fusion-transport.js +397 -0
- package/{agent-hub → superd-hub}/dist/gateway.d.ts +9 -4
- package/superd-hub/dist/gateway.js +44 -0
- package/superd-hub/dist/hub-route.d.ts +74 -0
- package/superd-hub/dist/hub-route.js +188 -0
- package/{agent-hub → superd-hub}/dist/index.d.ts +14 -6
- package/{agent-hub → superd-hub}/dist/index.js +14 -6
- package/{agent-hub → superd-hub}/dist/roster.d.ts +2 -2
- package/{agent-hub → superd-hub}/dist/rpc.js +1 -1
- package/{agent-hub → superd-hub}/dist/spawn-world.d.ts +27 -6
- package/superd-hub/dist/spawn-world.js +279 -0
- package/superd-hub/dist/switch-core.d.ts +630 -0
- package/superd-hub/dist/switch-core.js +734 -0
- package/superd-hub/dist/system-head.d.ts +69 -0
- package/superd-hub/dist/system-head.js +194 -0
- package/superd-hub/dist/web-trust.d.ts +112 -0
- package/superd-hub/dist/web-trust.js +126 -0
- package/superd-hub/dist/world-entry.d.ts +38 -0
- package/superd-hub/dist/world-entry.js +47 -0
- package/{agent-hub → superd-hub}/dist/world-host.d.ts +15 -20
- package/superd-hub/dist/world-host.js +65 -0
- package/{agent-hub → superd-hub}/dist/world-join.d.ts +2 -1
- package/{agent-hub → superd-hub}/dist/world-join.js +30 -50
- package/superd-hub/dist/world-mount.d.ts +82 -0
- package/superd-hub/dist/world-mount.js +105 -0
- package/{agent-hub → superd-hub}/dist/world-mux.d.ts +21 -6
- package/superd-hub/dist/world-mux.js +392 -0
- package/{agent-hub → superd-hub}/dist/world-provision.d.ts +20 -4
- package/superd-hub/dist/world-provision.js +203 -0
- package/superd-hub/dist/world-web-server.d.ts +113 -0
- package/superd-hub/dist/world-web-server.js +99 -0
- package/superd-hub/lib/client/index.js +2086 -0
- package/{agent-hub → superd-hub}/package.json +12 -7
- package/agent-agy/dist/agent-preset-projection.d.ts +0 -31
- package/agent-agy/dist/agent-preset-projection.js +0 -33
- package/agent-claude/dist/agent-preset-projection.js +0 -30
- package/agent-codex/dist/agent-preset-projection.js +0 -37
- package/agent-codex/dist/app-home.js +0 -65
- package/agent-codex/dist/spike.js +0 -46
- package/agent-hermes/dist/agent-preset-projection.js +0 -34
- package/agent-hub/dist/carrier.d.ts +0 -43
- package/agent-hub/dist/carrier.js +0 -241
- package/agent-hub/dist/client-shim.d.ts +0 -28
- package/agent-hub/dist/client-shim.js +0 -251
- package/agent-hub/dist/gateway.js +0 -18
- package/agent-hub/dist/index-pass.d.ts +0 -22
- package/agent-hub/dist/index-pass.js +0 -47
- package/agent-hub/dist/labels.d.ts +0 -45
- package/agent-hub/dist/labels.js +0 -83
- package/agent-hub/dist/spawn-world.js +0 -72
- package/agent-hub/dist/world-entry.d.ts +0 -31
- package/agent-hub/dist/world-entry.js +0 -51
- package/agent-hub/dist/world-host.js +0 -44
- package/agent-hub/dist/world-mount.d.ts +0 -52
- package/agent-hub/dist/world-mount.js +0 -52
- package/agent-hub/dist/world-mux.js +0 -224
- package/agent-hub/dist/world-provision.js +0 -122
- package/agent-hub/dist/world-web-server.d.ts +0 -162
- package/agent-hub/dist/world-web-server.js +0 -248
- package/agent-hub/lib/client/index.js +0 -242
- package/agent-omp/dist/agent-preset-projection.js +0 -36
- package/agent-omp/dist/app-home.js +0 -86
- package/agent-pi/dist/agent-preset-projection.js +0 -29
- /package/{agent-hub → superd-hub}/dist/envelope.d.ts +0 -0
- /package/{agent-hub → superd-hub}/dist/envelope.js +0 -0
- /package/{agent-hub → superd-hub}/dist/ownership.d.ts +0 -0
- /package/{agent-hub → superd-hub}/dist/ownership.js +0 -0
- /package/{agent-hub → superd-hub}/dist/roster.js +0 -0
- /package/{agent-hub → superd-hub}/dist/rpc.d.ts +0 -0
- /package/{agent-hub → superd-hub}/dist/targets.d.ts +0 -0
- /package/{agent-hub → superd-hub}/dist/targets.js +0 -0
package/cordis.patch.yml
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# super-dsh — the
|
|
1
|
+
# super-dsh — the Super D composite bundle (one `dsh plugin add` face).
|
|
2
2
|
#
|
|
3
3
|
# better-dsh shape: ONE package, components are this package's own subpath
|
|
4
4
|
# exports, so every row below is individually toggleable on the plugin page
|
|
@@ -7,34 +7,57 @@
|
|
|
7
7
|
# - super-dsh/hub the hub: selector + roster + per-world mount
|
|
8
8
|
# carrier + V5 gateway delegation (wraps the live
|
|
9
9
|
# typertGateway; upstream dispatch untouched)
|
|
10
|
-
# - super-dsh/
|
|
10
|
+
# - super-dsh/agents/<label> one world plugin per adapter (activation IS
|
|
11
11
|
# roster membership, S2) — each spawns its own
|
|
12
12
|
# zero-port sibling root, mounted under /<label>
|
|
13
13
|
# - super-dsh/join the generic hub joiner for the standalone
|
|
14
14
|
# claude adapter (R2)
|
|
15
|
+
# - super-dsh/web-trust the page-trust component (ported from
|
|
16
|
+
# better-dsh web-trust, authorities leg): the
|
|
17
|
+
# browser-side twin of the server trustedHosts
|
|
18
|
+
# fence — declares trusted page authorities so
|
|
19
|
+
# the Web UI treats a non-loopback page (Caddy
|
|
20
|
+
# domain / LAN IP) as loopback-equivalent.
|
|
21
|
+
# On/off: row `disabled: true`, or config
|
|
22
|
+
# `trustedPageAuthorities: []` (inert). Default
|
|
23
|
+
# derives from the trusted-hosts env.
|
|
15
24
|
#
|
|
16
25
|
# Profile-layer values (webserver port/host, settings path) stay in the USER's
|
|
17
26
|
# profile patch layer, never here.
|
|
18
27
|
- insert:
|
|
19
|
-
# BARE package row: subpath rows (…/
|
|
28
|
+
# BARE package row: subpath rows (…/agents/omp) are permanently not client
|
|
20
29
|
# rows in client-modules' scan (exactPackageSpecifier), so THIS row is
|
|
21
30
|
# what registers the package's client half — the sidebar selector.
|
|
22
|
-
- id:
|
|
31
|
+
- id: superd-hub
|
|
23
32
|
name: 'super-dsh'
|
|
24
|
-
- id:
|
|
25
|
-
name: 'super-dsh/
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
33
|
+
- id: superd-web-trust
|
|
34
|
+
name: 'super-dsh/web-trust'
|
|
35
|
+
# Native UI fusion transport (plan Task 3): the ctx0 page-level state atom
|
|
36
|
+
# + five call-time patches, flag-gated (SUPERD_UI_FUSION, default off).
|
|
37
|
+
# ROW ORDER IS LOAD ORDER and the row MUST stay after superd-web-trust:
|
|
38
|
+
# the trust script's non-merging `if(!window.__DSH_TRANSPORT__)` verdict
|
|
39
|
+
# must be evaluated before the fusion script could own that global
|
|
40
|
+
# (spec §3.4, hard; precedent world-web-server.ts renderIndex).
|
|
41
|
+
# On/off (Task 5 formalization): env `SUPERD_UI_FUSION` derives the
|
|
42
|
+
# schema default (off when unset); a profile layer may restate this row
|
|
43
|
+
# (same id, same name) with `config: {enabled: true|false}` to override.
|
|
44
|
+
# Off = the component registers nothing: no script, no flag global.
|
|
45
|
+
- id: superd-fusion-transport
|
|
46
|
+
name: 'super-dsh/fusion-transport'
|
|
47
|
+
- id: agent-omp
|
|
48
|
+
name: 'super-dsh/agents/omp'
|
|
49
|
+
- id: agent-codex
|
|
50
|
+
name: 'super-dsh/agents/codex'
|
|
51
|
+
- id: agent-pi
|
|
52
|
+
name: 'super-dsh/agents/pi'
|
|
53
|
+
- id: agent-hermes
|
|
54
|
+
name: 'super-dsh/agents/hermes'
|
|
55
|
+
- id: agent-agy
|
|
56
|
+
name: 'super-dsh/agents/agy'
|
|
34
57
|
# R2 (2026-09-16): the claude adapter ships STANDALONE only — its /world
|
|
35
58
|
# entry is inert. The HUB side joins it: one generic joiner row with the
|
|
36
59
|
# key; spawn/roster/mount wiring lives in super-dsh/join.
|
|
37
|
-
- id:
|
|
60
|
+
- id: superd-join-claude
|
|
38
61
|
name: 'super-dsh/join'
|
|
39
62
|
config:
|
|
40
63
|
key: claude
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "super-dsh",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.1.5",
|
|
4
|
+
"description": "Super D for the DeepSeek Harness (DSH) — one dsh plugin that mounts the superd hub (runtime selector, roster, per-runtime agents) and joins local foreign-agent runtimes (OMP, Codex, Claude, Pi, Hermes, Antigravity) into the DSH Web UI. Each runtime keeps its native home and session store; the hub only bridges.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": {
|
|
@@ -9,27 +9,29 @@
|
|
|
9
9
|
"url": "git+https://github.com/pgmi-builds/superd.git"
|
|
10
10
|
},
|
|
11
11
|
"exports": {
|
|
12
|
-
".": "./
|
|
13
|
-
"./hub": "./
|
|
14
|
-
"./join": "./
|
|
15
|
-
"./
|
|
16
|
-
"./
|
|
17
|
-
"./
|
|
18
|
-
"./
|
|
19
|
-
"./
|
|
20
|
-
"./
|
|
12
|
+
".": "./superd-hub/dist/index.js",
|
|
13
|
+
"./hub": "./superd-hub/dist/index.js",
|
|
14
|
+
"./join": "./superd-hub/dist/world-join.js",
|
|
15
|
+
"./agents/omp": "./agent-omp/dist/world-plugin.js",
|
|
16
|
+
"./agents/codex": "./agent-codex/dist/world-plugin.js",
|
|
17
|
+
"./agents/claude": "./agent-claude/dist/world-plugin.js",
|
|
18
|
+
"./agents/pi": "./agent-pi/dist/world-plugin.js",
|
|
19
|
+
"./agents/hermes": "./agent-hermes/dist/world-plugin.js",
|
|
20
|
+
"./agents/agy": "./agent-agy/dist/world-plugin.js",
|
|
21
21
|
"./client": "./client/index.js",
|
|
22
22
|
"./cordis.patch.yml": "./cordis.patch.yml",
|
|
23
|
-
"./package.json": "./package.json"
|
|
23
|
+
"./package.json": "./package.json",
|
|
24
|
+
"./web-trust": "./superd-hub/dist/web-trust.js",
|
|
25
|
+
"./fusion-transport": "./superd-hub/dist/fusion-transport.js"
|
|
24
26
|
},
|
|
25
27
|
"files": [
|
|
26
28
|
"cordis.patch.yml",
|
|
27
29
|
"client",
|
|
28
30
|
"README.md",
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"
|
|
31
|
+
"superd-hub/dist",
|
|
32
|
+
"superd-hub/lib",
|
|
33
|
+
"superd-hub/package.json",
|
|
34
|
+
"superd-hub/cordis.patch.yml",
|
|
33
35
|
"agent-omp/dist",
|
|
34
36
|
"agent-omp/package.json",
|
|
35
37
|
"agent-omp/cordis.patch.yml",
|
|
@@ -70,24 +72,24 @@
|
|
|
70
72
|
"@openai/codex-sdk": "0.154.0",
|
|
71
73
|
"bun": "^1.4.2",
|
|
72
74
|
"ws": "^8.21.0",
|
|
73
|
-
"zod": "
|
|
75
|
+
"zod": "4.4.3",
|
|
74
76
|
"@modelcontextprotocol/sdk": "^1.29.0"
|
|
75
77
|
},
|
|
76
78
|
"peerDependencies": {
|
|
77
79
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
78
|
-
"@deepseek-ai/dsh-agent": "0.1.5-
|
|
79
|
-
"@deepseek-ai/dsh-agent-presets": "0.1.5-
|
|
80
|
-
"@deepseek-ai/dsh-api-gateway": "
|
|
81
|
-
"@deepseek-ai/dsh-commands": "0.1.5-
|
|
82
|
-
"@deepseek-ai/dsh-home-paths": "0.1.5-
|
|
83
|
-
"@deepseek-ai/dsh-host-webserver": "
|
|
84
|
-
"@deepseek-ai/dsh-llm": "0.1.5-
|
|
85
|
-
"@deepseek-ai/dsh-scope": "0.1.5-
|
|
86
|
-
"@deepseek-ai/dsh-session": "0.1.5-
|
|
87
|
-
"@deepseek-ai/dsh-session-persistence": "0.1.5-
|
|
88
|
-
"@deepseek-ai/dsh-typert-protocol": "0.1.5-
|
|
89
|
-
"@deepseek-ai/dsh-user-approval": "0.1.5-
|
|
90
|
-
"@deepseek-ai/dsh-user-questions": "0.1.5-
|
|
80
|
+
"@deepseek-ai/dsh-agent": ">=0.1.5-0 <0.3.0-0",
|
|
81
|
+
"@deepseek-ai/dsh-agent-presets": ">=0.1.5-0 <0.3.0-0",
|
|
82
|
+
"@deepseek-ai/dsh-api-gateway": ">=0.1.5-0 <0.3.0-0",
|
|
83
|
+
"@deepseek-ai/dsh-commands": ">=0.1.5-0 <0.3.0-0",
|
|
84
|
+
"@deepseek-ai/dsh-home-paths": ">=0.1.5-0 <0.3.0-0",
|
|
85
|
+
"@deepseek-ai/dsh-host-webserver": ">=0.1.5-0 <0.3.0-0",
|
|
86
|
+
"@deepseek-ai/dsh-llm": ">=0.1.5-0 <0.3.0-0",
|
|
87
|
+
"@deepseek-ai/dsh-scope": ">=0.1.5-0 <0.3.0-0",
|
|
88
|
+
"@deepseek-ai/dsh-session": ">=0.1.5-0 <0.3.0-0",
|
|
89
|
+
"@deepseek-ai/dsh-session-persistence": ">=0.1.5-0 <0.3.0-0",
|
|
90
|
+
"@deepseek-ai/dsh-typert-protocol": ">=0.1.5-0 <0.3.0-0",
|
|
91
|
+
"@deepseek-ai/dsh-user-approval": ">=0.1.5-0 <0.3.0-0",
|
|
92
|
+
"@deepseek-ai/dsh-user-questions": ">=0.1.5-0 <0.3.0-0"
|
|
91
93
|
},
|
|
92
94
|
"peerDependenciesMeta": {
|
|
93
95
|
"@deepseek-ai/cordis": {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Mount the
|
|
1
|
+
# Mount the superd-hub host half BESIDE the upstream gateway.
|
|
2
2
|
# The typert-gateway row STAYS ENABLED: disabling it also removed the
|
|
3
3
|
# gateway package's client half from the browser module table (learned
|
|
4
4
|
# 2026-09-10: session-controller's client requires
|
|
@@ -8,5 +8,5 @@
|
|
|
8
8
|
# The /api/agent-runtime selector RPC face rides along (control plane,
|
|
9
9
|
# always CTX0-local).
|
|
10
10
|
- insert:
|
|
11
|
-
- id:
|
|
12
|
-
name: '@pgmi-builds/
|
|
11
|
+
- id: superd-hub
|
|
12
|
+
name: '@pgmi-builds/superd-hub'
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* /codex/ → the Codex world's mount
|
|
13
13
|
*/
|
|
14
14
|
import type { IndexInjection } from '@deepseek-ai/dsh-host-webserver';
|
|
15
|
-
/** One selectable runtime: its key, its label,
|
|
15
|
+
/** One selectable runtime: its key, its label, the path that addresses it, its machine. */
|
|
16
16
|
export interface AgentLink {
|
|
17
17
|
/** `native` for ctx0, otherwise the adapter's runtime key. */
|
|
18
18
|
key: string;
|
|
@@ -20,6 +20,8 @@ export interface AgentLink {
|
|
|
20
20
|
label: string;
|
|
21
21
|
/** Mount root, always trailing-slashed except the native `/`. */
|
|
22
22
|
path: string;
|
|
23
|
+
/** Machine the runtime runs on — the Hub UI's grouping key. */
|
|
24
|
+
machine: string;
|
|
23
25
|
}
|
|
24
26
|
/** The global this module publishes the roster under. */
|
|
25
27
|
export declare const AGENT_ROSTER_GLOBAL = "__DSH_AGENT_ROSTER__";
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { listAgents } from './roster.js';
|
|
2
2
|
import { takeHostMount } from './world-host.js';
|
|
3
|
+
/** Machine of every roster row today — the local constant; the extension point a multi-machine registry replaces. */
|
|
4
|
+
const LOCAL_MACHINE = 'local';
|
|
3
5
|
/** The native runtime's synthetic entry (no adapter plugin backs it). */
|
|
4
|
-
const NATIVE = { key: 'native', label: 'DSH', path: '/' };
|
|
6
|
+
const NATIVE = { key: 'native', label: 'DSH', path: '/', machine: LOCAL_MACHINE };
|
|
5
7
|
/** The global this module publishes the roster under. */
|
|
6
8
|
export const AGENT_ROSTER_GLOBAL = '__DSH_AGENT_ROSTER__';
|
|
7
9
|
/**
|
|
@@ -17,7 +19,7 @@ export function agentLinks() {
|
|
|
17
19
|
if (mount === undefined)
|
|
18
20
|
continue;
|
|
19
21
|
const path = mount.labelPath.endsWith('/') ? mount.labelPath : `${mount.labelPath}/`;
|
|
20
|
-
links.push({ key: agent.key, label: agent.label, path });
|
|
22
|
+
links.push({ key: agent.key, label: agent.label, path, machine: LOCAL_MACHINE });
|
|
21
23
|
}
|
|
22
24
|
return links;
|
|
23
25
|
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { type WorldRequest, type WorldResponse } from './world-web-server.js';
|
|
2
|
+
import { WorldMuxServer, type MuxFailure } from './world-mux.js';
|
|
3
|
+
/** The three-method face of a world's typertGateway service instance. */
|
|
4
|
+
export interface CarrierGatewayFace {
|
|
5
|
+
dispatchRpc(endpoint: string, payload: unknown, signal: AbortSignal): Promise<unknown>;
|
|
6
|
+
/**
|
|
7
|
+
* Streams return an async iterable (upstream face is synchronous-returning).
|
|
8
|
+
* Canonical order: (endpoint, payload, uplink, peer, signal, control) — the
|
|
9
|
+
* carrier passes no peer (ctx0's fence already authenticated the client),
|
|
10
|
+
* the mux controller's signal, and the controller itself, exactly as the
|
|
11
|
+
* native gateway's mux wires its own streams.
|
|
12
|
+
*/
|
|
13
|
+
openWireStream(endpoint: string, payload: unknown, uplink: AsyncIterable<unknown>, peer: undefined, signal: AbortSignal, control: AbortController): Promise<AsyncIterable<unknown>> | AsyncIterable<unknown>;
|
|
14
|
+
}
|
|
15
|
+
export declare function writeJson(res: WorldResponse, status: number, body: string): void;
|
|
16
|
+
/** Deps the forwarding kernel needs to answer for one world's traffic. */
|
|
17
|
+
export interface ForwardOptions {
|
|
18
|
+
/** The addressed world's gateway instance. */
|
|
19
|
+
gateway: CarrierGatewayFace;
|
|
20
|
+
/** World key addressing the world's published `/api` fetch handler. */
|
|
21
|
+
label: string;
|
|
22
|
+
/** URL prefix this carrier strips before the world sees the request (`/omp`, `/hub`). */
|
|
23
|
+
mountPath: string;
|
|
24
|
+
/** ctx0's browser-trust fence: returns an HTTP status to reject with. */
|
|
25
|
+
requestRejection?(req: unknown): number | undefined;
|
|
26
|
+
/** Max request body bytes (mirrors the connection default). */
|
|
27
|
+
maxBodyBytes?: number;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Forward one non-envelope GET/HEAD request into the owning world's shared
|
|
31
|
+
* `/api` fetch handler (exact Fetch routes first, then the gateway's RPC
|
|
32
|
+
* interceptor, then 404 — the upstream composition). The caller has already
|
|
33
|
+
* answered the ctx0 fence by the time we get here; the world's own
|
|
34
|
+
* browser-auth gate is never consulted (a different tree, a different secret).
|
|
35
|
+
*/
|
|
36
|
+
export declare function forwardWorldFetch(options: {
|
|
37
|
+
label: string;
|
|
38
|
+
mountPath: string;
|
|
39
|
+
}, req: WorldRequest, res: WorldResponse): Promise<void>;
|
|
40
|
+
/**
|
|
41
|
+
* The reusable forwarding kernel (envelope dispatch + world fetch bridge):
|
|
42
|
+
* decode the connection envelope and dispatch into the ADDRESSED world's
|
|
43
|
+
* gateway instance; non-envelope GET/HEAD traffic forwards into the world's
|
|
44
|
+
* own registered fetch routes. Parameterized by (gateway, label, mountPath)
|
|
45
|
+
* so the `/hub` route family shares this exact behavior — the demux key is
|
|
46
|
+
* the caller's business, the wire semantics live here.
|
|
47
|
+
*/
|
|
48
|
+
export declare function forwardApiCall(options: ForwardOptions, req: WorldRequest, res: WorldResponse): Promise<void>;
|
|
49
|
+
/** One WorldMuxServer bound to `gateway` — the canonical openWireStream wiring in one place. */
|
|
50
|
+
export declare function worldMuxOf(gateway: CarrierGatewayFace, options?: {
|
|
51
|
+
heartbeatIntervalMs?: number;
|
|
52
|
+
failure?: (error: unknown) => MuxFailure;
|
|
53
|
+
}): WorldMuxServer;
|
|
54
|
+
/**
|
|
55
|
+
* RETIRED with T-D (2026-09-26): the T-C `mountWorld` no-op — which itself
|
|
56
|
+
* used to register `/<label>/api`, `/<label>/open-in-app` and
|
|
57
|
+
* `/<label>/api/remote.mux` on the real webServer — is GONE from the module.
|
|
58
|
+
* The adapter world-plugins' spawn-time call sites were updated in the same
|
|
59
|
+
* round (the registerHostMount record needs no webServer and no fence; the
|
|
60
|
+
* `/hub` family reaches each world's gateway through the foreign-target
|
|
61
|
+
* table). Git history keeps the function.
|
|
62
|
+
*/
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The carrier forwarding kernel (AW-B DL1/DL5 → native UI fusion Task 2 →
|
|
3
|
+
* path-separation T-C): the wire semantics every foreign-agent entry shares.
|
|
4
|
+
*
|
|
5
|
+
* History and the T-C/T-D cuts:
|
|
6
|
+
* - The kernel — envelope dispatch ({@link forwardApiCall}), the world fetch
|
|
7
|
+
* bridge ({@link forwardWorldFetch}) and the mux construction
|
|
8
|
+
* ({@link worldMuxOf}) — is parameterized by (gateway, label, mountPath).
|
|
9
|
+
* - It used to be mounted twice: the per-label page family
|
|
10
|
+
* (`/<label>/api`, `/<label>/api/remote.mux`, `/<label>/open-in-app` —
|
|
11
|
+
* registered by the now-deleted `mountWorld`) and, since 2026-09-26, the
|
|
12
|
+
* hub-owned `/hub` family (`hub-route.ts`, demuxed by `?agent=`).
|
|
13
|
+
* - T-C (2026-09-26, user ruling "strip off the per agent url path … no need
|
|
14
|
+
* the url path fallback (we have git history)"): the per-label family is
|
|
15
|
+
* RETIRED — `/hub` is the sole foreign entry and the only remaining
|
|
16
|
+
* consumer of this kernel. The world DATA planes are untouched: the same
|
|
17
|
+
* gateway faces (dispatchRpc/openWireStream), the same WorldMuxServer, the
|
|
18
|
+
* same envelope, the same worldFetchHandlerOf lane, all reached through
|
|
19
|
+
* `/hub`.
|
|
20
|
+
* - T-D (2026-09-26, "disable their webui build"): the retired `mountWorld`
|
|
21
|
+
* no-op and the mount HTML pass re-export left the module; the carrier is
|
|
22
|
+
* the forwarding kernel alone.
|
|
23
|
+
*
|
|
24
|
+
* Nothing here reads a global: the addressed world travels with the request.
|
|
25
|
+
*/
|
|
26
|
+
import { EnvelopeError, parseClientRequest, serverError, serverResult, wireErrorOf, } from './envelope.js';
|
|
27
|
+
import { stripLabelFromUrl } from './world-web-server.js';
|
|
28
|
+
import { worldFetchHandlerOf } from './world-host.js';
|
|
29
|
+
import { WorldMuxServer } from './world-mux.js';
|
|
30
|
+
/** Default body cap, aligned with the connection service. */
|
|
31
|
+
const DEFAULT_MAX_BODY_BYTES = 1024 * 1024;
|
|
32
|
+
async function readBody(req, limit) {
|
|
33
|
+
const carrier = req;
|
|
34
|
+
const chunks = [];
|
|
35
|
+
let size = 0;
|
|
36
|
+
if (typeof carrier[Symbol.asyncIterator] === 'function') {
|
|
37
|
+
for await (const chunk of carrier) {
|
|
38
|
+
const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk));
|
|
39
|
+
size += buf.byteLength;
|
|
40
|
+
if (size > limit)
|
|
41
|
+
throw new EnvelopeError({ code: 'gateway/bad-request', message: 'request body too large' });
|
|
42
|
+
chunks.push(buf);
|
|
43
|
+
}
|
|
44
|
+
return Buffer.concat(chunks).toString('utf8');
|
|
45
|
+
}
|
|
46
|
+
if (typeof carrier.on !== 'function')
|
|
47
|
+
return '';
|
|
48
|
+
return await new Promise((resolve, reject) => {
|
|
49
|
+
carrier.on?.('data', (chunk) => {
|
|
50
|
+
const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk ?? ''));
|
|
51
|
+
size += buf.byteLength;
|
|
52
|
+
if (size > limit) {
|
|
53
|
+
reject(new EnvelopeError({ code: 'gateway/bad-request', message: 'request body too large' }));
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
chunks.push(buf);
|
|
57
|
+
});
|
|
58
|
+
carrier.on?.('end', () => resolve(Buffer.concat(chunks).toString('utf8')));
|
|
59
|
+
carrier.on?.('error', (error) => reject(error instanceof Error ? error : new Error(String(error))));
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
export function writeJson(res, status, body) {
|
|
63
|
+
const carrier = res;
|
|
64
|
+
carrier.writeHead?.(status, { 'content-type': 'application/json' });
|
|
65
|
+
res.end(body);
|
|
66
|
+
}
|
|
67
|
+
/** Write a plain-text answer (the shape upstream's own 404/413 answers use). */
|
|
68
|
+
function writeText(res, status, body) {
|
|
69
|
+
const carrier = res;
|
|
70
|
+
carrier.writeHead?.(status, { 'content-type': 'text/plain; charset=utf-8' });
|
|
71
|
+
res.end(body);
|
|
72
|
+
}
|
|
73
|
+
const forwardsFetchMethod = (req) => {
|
|
74
|
+
const method = req.method;
|
|
75
|
+
return method === 'GET' || method === 'HEAD';
|
|
76
|
+
};
|
|
77
|
+
/**
|
|
78
|
+
* Forward one non-envelope GET/HEAD request into the owning world's shared
|
|
79
|
+
* `/api` fetch handler (exact Fetch routes first, then the gateway's RPC
|
|
80
|
+
* interceptor, then 404 — the upstream composition). The caller has already
|
|
81
|
+
* answered the ctx0 fence by the time we get here; the world's own
|
|
82
|
+
* browser-auth gate is never consulted (a different tree, a different secret).
|
|
83
|
+
*/
|
|
84
|
+
export async function forwardWorldFetch(options, req, res) {
|
|
85
|
+
const worldFetch = worldFetchHandlerOf(options.label);
|
|
86
|
+
if (worldFetch === undefined) {
|
|
87
|
+
writeText(res, 404, 'not found');
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
const method = (req.method ?? 'GET');
|
|
91
|
+
const resCarrier = res;
|
|
92
|
+
// Client-disconnect detection rides the response (same reason as the
|
|
93
|
+
// upstream node:http bridge: the request 'close' fires as soon as a
|
|
94
|
+
// bodyless GET is consumed).
|
|
95
|
+
const abort = new AbortController();
|
|
96
|
+
const onClose = () => {
|
|
97
|
+
if (resCarrier.writableEnded !== true)
|
|
98
|
+
abort.abort();
|
|
99
|
+
};
|
|
100
|
+
resCarrier.once?.('close', onClose);
|
|
101
|
+
let headersSent = false;
|
|
102
|
+
try {
|
|
103
|
+
const headers = {};
|
|
104
|
+
for (const [name, value] of Object.entries(req.headers ?? {})) {
|
|
105
|
+
if (typeof value === 'string')
|
|
106
|
+
headers[name.toLowerCase()] = value;
|
|
107
|
+
}
|
|
108
|
+
// The world route owns the world-relative URL: strip the mount prefix,
|
|
109
|
+
// keep the query (the session-export route reads it from searchParams).
|
|
110
|
+
const request = new Request(new URL(stripLabelFromUrl(req.url, options.mountPath), 'http://dsh.internal'), { method, headers, signal: abort.signal });
|
|
111
|
+
const response = await worldFetch.fetch(request);
|
|
112
|
+
res.writeHead(response.status, Object.fromEntries(response.headers.entries()));
|
|
113
|
+
headersSent = true;
|
|
114
|
+
if (response.body === null) {
|
|
115
|
+
res.end();
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
for await (const chunk of response.body) {
|
|
119
|
+
// Backpressure: wait for drain instead of buffering unboundedly; a
|
|
120
|
+
// socket close resolves the wait and the aborted signal ends the stream.
|
|
121
|
+
if (resCarrier.write?.(chunk) === false && typeof resCarrier.once === 'function') {
|
|
122
|
+
await new Promise((resolve) => {
|
|
123
|
+
const done = () => {
|
|
124
|
+
resCarrier.off?.('drain', done);
|
|
125
|
+
resCarrier.off?.('close', done);
|
|
126
|
+
resolve();
|
|
127
|
+
};
|
|
128
|
+
resCarrier.once?.('drain', done);
|
|
129
|
+
resCarrier.once?.('close', done);
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
res.end();
|
|
134
|
+
}
|
|
135
|
+
catch {
|
|
136
|
+
// The world route owns its statuses; only carrier-level faults land here.
|
|
137
|
+
if (!headersSent)
|
|
138
|
+
writeText(res, 500, 'carrier fetch bridge failure');
|
|
139
|
+
else
|
|
140
|
+
resCarrier.destroy?.();
|
|
141
|
+
}
|
|
142
|
+
finally {
|
|
143
|
+
resCarrier.off?.('close', onClose);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* The reusable forwarding kernel (envelope dispatch + world fetch bridge):
|
|
148
|
+
* decode the connection envelope and dispatch into the ADDRESSED world's
|
|
149
|
+
* gateway instance; non-envelope GET/HEAD traffic forwards into the world's
|
|
150
|
+
* own registered fetch routes. Parameterized by (gateway, label, mountPath)
|
|
151
|
+
* so the `/hub` route family shares this exact behavior — the demux key is
|
|
152
|
+
* the caller's business, the wire semantics live here.
|
|
153
|
+
*/
|
|
154
|
+
export async function forwardApiCall(options, req, res) {
|
|
155
|
+
const maxBody = options.maxBodyBytes ?? DEFAULT_MAX_BODY_BYTES;
|
|
156
|
+
const rejection = options.requestRejection?.(req);
|
|
157
|
+
if (rejection !== undefined) {
|
|
158
|
+
writeJson(res, rejection, JSON.stringify({ error: rejection === 401 ? 'unauthorized' : 'forbidden' }));
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
let rpcId = 'invalid-request';
|
|
162
|
+
try {
|
|
163
|
+
const text = await readBody(req, maxBody);
|
|
164
|
+
let envelope;
|
|
165
|
+
try {
|
|
166
|
+
envelope = parseClientRequest(text);
|
|
167
|
+
}
|
|
168
|
+
catch (error) {
|
|
169
|
+
// Non-envelope GET/HEAD traffic on the shared mount prefix belongs to
|
|
170
|
+
// the world's own registered fetch routes; envelopes (and every other
|
|
171
|
+
// method) keep the transport-level 400 below.
|
|
172
|
+
if (error instanceof EnvelopeError && forwardsFetchMethod(req)) {
|
|
173
|
+
await forwardWorldFetch(options, req, res);
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
throw error;
|
|
177
|
+
}
|
|
178
|
+
rpcId = envelope.rpcId;
|
|
179
|
+
const controller = new AbortController();
|
|
180
|
+
const result = await options.gateway.dispatchRpc(envelope.method, envelope.payload, controller.signal);
|
|
181
|
+
// The gateway already returns a Result (`{ok:true,value}` | `{ok:false,error}`),
|
|
182
|
+
// which is exactly the server-response's `result` field.
|
|
183
|
+
writeJson(res, 200, serverResult(rpcId, result));
|
|
184
|
+
}
|
|
185
|
+
catch (error) {
|
|
186
|
+
const wire = wireErrorOf(error);
|
|
187
|
+
// Envelope-level failures are transport-level 400s; dispatch failures are
|
|
188
|
+
// business results carried inside a 200 server-response (upstream shape).
|
|
189
|
+
if (error instanceof EnvelopeError) {
|
|
190
|
+
writeJson(res, 400, serverError(rpcId, wire));
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
writeJson(res, 200, serverError(rpcId, wire));
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
/** One WorldMuxServer bound to `gateway` — the canonical openWireStream wiring in one place. */
|
|
197
|
+
export function worldMuxOf(gateway, options) {
|
|
198
|
+
return new WorldMuxServer((endpoint, payload, uplink, control) => Promise.resolve(gateway.openWireStream(endpoint, payload, uplink, undefined, control.signal, control)), {
|
|
199
|
+
...(options?.heartbeatIntervalMs === undefined ? {} : { heartbeatIntervalMs: options.heartbeatIntervalMs }),
|
|
200
|
+
...(options?.failure === undefined ? {} : { failure: options.failure }),
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* RETIRED with T-D (2026-09-26): the T-C `mountWorld` no-op — which itself
|
|
205
|
+
* used to register `/<label>/api`, `/<label>/open-in-app` and
|
|
206
|
+
* `/<label>/api/remote.mux` on the real webServer — is GONE from the module.
|
|
207
|
+
* The adapter world-plugins' spawn-time call sites were updated in the same
|
|
208
|
+
* round (the registerHostMount record needs no webServer and no fence; the
|
|
209
|
+
* `/hub` family reaches each world's gateway through the foreign-target
|
|
210
|
+
* table). Git history keeps the function.
|
|
211
|
+
*/
|
|
212
|
+
// The carrier is now purely the forwarding kernel: no mount-time HTML pass,
|
|
213
|
+
// no per-label registration — `/hub` (hub-route.ts) is the sole consumer.
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fusion transport (native UI fusion, plan Task 3) — the ctx0 page-level head
|
|
3
|
+
* script plus its injection component.
|
|
4
|
+
*
|
|
5
|
+
* The script installs, BEFORE any application bundle materializes:
|
|
6
|
+
* - the page-level state atom `__SUPERD_UI_STATE__`
|
|
7
|
+
* ({ get activeAgent(): 'native'|string, setAgent(label), subscribe(fn) }),
|
|
8
|
+
* initial `'native'`, never persisted (no localStorage);
|
|
9
|
+
* - five CALL-TIME patches (the atom is read at request time, never baked
|
|
10
|
+
* into a closure — after setAgent the same request expression retargets):
|
|
11
|
+
* 1. `globalThis.fetch` — while a FOREIGN agent is active, a same-origin
|
|
12
|
+
* request whose path starts with `/api` is re-rooted under `/hub`
|
|
13
|
+
* and gains exactly one `agent=<label>` param (a pre-existing agent
|
|
14
|
+
* key is replaced, never duplicated — the server demuxes repeated
|
|
15
|
+
* params to the FIRST value; other query bytes + hash preserved);
|
|
16
|
+
* 2. `WebSocket` / `EventSource` Proxy constructors + `XMLHttpRequest.open`
|
|
17
|
+
* — the same rule (the mux WS lands on `/hub/api/remote.mux`);
|
|
18
|
+
* 3. `__DSH_FILE_UPLOAD__ = { fetch }` — uploads ride patch 1 (the
|
|
19
|
+
* file-upload service reads the hook at construction, so the hook
|
|
20
|
+
* must exist before app boot);
|
|
21
|
+
* 4. `HTMLAnchorElement.prototype.click` — ONLY download anchors with a
|
|
22
|
+
* same-origin `/api` href rewrite (the narrow client-shim r2 rule);
|
|
23
|
+
* the rewrite is transient — saved around the native click and
|
|
24
|
+
* restored after, so an agent switch re-targets the same anchor;
|
|
25
|
+
* 5. `Storage.prototype` get/set/removeItem — namespace read at call
|
|
26
|
+
* time: native = no prefix, foreign = `'<label>:'`.
|
|
27
|
+
* - one control-plane exemption: `/api/agent-runtime` is NEVER rewritten —
|
|
28
|
+
* the roster always talks to ctx0, so the user can always switch back.
|
|
29
|
+
* Native mode is zero-interference: every patched face passes its exact
|
|
30
|
+
* arguments through untouched.
|
|
31
|
+
*
|
|
32
|
+
* The component's gated listener ALSO bakes `__SUPERD_UI_FUSION__ = true`
|
|
33
|
+
* into the ctx0 index (Task 4): the client half's fusion-branch
|
|
34
|
+
* discriminator, emitted by the same gate as the script so the halves never
|
|
35
|
+
* disagree (world pages never carry it and keep real hyperlinks — spec §5).
|
|
36
|
+
*
|
|
37
|
+
* Quoting discipline: the generated script contains NO double-quoted string —
|
|
38
|
+
* index-pass rewrites every DOUBLE-quoted root-absolute literal in served
|
|
39
|
+
* HTML, so all literals stay single-quoted (the client-shim precedent). The
|
|
40
|
+
* install is idempotent (per-leg guards) and best-effort (every leg is
|
|
41
|
+
* individually guarded; a failure disables that leg only).
|
|
42
|
+
*
|
|
43
|
+
* Injection (the web-trust emission path, ordered AFTER it — spec §3.4 hard
|
|
44
|
+
* constraint): the row is a `webserver/index-inject` head script pushed by the
|
|
45
|
+
* `superd-fusion-transport` component, composed through the composite row
|
|
46
|
+
* `super-dsh/fusion-transport` positioned after `super-dsh/web-trust`. Both
|
|
47
|
+
* components defer their listener registration behind `inject(['webServer'])`,
|
|
48
|
+
* so cordis's FIFO effect order guarantees trust pushes first and fusion
|
|
49
|
+
* pushes last — the non-merging `if(!window.__DSH_TRANSPORT__)` verdict in the
|
|
50
|
+
* trust script is always evaluated before anything could own that global.
|
|
51
|
+
* Flag gate (minimal, Task 5 formalizes the config face): row config
|
|
52
|
+
* `enabled`, defaulting OFF from the `SUPERD_UI_FUSION` env — while the flag
|
|
53
|
+
* is off the component stays dormant and injects no row at all.
|
|
54
|
+
*
|
|
55
|
+
* @module @pgmi-builds/superd-hub/fusion-transport
|
|
56
|
+
*/
|
|
57
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
58
|
+
import z from '@deepseek-ai/schemastery';
|
|
59
|
+
/**
|
|
60
|
+
* Render the page-level fusion transport as a classic script (head injection).
|
|
61
|
+
* Pure and constant: the active label is state, never a baked literal, so the
|
|
62
|
+
* script takes no arguments. All string literals are single-quoted (see the
|
|
63
|
+
* module doc block).
|
|
64
|
+
* @returns JavaScript source.
|
|
65
|
+
*/
|
|
66
|
+
export declare function renderFusionTransport(): string;
|
|
67
|
+
/** The env name the minimal Task-3 gate reads; Task 5 builds the config face on it. */
|
|
68
|
+
export declare const FUSION_FLAG_ENV = "SUPERD_UI_FUSION";
|
|
69
|
+
/**
|
|
70
|
+
* The page global the ctx0 index carries when the gate is on: the client
|
|
71
|
+
* half's fusion-branch discriminator (the Hub UI switch surfaces read its
|
|
72
|
+
* presence to intercept agent clicks into the switch orchestration instead
|
|
73
|
+
* of letting the hyperlinks navigate — the sole switch surface since the T-B
|
|
74
|
+
* RuntimeSeat retirement; world pages never carry it, so they keep the real
|
|
75
|
+
* navigation half — spec §5 双半边). Baked by the SAME gated listener as the
|
|
76
|
+
* transport script, so the two halves can never disagree.
|
|
77
|
+
*/
|
|
78
|
+
export declare const FUSION_FLAG_GLOBAL = "__SUPERD_UI_FUSION__";
|
|
79
|
+
/**
|
|
80
|
+
* The flag's SEMANTICS after the path-separation Part 2 closeout (T-C/T-D
|
|
81
|
+
* landed; this block is the T-E closeout record) — native-ui-only, there is
|
|
82
|
+
* no fallback route anywhere:
|
|
83
|
+
*
|
|
84
|
+
* - ON: the ctx0 page fuses. The transport script arms the in-place switch
|
|
85
|
+
* and `/hub` is the sole surface for every runtime. The per-label URL
|
|
86
|
+
* family (`/<label>/` ctx0 pages, T-C) and the world web UIs (T-D) are
|
|
87
|
+
* RETIRED from the product, not gated by this flag — there is nothing
|
|
88
|
+
* navigational behind them to fall back to.
|
|
89
|
+
* - OFF: NO foreign entry exists AT ALL. The served product is the bare
|
|
90
|
+
* native UI plus the Hub panel as an information surface: the roster
|
|
91
|
+
* still lists the runtimes (the control plane is not gated), but the
|
|
92
|
+
* switch affordances render inert with the degradation hint
|
|
93
|
+
* (`switchAffordance` in switch-core) instead of dead controls — a row
|
|
94
|
+
* has no /<label>/ page to reach and the Hub UI ships no hrefs to reach
|
|
95
|
+
* one with.
|
|
96
|
+
*
|
|
97
|
+
* The shipped default stays OFF (truthy env opt-in). Moving the default ON is
|
|
98
|
+
* the user's 放行 (acceptance/release) round — a two-gate decision per repo
|
|
99
|
+
* §〇.1, never a code-side choice.
|
|
100
|
+
*
|
|
101
|
+
* Derivation: truthy spellings only (`1` / `true` / `yes` / `on`,
|
|
102
|
+
* case-insensitive, trimmed). Anything else — unset included — is OFF.
|
|
103
|
+
*/
|
|
104
|
+
export declare function deriveFusionFlag(env: string | undefined): boolean;
|
|
105
|
+
/** Row config schema face. */
|
|
106
|
+
export interface FusionConfig {
|
|
107
|
+
/** Master gate: inject the transport script on ctx0's index. Default off. */
|
|
108
|
+
enabled?: boolean;
|
|
109
|
+
}
|
|
110
|
+
/** Row config (schema-level default derives from the {@link FUSION_FLAG_ENV} env). */
|
|
111
|
+
export declare const Config: z<Schemastery.ObjectS<NoInfer<{
|
|
112
|
+
enabled: z<boolean, boolean, "defined">;
|
|
113
|
+
}>>, Schemastery.ObjectT<NoInfer<{
|
|
114
|
+
enabled: z<boolean, boolean, "defined">;
|
|
115
|
+
}>>, "plain">;
|
|
116
|
+
/** Cordis plugin name. */
|
|
117
|
+
export declare const name = "superd-fusion-transport";
|
|
118
|
+
/**
|
|
119
|
+
* No static injects: `webServer` is composed conditionally inside
|
|
120
|
+
* {@link apply}, so the row loads (dormant) in compositions without one.
|
|
121
|
+
*/
|
|
122
|
+
export declare const inject: string[];
|
|
123
|
+
/**
|
|
124
|
+
* Mount the fusion injection: one `webserver/index-inject` listener pushing
|
|
125
|
+
* the rendered head script row — the same emission path as the web-trust
|
|
126
|
+
* component, composed AFTER it (the composite row order is load order, and
|
|
127
|
+
* both components register their listeners behind `inject(['webServer'])`, so
|
|
128
|
+
* cordis's FIFO effect order pushes the fusion row last; spec §3.4) — plus
|
|
129
|
+
* the {@link FUSION_FLAG_GLOBAL} baked global row (Task 4): one gate, both
|
|
130
|
+
* halves.
|
|
131
|
+
*
|
|
132
|
+
* Flag off → the component registers nothing: no listener, no row, no script,
|
|
133
|
+
* no flag global.
|
|
134
|
+
* @param ctx - host plugin context.
|
|
135
|
+
* @param config - the row config.
|
|
136
|
+
*/
|
|
137
|
+
export declare function apply(ctx: Context, config: FusionConfig | undefined): void;
|
|
138
|
+
declare const _default: {
|
|
139
|
+
name: string;
|
|
140
|
+
inject: string[];
|
|
141
|
+
Config: z<Schemastery.ObjectS<NoInfer<{
|
|
142
|
+
enabled: z<boolean, boolean, "defined">;
|
|
143
|
+
}>>, Schemastery.ObjectT<NoInfer<{
|
|
144
|
+
enabled: z<boolean, boolean, "defined">;
|
|
145
|
+
}>>, "plain">;
|
|
146
|
+
apply: typeof apply;
|
|
147
|
+
};
|
|
148
|
+
export default _default;
|