super-dsh 0.1.5 → 0.1.6

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 (35) hide show
  1. package/agent-agy/dist/agent-preset-projection.d.ts +31 -0
  2. package/agent-agy/dist/agent-preset-projection.js +33 -0
  3. package/agent-claude/dist/agent-preset-projection.js +30 -0
  4. package/agent-codex/dist/agent-preset-projection.js +37 -0
  5. package/agent-codex/dist/app-home.js +65 -0
  6. package/agent-codex/dist/spike.js +46 -0
  7. package/agent-hermes/dist/agent-preset-projection.js +34 -0
  8. package/agent-omp/dist/agent-preset-projection.js +36 -0
  9. package/agent-omp/dist/app-home.js +86 -0
  10. package/agent-pi/dist/agent-preset-projection.js +29 -0
  11. package/client/index.js +273 -93
  12. package/cordis.patch.yml +6 -5
  13. package/package.json +2 -2
  14. package/superd-hub/dist/agent-roster.d.ts +4 -0
  15. package/superd-hub/dist/agent-roster.js +2 -2
  16. package/superd-hub/dist/client-shim.d.ts +28 -0
  17. package/superd-hub/dist/client-shim.js +251 -0
  18. package/superd-hub/dist/fusion-transport.d.ts +23 -21
  19. package/superd-hub/dist/fusion-transport.js +12 -40
  20. package/superd-hub/dist/index-pass.d.ts +22 -0
  21. package/superd-hub/dist/index-pass.js +47 -0
  22. package/superd-hub/dist/index.d.ts +3 -3
  23. package/superd-hub/dist/index.js +3 -3
  24. package/superd-hub/dist/labels.d.ts +45 -0
  25. package/superd-hub/dist/labels.js +83 -0
  26. package/superd-hub/dist/roster.d.ts +4 -0
  27. package/superd-hub/dist/roster.js +9 -1
  28. package/superd-hub/dist/switch-core.d.ts +40 -0
  29. package/superd-hub/dist/switch-core.js +72 -0
  30. package/superd-hub/dist/toast-core.d.ts +43 -0
  31. package/superd-hub/dist/toast-core.js +63 -0
  32. package/superd-hub/dist/world-join.js +8 -3
  33. package/superd-hub/dist/world-mount.d.ts +27 -0
  34. package/superd-hub/dist/world-mount.js +67 -0
  35. package/superd-hub/lib/client/index.js +273 -93
package/client/index.js CHANGED
@@ -268,7 +268,9 @@ const NATIVE_LINK = {
268
268
  key: "native",
269
269
  label: "DSH",
270
270
  path: "/",
271
- machine: "local"
271
+ machine: "local",
272
+ ready: true,
273
+ failed: false
272
274
  };
273
275
  /** Labels for the read-only face's bare keys (it reports keys, not labels). */
274
276
  const FALLBACK_LABELS = {
@@ -292,7 +294,9 @@ function coerceAgents(raw) {
292
294
  key,
293
295
  label: typeof label === "string" ? label : FALLBACK_LABELS[key] ?? key,
294
296
  path,
295
- machine: typeof machine === "string" ? machine : "local"
297
+ machine: typeof machine === "string" ? machine : "local",
298
+ ready: entry.ready === true,
299
+ failed: entry.failed === true
296
300
  });
297
301
  }
298
302
  return links.length > 0 ? links : void 0;
@@ -329,7 +333,8 @@ async function fetchRoster() {
329
333
  key,
330
334
  label: FALLBACK_LABELS[key] ?? key,
331
335
  path: `/${key}/`,
332
- machine: "local"
336
+ machine: "local",
337
+ ready: key === "native"
333
338
  });
334
339
  }
335
340
  if (links.length > 0) return links;
@@ -931,10 +936,10 @@ function machineGroups(rows) {
931
936
  function createSwitchController(host, options = {}) {
932
937
  const fallbackMs = options.fallbackMs ?? SWITCH_FALLBACK_MS;
933
938
  const quietWindowMs = options.quietWindowMs ?? LANDING_QUIET_MS;
934
- let current;
939
+ let current$1;
935
940
  let armedLanding;
936
941
  return { run(label) {
937
- const prior = current;
942
+ const prior = current$1;
938
943
  return new Promise((resolve) => {
939
944
  let timer;
940
945
  let watchdog;
@@ -961,7 +966,7 @@ function createSwitchController(host, options = {}) {
961
966
  attempt.finished = true;
962
967
  host.clearTimeout(timer);
963
968
  disposer();
964
- if (current === attempt) current = void 0;
969
+ if (current$1 === attempt) current$1 = void 0;
965
970
  if (landingArmed) watchdog = host.setTimeout(() => {
966
971
  attempt.cancelLanding();
967
972
  }, fallbackMs);
@@ -974,9 +979,9 @@ function createSwitchController(host, options = {}) {
974
979
  cancelPriorLanding();
975
980
  }
976
981
  if (prior !== void 0 && !prior.finished) prior.finish();
977
- current = attempt;
982
+ current$1 = attempt;
978
983
  const revert = (reason) => {
979
- if (attempt.finished || current !== attempt) return;
984
+ if (attempt.finished || current$1 !== attempt) return;
980
985
  attempt.cancelLanding();
981
986
  try {
982
987
  host.setAgent(NATIVE_AGENT);
@@ -999,7 +1004,7 @@ function createSwitchController(host, options = {}) {
999
1004
  revert("timeout");
1000
1005
  }, fallbackMs);
1001
1006
  disposer = host.onGenerationEstablished(() => {
1002
- if (attempt.finished || current !== attempt) return;
1007
+ if (attempt.finished || current$1 !== attempt) return;
1003
1008
  attempt.finish();
1004
1009
  });
1005
1010
  landingArmed = true;
@@ -1056,6 +1061,121 @@ function createSwitchController(host, options = {}) {
1056
1061
  });
1057
1062
  } };
1058
1063
  }
1064
+ /**
1065
+ * The pure pre-flight decision. `native` always runs; an absent row (roster
1066
+ * fetch failed, or the key is not listed) also runs — the machine's roster
1067
+ * probe is the authority on unknown targets, exactly as before C1.
1068
+ */
1069
+ function decidePreFlight(label, row) {
1070
+ if (label === NATIVE_AGENT) return "run";
1071
+ if (row === void 0) return "run";
1072
+ if (row.failed === true) return "failed";
1073
+ if (row.ready !== true) return "wait";
1074
+ return "run";
1075
+ }
1076
+ /** Default bound on one readiness wait (the page never locks behind a stuck world). */
1077
+ const WAIT_BOUND_MS = 12e4;
1078
+ /** Default poll interval for one readiness wait. */
1079
+ const WAIT_POLL_MS = 1e3;
1080
+ /**
1081
+ * Build a bounded readiness waiter over injected faces. The poll re-reads
1082
+ * the roster row every {@link ReadinessWaiterOptions.pollMs}; `failed`
1083
+ * short-circuits immediately; the bound always terminates the wait.
1084
+ */
1085
+ function createReadinessWaiter(faces, options = {}) {
1086
+ const boundMs = options.boundMs ?? WAIT_BOUND_MS;
1087
+ const pollMs = options.pollMs ?? WAIT_POLL_MS;
1088
+ let pending;
1089
+ let pollHandle;
1090
+ let boundHandle;
1091
+ let settled = false;
1092
+ const settle = (outcome) => {
1093
+ if (settled) return;
1094
+ settled = true;
1095
+ if (pollHandle !== void 0) faces.clearTimeout(pollHandle);
1096
+ if (boundHandle !== void 0) faces.clearTimeout(boundHandle);
1097
+ pending?.(outcome);
1098
+ pending = void 0;
1099
+ };
1100
+ return {
1101
+ wait(label) {
1102
+ return new Promise((resolve) => {
1103
+ pending = resolve;
1104
+ boundHandle = faces.setTimeout(() => {
1105
+ settle("bound");
1106
+ }, boundMs);
1107
+ const tick = () => {
1108
+ if (settled) return;
1109
+ faces.fetchRow().then((row) => {
1110
+ if (settled) return;
1111
+ if (row?.failed === true) {
1112
+ settle("failed");
1113
+ return;
1114
+ }
1115
+ if (row?.ready === true) {
1116
+ settle("ready");
1117
+ return;
1118
+ }
1119
+ pollHandle = faces.setTimeout(tick, pollMs);
1120
+ }, () => {
1121
+ if (!settled) pollHandle = faces.setTimeout(tick, pollMs);
1122
+ });
1123
+ };
1124
+ tick();
1125
+ });
1126
+ },
1127
+ cancel() {
1128
+ settle("cancelled");
1129
+ }
1130
+ };
1131
+ }
1132
+
1133
+ //#endregion
1134
+ //#region src/toast-core.ts
1135
+ /** Failures that name what broke need a longer read than a one-liner. */
1136
+ const TOAST_DEFAULT_HOLD_MS = 6e3;
1137
+ /** The exact props the official primitive receives (pure — the unit seam). */
1138
+ function toastProps(text, options = {}) {
1139
+ const props = {
1140
+ text,
1141
+ holdMs: options.holdMs ?? TOAST_DEFAULT_HOLD_MS
1142
+ };
1143
+ if (options.tone !== void 0) props.tone = options.tone;
1144
+ return props;
1145
+ }
1146
+ let seq = 0;
1147
+ let current;
1148
+ const listeners = /* @__PURE__ */ new Set();
1149
+ function emit() {
1150
+ for (const fn of [...listeners]) try {
1151
+ fn(current);
1152
+ } catch {}
1153
+ }
1154
+ /** Fire one toast (best-effort: without a mounted owner nothing renders). */
1155
+ function showSuperdToast(text, options = {}) {
1156
+ current = {
1157
+ seq: ++seq,
1158
+ text,
1159
+ options
1160
+ };
1161
+ emit();
1162
+ }
1163
+ /** Clear a shown toast (the fade's `onDone`); stale sequences are no-ops. */
1164
+ function clearSuperdToast(done) {
1165
+ if (current === void 0 || current.seq !== done) return;
1166
+ current = void 0;
1167
+ emit();
1168
+ }
1169
+ /** Subscribe to the store (the host's effect face); returns unsubscribe. */
1170
+ function onSuperdToast(fn) {
1171
+ listeners.add(fn);
1172
+ try {
1173
+ fn(current);
1174
+ } catch {}
1175
+ return () => {
1176
+ listeners.delete(fn);
1177
+ };
1178
+ }
1059
1179
 
1060
1180
  //#endregion
1061
1181
  //#region src/client/switch.ts
@@ -1071,39 +1191,14 @@ function uiState() {
1071
1191
  if (typeof state.subscribe !== "function" || typeof state.activeAgent !== "string") return void 0;
1072
1192
  return state;
1073
1193
  }
1074
- /** How long one revert toast stays on screen. */
1075
- const TOAST_HOLD_MS = 6e3;
1076
1194
  /**
1077
- * One transient message, fixed above the sidebar footer. Self-owned
1078
- * presentation only — no read from any foreign DOM, nothing is a state input.
1195
+ * One transient message through the official `Toast` primitive (C1 task 4:
1196
+ * the platform's top-center banner — dark surface in both themes, warn icon
1197
+ * seat — rendered by the host's React tree from the Hub sidebar row's
1198
+ * always-mounted owner; see client/toast.ts).
1079
1199
  */
1080
1200
  function showToast(message) {
1081
- try {
1082
- const doc = globalThis.document;
1083
- if (doc === void 0 || doc.body === null) return;
1084
- const el = doc.createElement("div");
1085
- el.textContent = message;
1086
- el.setAttribute("style", [
1087
- "position:fixed",
1088
- "left:50%",
1089
- "bottom:64px",
1090
- "transform:translateX(-50%)",
1091
- "z-index:9999",
1092
- "max-width:80vw",
1093
- "padding:10px 14px",
1094
- "border-radius:8px",
1095
- "background:rgba(24,24,28,.94)",
1096
- "color:#ececf0",
1097
- "font:13px/1.4 system-ui,sans-serif",
1098
- "box-shadow:0 8px 24px rgba(0,0,0,.35)"
1099
- ].join(";"));
1100
- doc.body.appendChild(el);
1101
- globalThis.setTimeout(() => {
1102
- try {
1103
- el.remove();
1104
- } catch {}
1105
- }, TOAST_HOLD_MS);
1106
- } catch {}
1201
+ showSuperdToast(message);
1107
1202
  }
1108
1203
  /** The bound `switchAgent`, or `undefined` until the entry binds it. */
1109
1204
  let bound;
@@ -1211,10 +1306,63 @@ function bindSwitchAgent(deps) {
1211
1306
  * `false` means the click is swallowed, never that the anchor navigates
1212
1307
  * the fused page away (review round 1).
1213
1308
  */
1309
+ let pendingWait;
1310
+ /**
1311
+ * The Hub switch surfaces' entry point. Attempts the in-page switch for
1312
+ * `label`, gated on the target world's readiness (C1): a not-ready world
1313
+ * holds the UI on native with starting feedback and a bounded poll; a
1314
+ * failed world reports and never switches; a ready/native/unknown target
1315
+ * runs the machine (whose roster probe stays the fallback).
1316
+ * @returns `true` when the fusion switch took the click over; `false` when
1317
+ * this page is not a fusion page or the orchestration is unbound.
1318
+ * Informational only — the interception contract (`seatClickDecision`)
1319
+ * prevents navigation on every fusion-page left click regardless: a
1320
+ * `false` means the click is swallowed, never that the anchor navigates
1321
+ * the fused page away (review round 1).
1322
+ */
1214
1323
  function attemptSwitch(label) {
1215
1324
  const run = bound;
1216
1325
  if (run === void 0 || !fusionPage()) return false;
1217
- run(label).catch(() => {});
1326
+ pendingWait?.cancel();
1327
+ pendingWait = void 0;
1328
+ (async () => {
1329
+ let row;
1330
+ try {
1331
+ row = (await fetchRoster()).find((agent) => agent.key === label);
1332
+ } catch {
1333
+ row = void 0;
1334
+ }
1335
+ const decision = decidePreFlight(label, row);
1336
+ if (decision === "failed") {
1337
+ showToast(`Super D: ${label} failed to start — see the service log.`);
1338
+ return;
1339
+ }
1340
+ if (decision === "wait") {
1341
+ showToast(`Super D: ${label} is starting…`);
1342
+ const waiter = createReadinessWaiter({
1343
+ fetchRow: async () => {
1344
+ try {
1345
+ return (await fetchRoster()).find((agent) => agent.key === label);
1346
+ } catch {
1347
+ return;
1348
+ }
1349
+ },
1350
+ setTimeout: (fn, ms) => globalThis.setTimeout(fn, ms),
1351
+ clearTimeout: (handle) => globalThis.clearTimeout(handle)
1352
+ });
1353
+ pendingWait = waiter;
1354
+ const outcome = await waiter.wait(label);
1355
+ if (pendingWait === waiter) pendingWait = void 0;
1356
+ if (outcome === "ready") {
1357
+ run(label).catch(() => {});
1358
+ return;
1359
+ }
1360
+ if (outcome === "failed") showToast(`Super D: ${label} failed to start — see the service log.`);
1361
+ else if (outcome === "bound") showToast(`Super D: ${label} is still starting — try again in a moment.`);
1362
+ return;
1363
+ }
1364
+ run(label).catch(() => {});
1365
+ })();
1218
1366
  return true;
1219
1367
  }
1220
1368
 
@@ -1847,6 +1995,34 @@ function HubPage() {
1847
1995
  });
1848
1996
  }
1849
1997
 
1998
+ //#endregion
1999
+ //#region src/client/toast.ts
2000
+ /**
2001
+ * The element for one pending toast: keyed by sequence so a newer toast
2002
+ * remounts the primitive and restarts its slide-in cycle (the primitive's
2003
+ * own re-show contract).
2004
+ */
2005
+ function superdToastElement(toast) {
2006
+ return react.createElement(__deepseek_ai_dsh_client_ui_primitives.Toast, {
2007
+ key: toast.seq,
2008
+ ...toastProps(toast.text, toast.options),
2009
+ onDone: () => {
2010
+ clearSuperdToast(toast.seq);
2011
+ }
2012
+ });
2013
+ }
2014
+ /**
2015
+ * The always-mounted owner: subscribes to the store and renders the current
2016
+ * toast (nothing while the store is empty). Mounted inside the Hub sidebar
2017
+ * row — the primitive's body portal places the banner top-center regardless
2018
+ * of where the owner sits.
2019
+ */
2020
+ function SuperdToastHost() {
2021
+ const [toast, setToast] = react.useState(void 0);
2022
+ react.useEffect(() => onSuperdToast(setToast), []);
2023
+ return toast === void 0 ? null : superdToastElement(toast);
2024
+ }
2025
+
1850
2026
  //#endregion
1851
2027
  //#region src/client/HubPanelIcon.tsx
1852
2028
  /** Runtime-mark edge inside the selector, and the chevron's own default edge. */
@@ -1986,61 +2162,65 @@ function HubPanelIcon({ size }) {
1986
2162
  alignItems: "center",
1987
2163
  justifyContent: "center"
1988
2164
  },
1989
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(HubGlyph, { size }), wide && box !== null && switchUi.available && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__deepseek_ai_dsh_client_ui_primitives.Menu, {
1990
- open,
1991
- onClose: () => {
1992
- setOpen(false);
1993
- },
1994
- items,
1995
- selectedIds: activeKey === void 0 ? [] : [activeKey],
1996
- onSelect: select,
1997
- dense: true,
1998
- portal: true,
1999
- align: "end",
2000
- getAnchorRect: anchorRect,
2001
- anchor: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
2002
- ref: selectorRef,
2003
- role: "button",
2004
- tabIndex: 0,
2005
- "aria-label": "Agent selector",
2006
- "aria-haspopup": "menu",
2007
- "aria-expanded": open,
2008
- title: activeLabel === void 0 ? "Agent selector" : `Agent selector: ${activeLabel}`,
2009
- style: {
2010
- position: "fixed",
2011
- left: box.right - ROW_INSET - selectorWidth,
2012
- top: box.top + (box.bottom - box.top) / 2,
2013
- transform: "translateY(-50%)",
2014
- display: "inline-flex",
2015
- alignItems: "center",
2016
- justifyContent: "center",
2017
- gap: SELECTOR_GAP,
2018
- boxSizing: "border-box",
2019
- width: selectorWidth,
2020
- height: SELECTOR_HEIGHT,
2021
- padding: `0 ${SELECTOR_PAD}px`,
2022
- borderRadius: 16,
2023
- background: hover || open ? "var(--dsw-alias-interactive-bg-hover)" : "transparent",
2024
- color: "var(--dsw-alias-label-caption)",
2025
- cursor: "pointer",
2026
- zIndex: 50
2027
- },
2028
- onMouseEnter: () => {
2029
- setHover(true);
2030
- },
2031
- onMouseLeave: () => {
2032
- setHover(false);
2033
- },
2034
- onClick: toggle,
2035
- onKeyDown: (event) => {
2036
- if (event.key === "Enter" || event.key === " ") toggle(event);
2165
+ children: [
2166
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(HubGlyph, { size }),
2167
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SuperdToastHost, {}),
2168
+ wide && box !== null && switchUi.available && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__deepseek_ai_dsh_client_ui_primitives.Menu, {
2169
+ open,
2170
+ onClose: () => {
2171
+ setOpen(false);
2037
2172
  },
2038
- children: [activeKey !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RuntimeMark, {
2039
- agentKey: activeKey,
2040
- size: MARK_SIZE
2041
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutlineRegular, { size: CHEVRON_SIZE })]
2173
+ items,
2174
+ selectedIds: activeKey === void 0 ? [] : [activeKey],
2175
+ onSelect: select,
2176
+ dense: true,
2177
+ portal: true,
2178
+ align: "end",
2179
+ getAnchorRect: anchorRect,
2180
+ anchor: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
2181
+ ref: selectorRef,
2182
+ role: "button",
2183
+ tabIndex: 0,
2184
+ "aria-label": "Agent selector",
2185
+ "aria-haspopup": "menu",
2186
+ "aria-expanded": open,
2187
+ title: activeLabel === void 0 ? "Agent selector" : `Agent selector: ${activeLabel}`,
2188
+ style: {
2189
+ position: "fixed",
2190
+ left: box.right - ROW_INSET - selectorWidth,
2191
+ top: box.top + (box.bottom - box.top) / 2,
2192
+ transform: "translateY(-50%)",
2193
+ display: "inline-flex",
2194
+ alignItems: "center",
2195
+ justifyContent: "center",
2196
+ gap: SELECTOR_GAP,
2197
+ boxSizing: "border-box",
2198
+ width: selectorWidth,
2199
+ height: SELECTOR_HEIGHT,
2200
+ padding: `0 ${SELECTOR_PAD}px`,
2201
+ borderRadius: 16,
2202
+ background: hover || open ? "var(--dsw-alias-interactive-bg-hover)" : "transparent",
2203
+ color: "var(--dsw-alias-label-caption)",
2204
+ cursor: "pointer",
2205
+ zIndex: 50
2206
+ },
2207
+ onMouseEnter: () => {
2208
+ setHover(true);
2209
+ },
2210
+ onMouseLeave: () => {
2211
+ setHover(false);
2212
+ },
2213
+ onClick: toggle,
2214
+ onKeyDown: (event) => {
2215
+ if (event.key === "Enter" || event.key === " ") toggle(event);
2216
+ },
2217
+ children: [activeKey !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RuntimeMark, {
2218
+ agentKey: activeKey,
2219
+ size: MARK_SIZE
2220
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutlineRegular, { size: CHEVRON_SIZE })]
2221
+ })
2042
2222
  })
2043
- })]
2223
+ ]
2044
2224
  });
2045
2225
  }
2046
2226
 
package/cordis.patch.yml CHANGED
@@ -33,15 +33,16 @@
33
33
  - id: superd-web-trust
34
34
  name: 'super-dsh/web-trust'
35
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).
36
+ # + five call-time patches. Composing this row IS the switch — there is no
37
+ # environment variable in the decision (2026-09-27 user ruling: a release
38
+ # gate living in an env var is deployment state no patch layer can see).
37
39
  # ROW ORDER IS LOAD ORDER and the row MUST stay after superd-web-trust:
38
40
  # the trust script's non-merging `if(!window.__DSH_TRANSPORT__)` verdict
39
41
  # must be evaluated before the fusion script could own that global
40
42
  # (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.
43
+ # To turn the fused surface off: restate this row (same id, same name) with
44
+ # `config: {enabled: false}` or `disabled: true`, or drop it from the
45
+ # composition. Off = the component registers nothing: no script, no global.
45
46
  - id: superd-fusion-transport
46
47
  name: 'super-dsh/fusion-transport'
47
48
  - id: agent-omp
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "super-dsh",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
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": {
8
8
  "type": "git",
9
- "url": "git+https://github.com/pgmi-builds/superd.git"
9
+ "url": "git+https://github.com/pgmi-builds/super-dsh.git"
10
10
  },
11
11
  "exports": {
12
12
  ".": "./superd-hub/dist/index.js",
@@ -22,6 +22,10 @@ export interface AgentLink {
22
22
  path: string;
23
23
  /** Machine the runtime runs on — the Hub UI's grouping key. */
24
24
  machine: string;
25
+ /** Whether the world's data plane is up (spawn resolved). Native is always ready. */
26
+ ready: boolean;
27
+ /** Whether the world's spawn REJECTED (mount stays for diagnosis). */
28
+ failed: boolean;
25
29
  }
26
30
  /** The global this module publishes the roster under. */
27
31
  export declare const AGENT_ROSTER_GLOBAL = "__DSH_AGENT_ROSTER__";
@@ -3,7 +3,7 @@ import { takeHostMount } from './world-host.js';
3
3
  /** Machine of every roster row today — the local constant; the extension point a multi-machine registry replaces. */
4
4
  const LOCAL_MACHINE = 'local';
5
5
  /** The native runtime's synthetic entry (no adapter plugin backs it). */
6
- const NATIVE = { key: 'native', label: 'DSH', path: '/', machine: LOCAL_MACHINE };
6
+ const NATIVE = { key: 'native', label: 'DSH', path: '/', machine: LOCAL_MACHINE, ready: true, failed: false };
7
7
  /** The global this module publishes the roster under. */
8
8
  export const AGENT_ROSTER_GLOBAL = '__DSH_AGENT_ROSTER__';
9
9
  /**
@@ -19,7 +19,7 @@ export function agentLinks() {
19
19
  if (mount === undefined)
20
20
  continue;
21
21
  const path = mount.labelPath.endsWith('/') ? mount.labelPath : `${mount.labelPath}/`;
22
- links.push({ key: agent.key, label: agent.label, path, machine: LOCAL_MACHINE });
22
+ links.push({ key: agent.key, label: agent.label, path, machine: LOCAL_MACHINE, ready: agent.ready === true, failed: agent.failed === true });
23
23
  }
24
24
  return links;
25
25
  }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Client mount shim (AW-B DL8).
3
+ *
4
+ * ONE head script installs every client-side break point:
5
+ * - `__DSH_TRANSPORT__.fetch` → the Connection RPC fetch (URL object input)
6
+ * - `WebSocket` / `EventSource` / `XMLHttpRequest` constructors → path rewrite
7
+ * - `__DSH_FILE_UPLOAD__` → uploads bypass the blob worker + its XHR
8
+ * - Storage.prototype get/set/remove → per-world key namespace
9
+ * - `globalThis.fetch` → global-fetch calls asking for ctx0-root `/api`
10
+ * URLs (2026-09-17 H1: upstream session-log-export resolves the GLOBAL
11
+ * fetch at call time; narrow `/api`-only rule, query + hash preserved)
12
+ * - `HTMLAnchorElement.prototype.click` → download-anchor clicks re-rooted
13
+ * (2026-09-18 H1 r2: upstream hands the UNREWRITTEN absolute URL to a
14
+ * DETACHED `<a download>` and clicks it — detached clicks never reach
15
+ * document, so a document-level listener cannot see them, and a blanket
16
+ * rewrite breaks the runtime selector's root-absolute anchors
17
+ * (live-found 2026-09-18). Narrow rule: ONLY anchors carrying a
18
+ * `download` attribute AND a same-authority root-absolute `/api` href.)
19
+ * The rule is namespace-agnostic: a same-origin root-absolute URL is re-rooted
20
+ * under the mount (`/omp`), nothing else is touched. That covers every prefix
21
+ * a plugin may declare later — no list to keep in sync.
22
+ */
23
+ /**
24
+ * Render the shim as a classic script (parser-blocking head injection).
25
+ * @param labelPath - mount root, e.g. `/omp`.
26
+ * @returns JavaScript source.
27
+ */
28
+ export declare function renderClientShim(labelPath: string): string;