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.
Files changed (142) hide show
  1. package/README.md +3 -3
  2. package/agent-agy/cordis.patch.yml +8 -4
  3. package/agent-agy/dist/agent-preset-agy.d.ts +23 -43
  4. package/agent-agy/dist/agent-preset-agy.js +29 -166
  5. package/agent-agy/dist/agent.d.ts +2 -1
  6. package/agent-agy/dist/agent.js +3 -2
  7. package/agent-agy/dist/agy-sessions.d.ts +2 -1
  8. package/agent-agy/dist/agy-sessions.js +2 -11
  9. package/agent-agy/dist/index.js +13 -12
  10. package/agent-agy/dist/world-plugin.d.ts +2 -1
  11. package/agent-agy/dist/world-plugin.js +31 -51
  12. package/agent-agy/package.json +6 -6
  13. package/agent-claude/cordis.patch.yml +8 -4
  14. package/agent-claude/dist/agent-preset-claude.js +29 -166
  15. package/agent-claude/dist/agent.js +10 -10
  16. package/agent-claude/dist/claude-client.js +22 -3
  17. package/agent-claude/dist/claude-home.js +0 -8
  18. package/agent-claude/dist/index.js +12 -15
  19. package/agent-claude/dist/session-map.js +2 -5
  20. package/agent-claude/dist/world-plugin.js +3 -3
  21. package/agent-claude/package.json +9 -9
  22. package/agent-codex/README.md +8 -8
  23. package/agent-codex/cordis.patch.yml +9 -5
  24. package/agent-codex/dist/agent-preset-codex.js +29 -168
  25. package/agent-codex/dist/agent.js +17 -12
  26. package/agent-codex/dist/codex-store.js +0 -9
  27. package/agent-codex/dist/index.js +13 -16
  28. package/agent-codex/dist/session-map.js +2 -5
  29. package/agent-codex/dist/world-plugin.js +31 -51
  30. package/agent-codex/package.json +14 -11
  31. package/agent-hermes/README.md +9 -8
  32. package/agent-hermes/cordis.patch.yml +8 -4
  33. package/agent-hermes/dist/agent-preset-hermes.js +29 -168
  34. package/agent-hermes/dist/agent.js +33 -19
  35. package/agent-hermes/dist/hermes-client.js +5 -5
  36. package/agent-hermes/dist/hermes-store.js +2 -11
  37. package/agent-hermes/dist/index.js +13 -12
  38. package/agent-hermes/dist/world-plugin.js +31 -52
  39. package/agent-hermes/package.json +14 -11
  40. package/agent-omp/README.md +2 -2
  41. package/agent-omp/cordis.patch.yml +12 -7
  42. package/agent-omp/dist/agent-preset-omp.js +30 -169
  43. package/agent-omp/dist/agent.js +13 -5
  44. package/agent-omp/dist/index.js +12 -22
  45. package/agent-omp/dist/mobile/gesture.js +2 -2
  46. package/agent-omp/dist/mobile/zoom-guard.js +4 -4
  47. package/agent-omp/dist/mobile-boot.js +2 -2
  48. package/agent-omp/dist/omp-cli.js +1 -1
  49. package/agent-omp/dist/omp-disk-discovery.js +1 -1
  50. package/agent-omp/dist/protocol.js +1 -1
  51. package/agent-omp/dist/sidecar-client.js +1 -1
  52. package/agent-omp/dist/world-plugin.js +37 -50
  53. package/agent-omp/package.json +18 -14
  54. package/agent-omp/sidecar/main.ts +2 -2
  55. package/agent-pi/README.md +5 -5
  56. package/agent-pi/cordis.patch.yml +8 -4
  57. package/agent-pi/dist/agent-preset-pi.js +29 -166
  58. package/agent-pi/dist/agent.js +18 -12
  59. package/agent-pi/dist/index.js +14 -16
  60. package/agent-pi/dist/pi-home.js +2 -12
  61. package/agent-pi/dist/world-plugin.js +31 -51
  62. package/agent-pi/package.json +14 -11
  63. package/client/index.js +1994 -150
  64. package/cordis.patch.yml +38 -15
  65. package/package.json +32 -30
  66. package/{agent-hub → superd-hub}/cordis.patch.yml +3 -3
  67. package/{agent-hub → superd-hub}/dist/agent-roster.d.ts +3 -1
  68. package/{agent-hub → superd-hub}/dist/agent-roster.js +4 -2
  69. package/superd-hub/dist/carrier.d.ts +62 -0
  70. package/superd-hub/dist/carrier.js +213 -0
  71. package/superd-hub/dist/fusion-transport.d.ts +148 -0
  72. package/superd-hub/dist/fusion-transport.js +397 -0
  73. package/{agent-hub → superd-hub}/dist/gateway.d.ts +9 -4
  74. package/superd-hub/dist/gateway.js +44 -0
  75. package/superd-hub/dist/hub-route.d.ts +74 -0
  76. package/superd-hub/dist/hub-route.js +188 -0
  77. package/{agent-hub → superd-hub}/dist/index.d.ts +14 -6
  78. package/{agent-hub → superd-hub}/dist/index.js +14 -6
  79. package/{agent-hub → superd-hub}/dist/roster.d.ts +2 -2
  80. package/{agent-hub → superd-hub}/dist/rpc.js +1 -1
  81. package/{agent-hub → superd-hub}/dist/spawn-world.d.ts +27 -6
  82. package/superd-hub/dist/spawn-world.js +279 -0
  83. package/superd-hub/dist/switch-core.d.ts +630 -0
  84. package/superd-hub/dist/switch-core.js +734 -0
  85. package/superd-hub/dist/system-head.d.ts +69 -0
  86. package/superd-hub/dist/system-head.js +194 -0
  87. package/superd-hub/dist/web-trust.d.ts +112 -0
  88. package/superd-hub/dist/web-trust.js +126 -0
  89. package/superd-hub/dist/world-entry.d.ts +38 -0
  90. package/superd-hub/dist/world-entry.js +47 -0
  91. package/{agent-hub → superd-hub}/dist/world-host.d.ts +15 -20
  92. package/superd-hub/dist/world-host.js +65 -0
  93. package/{agent-hub → superd-hub}/dist/world-join.d.ts +2 -1
  94. package/{agent-hub → superd-hub}/dist/world-join.js +30 -50
  95. package/superd-hub/dist/world-mount.d.ts +82 -0
  96. package/superd-hub/dist/world-mount.js +105 -0
  97. package/{agent-hub → superd-hub}/dist/world-mux.d.ts +21 -6
  98. package/superd-hub/dist/world-mux.js +392 -0
  99. package/{agent-hub → superd-hub}/dist/world-provision.d.ts +20 -4
  100. package/superd-hub/dist/world-provision.js +203 -0
  101. package/superd-hub/dist/world-web-server.d.ts +113 -0
  102. package/superd-hub/dist/world-web-server.js +99 -0
  103. package/superd-hub/lib/client/index.js +2086 -0
  104. package/{agent-hub → superd-hub}/package.json +12 -7
  105. package/agent-agy/dist/agent-preset-projection.d.ts +0 -31
  106. package/agent-agy/dist/agent-preset-projection.js +0 -33
  107. package/agent-claude/dist/agent-preset-projection.js +0 -30
  108. package/agent-codex/dist/agent-preset-projection.js +0 -37
  109. package/agent-codex/dist/app-home.js +0 -65
  110. package/agent-codex/dist/spike.js +0 -46
  111. package/agent-hermes/dist/agent-preset-projection.js +0 -34
  112. package/agent-hub/dist/carrier.d.ts +0 -43
  113. package/agent-hub/dist/carrier.js +0 -241
  114. package/agent-hub/dist/client-shim.d.ts +0 -28
  115. package/agent-hub/dist/client-shim.js +0 -251
  116. package/agent-hub/dist/gateway.js +0 -18
  117. package/agent-hub/dist/index-pass.d.ts +0 -22
  118. package/agent-hub/dist/index-pass.js +0 -47
  119. package/agent-hub/dist/labels.d.ts +0 -45
  120. package/agent-hub/dist/labels.js +0 -83
  121. package/agent-hub/dist/spawn-world.js +0 -72
  122. package/agent-hub/dist/world-entry.d.ts +0 -31
  123. package/agent-hub/dist/world-entry.js +0 -51
  124. package/agent-hub/dist/world-host.js +0 -44
  125. package/agent-hub/dist/world-mount.d.ts +0 -52
  126. package/agent-hub/dist/world-mount.js +0 -52
  127. package/agent-hub/dist/world-mux.js +0 -224
  128. package/agent-hub/dist/world-provision.js +0 -122
  129. package/agent-hub/dist/world-web-server.d.ts +0 -162
  130. package/agent-hub/dist/world-web-server.js +0 -248
  131. package/agent-hub/lib/client/index.js +0 -242
  132. package/agent-omp/dist/agent-preset-projection.js +0 -36
  133. package/agent-omp/dist/app-home.js +0 -86
  134. package/agent-pi/dist/agent-preset-projection.js +0 -29
  135. /package/{agent-hub → superd-hub}/dist/envelope.d.ts +0 -0
  136. /package/{agent-hub → superd-hub}/dist/envelope.js +0 -0
  137. /package/{agent-hub → superd-hub}/dist/ownership.d.ts +0 -0
  138. /package/{agent-hub → superd-hub}/dist/ownership.js +0 -0
  139. /package/{agent-hub → superd-hub}/dist/roster.js +0 -0
  140. /package/{agent-hub → superd-hub}/dist/rpc.d.ts +0 -0
  141. /package/{agent-hub → superd-hub}/dist/targets.d.ts +0 -0
  142. /package/{agent-hub → superd-hub}/dist/targets.js +0 -0
package/cordis.patch.yml CHANGED
@@ -1,4 +1,4 @@
1
- # super-dsh — the Agent Worlds composite bundle (one `dsh plugin add` face).
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/world/<label> one world plugin per adapter (activation IS
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 (…/world/omp) are permanently not client
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: agent-hub
31
+ - id: superd-hub
23
32
  name: 'super-dsh'
24
- - id: aw-agent-adapter-omp
25
- name: 'super-dsh/world/omp'
26
- - id: aw-agent-adapter-codex
27
- name: 'super-dsh/world/codex'
28
- - id: aw-agent-adapter-pi
29
- name: 'super-dsh/world/pi'
30
- - id: aw-agent-adapter-hermes
31
- name: 'super-dsh/world/hermes'
32
- - id: aw-agent-adapter-agy
33
- name: 'super-dsh/world/agy'
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: aw-world-join-claude
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.3",
4
- "description": "Agent Worlds for the DeepSeek Harness (DSH) — one dsh plugin that mounts the agent hub (runtime selector, roster, per-runtime worlds) 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.",
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
- ".": "./agent-hub/dist/index.js",
13
- "./hub": "./agent-hub/dist/index.js",
14
- "./join": "./agent-hub/dist/world-join.js",
15
- "./world/omp": "./agent-omp/dist/world-plugin.js",
16
- "./world/codex": "./agent-codex/dist/world-plugin.js",
17
- "./world/claude": "./agent-claude/dist/world-plugin.js",
18
- "./world/pi": "./agent-pi/dist/world-plugin.js",
19
- "./world/hermes": "./agent-hermes/dist/world-plugin.js",
20
- "./world/agy": "./agent-agy/dist/world-plugin.js",
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
- "agent-hub/dist",
30
- "agent-hub/lib",
31
- "agent-hub/package.json",
32
- "agent-hub/cordis.patch.yml",
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": "3.25.76",
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-rc.2",
79
- "@deepseek-ai/dsh-agent-presets": "0.1.5-rc.2",
80
- "@deepseek-ai/dsh-api-gateway": "*",
81
- "@deepseek-ai/dsh-commands": "0.1.5-rc.2",
82
- "@deepseek-ai/dsh-home-paths": "0.1.5-rc.2",
83
- "@deepseek-ai/dsh-host-webserver": "*",
84
- "@deepseek-ai/dsh-llm": "0.1.5-rc.2",
85
- "@deepseek-ai/dsh-scope": "0.1.5-rc.2",
86
- "@deepseek-ai/dsh-session": "0.1.5-rc.2",
87
- "@deepseek-ai/dsh-session-persistence": "0.1.5-rc.2",
88
- "@deepseek-ai/dsh-typert-protocol": "0.1.5-rc.2",
89
- "@deepseek-ai/dsh-user-approval": "0.1.5-rc.2",
90
- "@deepseek-ai/dsh-user-questions": "0.1.5-rc.2"
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 agent-hub host half BESIDE the upstream gateway.
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: agent-hub
12
- name: '@pgmi-builds/agent-hub'
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, and the path that addresses it. */
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;