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
@@ -1,248 +0,0 @@
1
- /**
2
- * Per-world virtual webServer (AW-B DL3).
3
- *
4
- * A world's plugins must be able to declare ANY path they like (`/api`,
5
- * `/plugins`, `/whatever-name-i-like`). Enumerating those namespaces in the
6
- * carrier is wrong by construction — a third-party plugin may declare a new
7
- * one at any time. So this class translates at REGISTRATION time:
8
- *
9
- * world registers { kind, path } → real registers { kind, `${labelPath}${path}` }
10
- * real receives /<label>/<path>/... → plugin handler sees /<path>/...
11
- *
12
- * Consequences:
13
- * - any declared prefix lands under the label automatically; no list;
14
- * - two worlds may both own `/api` (they become `/omp/api`, `/codex/api`);
15
- * - ctx0 only ever sees the label namespaces, so a world cannot collide with
16
- * ctx0's own routes.
17
- *
18
- * Index rows stay world-local: this instance owns its taps and emits nothing
19
- * on the shared tree (worlds run as their own cordis ROOTS, whose event buses
20
- * are isolated — probe 2026-09-16: emit on root B never reaches root A).
21
- */
22
- import { renderIndexInjections } from '@deepseek-ai/dsh-host-webserver';
23
- import { rewriteIndexHtml } from './index-pass.js';
24
- import { renderClientShim } from './client-shim.js';
25
- import { agentRosterRow } from './agent-roster.js';
26
- function translatePath(labelPath, path) {
27
- if (typeof path !== 'string' || !path.startsWith('/')) {
28
- throw new Error(`world-web-server: route path must start with "/", got ${JSON.stringify(path)}`);
29
- }
30
- return path === '/' ? labelPath : `${labelPath}${path}`;
31
- }
32
- /** Remove the mount label from `req.url`, preserving the trailing query. */
33
- export function stripLabelFromUrl(url, labelPath) {
34
- const raw = typeof url === 'string' && url !== '' ? url : '/';
35
- const queryAt = raw.indexOf('?');
36
- const path = queryAt === -1 ? raw : raw.slice(0, queryAt);
37
- const rest = queryAt === -1 ? '' : raw.slice(queryAt);
38
- if (path === labelPath)
39
- return `/${rest}`;
40
- if (path.startsWith(`${labelPath}/`))
41
- return `${path.slice(labelPath.length)}${rest}`;
42
- return raw;
43
- }
44
- /** One world's web surface, mounted under `<labelPath>`. */
45
- export class WorldWebServer {
46
- labelPath;
47
- real;
48
- options;
49
- disposers = [];
50
- taps = [];
51
- /**
52
- * @param labelPath - mount root, e.g. `/omp` (no trailing slash).
53
- * @param real - the ctx0 webServer this world's routes forward into.
54
- * @param options - world-local index row source.
55
- */
56
- constructor(labelPath, real, options = {}) {
57
- this.labelPath = labelPath;
58
- this.real = real;
59
- this.options = options;
60
- if (typeof labelPath !== 'string' || !labelPath.startsWith('/') || labelPath === '/' || labelPath.endsWith('/')) {
61
- throw new Error(`world-web-server: labelPath must start with "/" and carry no trailing slash, got ${JSON.stringify(labelPath)}`);
62
- }
63
- }
64
- /** The ctx0 listener port (read-through; the world owns no socket). */
65
- get port() {
66
- return this.real.port ?? 0;
67
- }
68
- /** The ctx0 bind host (read-through). */
69
- get host() {
70
- return this.real.host ?? '127.0.0.1';
71
- }
72
- /**
73
- * The RPC channel belongs to the HUB, not to the world: the hub's carrier
74
- * answers `/<label>/api/*` and `/<label>/api/remote.mux` with ctx0's auth
75
- * domain, so the world's own connection/gateway registrations are swallowed
76
- * here (returning a no-op disposer) instead of colliding on the real table.
77
- * Non-envelope GET/HEAD traffic on `/<label>/api` still reaches the world's
78
- * exact Fetch routes: `world-entry` publishes the world connection's shared
79
- * `/api` fetch handler through `world-host`, and the carrier forwards into
80
- * it AFTER ctx0's fence — the world's own browser-auth gate is never in the
81
- * path (a different tree, a different secret).
82
- */
83
- static hubOwned(path) {
84
- return path === '/api' || path.startsWith('/api/');
85
- }
86
- /**
87
- * Mount-side authentication for one forwarded world route.
88
- *
89
- * The world's own browser-auth gate never sees a browser: it is reached
90
- * in-ctx through this mount, and its cookie secret belongs to a different
91
- * tree (every runtime is nested with its own home). So the decision is made
92
- * here, with ctx0's connection: the same cookie that authenticated `<label>`
93
- * in ctx0 authorizes its pages and assets.
94
- */
95
- gate(handler) {
96
- return (req, ...rest) => {
97
- const res = rest[0];
98
- // false => the authorizer already answered (401, or token→cookie 303).
99
- if (res !== undefined && this.options.authorize !== undefined
100
- && !this.options.authorize(req, res))
101
- return;
102
- return handler(req, ...rest);
103
- };
104
- }
105
- /** Register a world route; the real table stores its translated path. */
106
- register(route) {
107
- if (WorldWebServer.hubOwned(route.path))
108
- return () => { };
109
- return this.track(this.real.register({
110
- kind: route.kind,
111
- path: translatePath(this.labelPath, route.path),
112
- handler: this.strip(this.gate(route.handler)),
113
- }));
114
- }
115
- /** Register a world upgrade route (verbatim exact path; hub-owned RPC paths are swallowed). */
116
- registerUpgrade(route) {
117
- if (WorldWebServer.hubOwned(route.path))
118
- return () => { };
119
- return this.track(this.real.registerUpgrade({
120
- path: translatePath(this.labelPath, route.path),
121
- handler: this.strip(route.handler),
122
- }));
123
- }
124
- /**
125
- * Claim the world's SPA fallback: the ctx0 fallback seat is already owned by
126
- * native frontend-static, so the world's fallback lives as a PREFIX route on
127
- * the mount path (`/<label>`), which also keeps it inside the label namespace.
128
- */
129
- registerFallback(handler) {
130
- // The world's index arrives HERE (its own frontend-static claims the
131
- // fallback seat), so this is the route the mount must authenticate.
132
- const gated = this.gate((req, ...rest) => handler(req, rest[0]));
133
- return this.track(this.real.register({
134
- kind: 'prefix',
135
- path: this.labelPath,
136
- handler: this.htmlRewrite(this.strip(gated)),
137
- }));
138
- }
139
- /**
140
- * Fix up HTML on its way out. Two passes belong here, in this order:
141
- *
142
- * 1. the world's own frontend-static injects `<base href="/">` AFTER
143
- * `renderIndex`, and the FIRST `<base>` wins in a document, so the mount
144
- * base is re-pinned on the bytes actually sent;
145
- * 2. the agent roster is injected LAST — its values are the mount paths of
146
- * OTHER worlds (`/`, `/omp/`, `/codex/`), which the mount pass above
147
- * would otherwise re-root under this world's label.
148
- */
149
- htmlRewrite(handler) {
150
- const labelPath = this.labelPath;
151
- return (req, ...rest) => {
152
- const res = rest[0];
153
- const originalEnd = res?.end?.bind(res);
154
- if (res !== undefined && originalEnd !== undefined) {
155
- res.end = ((chunk, ...tail) => {
156
- if (typeof chunk === 'string' || Buffer.isBuffer(chunk)) {
157
- const text = typeof chunk === 'string' ? chunk : chunk.toString('utf8');
158
- if (/<head[\s>]/i.test(text) && /<base\b/i.test(text)) {
159
- const mounted = rewriteIndexHtml(text, labelPath);
160
- // A world that composes the hub row emits its own roster row during
161
- // renderIndex — i.e. BEFORE this mount pass, so its paths were
162
- // already re-rooted. Drop every earlier copy and inject the one
163
- // this pass has just built from unrewritten values.
164
- const stale = /<script>globalThis\["__DSH_AGENT_ROSTER__"\][^<]*<\/script>/g;
165
- const cleaned = mounted.replace(stale, '');
166
- return originalEnd(renderIndexInjections(cleaned, [agentRosterRow()]), ...tail);
167
- }
168
- }
169
- return originalEnd(chunk, ...tail);
170
- });
171
- }
172
- return handler(req, ...rest);
173
- };
174
- }
175
- /** World-local raw index transform (never forwarded to ctx0's taps). */
176
- tapIndex(transform) {
177
- this.taps.push(transform);
178
- return () => {
179
- const at = this.taps.indexOf(transform);
180
- if (at !== -1)
181
- this.taps.splice(at, 1);
182
- };
183
- }
184
- /** Apply this world's taps in registration order. */
185
- applyIndexTaps(html) {
186
- let out = html;
187
- for (const transform of this.taps)
188
- out = transform(out);
189
- return out;
190
- }
191
- /** Collect this world's structured rows (supplied by the world root). */
192
- collectIndexInjections() {
193
- const table = [];
194
- this.options.onIndexInject?.(table);
195
- return table;
196
- }
197
- /**
198
- * Render the world's index: the client mount shim first (it must run before
199
- * the app entry module), then the world's rows, then its taps, then the mount
200
- * pass (base pinned at `/<label>/`, root-absolute strings re-rooted).
201
- *
202
- * The agent roster is injected LAST, after the mount pass: its values are
203
- * mount paths of OTHER worlds (`/`, `/omp/`, `/codex/`), and the pass would
204
- * happily re-root them under this world's label.
205
- */
206
- renderIndex(html) {
207
- const rows = [
208
- { kind: 'script', placement: 'head', text: renderClientShim(this.labelPath) },
209
- // No hub-invented widget here: the world composes the hub's own client
210
- // plugin (see worldMountPatches), so its selector IS the native one.
211
- ...this.collectIndexInjections(),
212
- ];
213
- const rendered = this.applyIndexTaps(renderIndexInjections(html, rows));
214
- // The roster rides the outbound pass (htmlRewrite), not this one: the mount
215
- // rewrite above would re-root other worlds' paths under this label.
216
- return rewriteIndexHtml(rendered, this.labelPath);
217
- }
218
- /** Unregister every translated route (world unloaded). */
219
- dispose() {
220
- for (const dispose of this.disposers.splice(0).reverse()) {
221
- try {
222
- dispose();
223
- }
224
- catch {
225
- // release must never throw during teardown
226
- }
227
- }
228
- this.taps.length = 0;
229
- }
230
- /** Wrap a plugin handler so it sees the world-relative URL. */
231
- strip(handler) {
232
- const labelPath = this.labelPath;
233
- return (req, ...rest) => {
234
- req.url = stripLabelFromUrl(req.url, labelPath);
235
- return handler(req, ...rest);
236
- };
237
- }
238
- track(dispose) {
239
- const wrapped = () => {
240
- const at = this.disposers.indexOf(wrapped);
241
- if (at !== -1)
242
- this.disposers.splice(at, 1);
243
- dispose();
244
- };
245
- this.disposers.push(wrapped);
246
- return wrapped;
247
- }
248
- }
@@ -1,242 +0,0 @@
1
- window.__ModuleLoader__.load({ id: "@pgmi-builds/agent-hub", factory: (require) => {
2
- var module = { exports: {} }; var exports = module.exports;
3
- //#region rolldown:runtime
4
- var __create = Object.create;
5
- var __defProp = Object.defineProperty;
6
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
7
- var __getOwnPropNames = Object.getOwnPropertyNames;
8
- var __getProtoOf = Object.getPrototypeOf;
9
- var __hasOwnProp = Object.prototype.hasOwnProperty;
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
12
- key = keys[i];
13
- if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
14
- get: ((k) => from[k]).bind(null, key),
15
- enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
16
- });
17
- }
18
- return to;
19
- };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
21
- value: mod,
22
- enumerable: true
23
- }) : target, mod));
24
-
25
- //#endregion
26
- let react = require("react");
27
- react = __toESM(react);
28
- let react_jsx_runtime = require("react/jsx-runtime");
29
- react_jsx_runtime = __toESM(react_jsx_runtime);
30
-
31
- //#region src/client/RuntimeSeat.tsx
32
- const NATIVE = {
33
- key: "native",
34
- label: "DSH",
35
- path: "/"
36
- };
37
- /** Fallback labels for the read-only face (which only reports keys). */
38
- const RUNTIME_LABELS = {
39
- native: "DSH",
40
- omp: "OMP",
41
- codex: "Codex"
42
- };
43
- function fromGlobal() {
44
- const agents = globalThis.__DSH_AGENT_ROSTER__?.agents;
45
- if (!Array.isArray(agents)) return void 0;
46
- const links = [];
47
- for (const entry of agents) {
48
- if (typeof entry !== "object" || entry === null) continue;
49
- const { key, label, path } = entry;
50
- if (typeof key !== "string" || typeof path !== "string") continue;
51
- links.push({
52
- key,
53
- label: typeof label === "string" ? label : RUNTIME_LABELS[key] ?? key,
54
- path
55
- });
56
- }
57
- return links.length > 0 ? links : void 0;
58
- }
59
- /** Normalize the current mount root: `/omp` and `/omp/` are the same page. */
60
- function currentPath() {
61
- const pathname = typeof location === "undefined" ? "/" : location.pathname;
62
- if (pathname === "" || pathname === "/") return "/";
63
- return pathname.endsWith("/") ? pathname : `${pathname}/`;
64
- }
65
- function RuntimeSeat({ wide }) {
66
- const [agents, setAgents] = react.useState(() => fromGlobal() ?? [NATIVE]);
67
- const [open, setOpen] = react.useState(false);
68
- const rootRef = react.useRef(null);
69
- react.useEffect(() => {
70
- let cancelled = false;
71
- fetch("/api/agent-runtime", { credentials: "same-origin" }).then((r) => r.ok ? r.json() : Promise.reject(/* @__PURE__ */ new Error(`HTTP ${r.status}`))).then((j) => {
72
- if (cancelled) return;
73
- if (Array.isArray(j?.agents)) {
74
- const listed = [];
75
- for (const entry of j.agents) {
76
- if (typeof entry !== "object" || entry === null) continue;
77
- const { key, label, path } = entry;
78
- if (typeof key !== "string" || typeof path !== "string") continue;
79
- listed.push({
80
- key,
81
- label: typeof label === "string" ? label : RUNTIME_LABELS[key] ?? key,
82
- path
83
- });
84
- }
85
- if (listed.length > 0) {
86
- setAgents(listed);
87
- return;
88
- }
89
- }
90
- if (!Array.isArray(j?.available)) return;
91
- const links = [];
92
- for (const key of j.available) {
93
- if (typeof key !== "string") continue;
94
- links.push(key === "native" ? NATIVE : {
95
- key,
96
- label: RUNTIME_LABELS[key] ?? key,
97
- path: `/${key}/`
98
- });
99
- }
100
- if (links.length > 0) setAgents(links);
101
- }).catch(() => {});
102
- return () => {
103
- cancelled = true;
104
- };
105
- }, []);
106
- react.useEffect(() => {
107
- if (!open) return;
108
- const onDown = (event) => {
109
- if (rootRef.current !== null && !rootRef.current.contains(event.target)) setOpen(false);
110
- };
111
- document.addEventListener("mousedown", onDown);
112
- return () => document.removeEventListener("mousedown", onDown);
113
- }, [open]);
114
- const here = currentPath();
115
- const active = agents.find((agent) => agent.path === here) ?? NATIVE;
116
- const styleBase = {
117
- display: "flex",
118
- alignItems: "center",
119
- gap: 8,
120
- width: "100%",
121
- padding: wide ? "7px 10px" : "7px 0",
122
- justifyContent: wide ? "flex-start" : "center",
123
- border: "none",
124
- borderRadius: 8,
125
- background: "transparent",
126
- color: "inherit",
127
- font: "inherit",
128
- fontSize: 13,
129
- cursor: "pointer",
130
- position: "relative"
131
- };
132
- const styleBadge = {
133
- fontSize: 10,
134
- lineHeight: 1.4,
135
- padding: "1px 6px",
136
- borderRadius: 999,
137
- background: "color-mix(in srgb, currentColor 12%, transparent)",
138
- whiteSpace: "nowrap"
139
- };
140
- const styleMenu = {
141
- position: "absolute",
142
- bottom: "calc(100% + 6px)",
143
- left: 6,
144
- right: 6,
145
- zIndex: 40,
146
- background: "var(--dsh-surface, #26262b)",
147
- border: "1px solid color-mix(in srgb, currentColor 18%, transparent)",
148
- borderRadius: 10,
149
- boxShadow: "0 8px 24px rgba(0,0,0,.35)",
150
- overflow: "hidden"
151
- };
152
- const styleItem = (isActive) => ({
153
- display: "block",
154
- width: "100%",
155
- padding: "8px 12px",
156
- border: "none",
157
- background: isActive ? "color-mix(in srgb, currentColor 10%, transparent)" : "transparent",
158
- color: "inherit",
159
- font: "inherit",
160
- fontSize: 13,
161
- textAlign: "left",
162
- cursor: "pointer"
163
- });
164
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
165
- ref: rootRef,
166
- style: {
167
- position: "relative",
168
- width: "100%"
169
- },
170
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
171
- type: "button",
172
- style: styleBase,
173
- title: "Agent runtime — picking one opens that runtime's mount (/omp/, /codex/, …)",
174
- onClick: () => {
175
- setOpen((v) => !v);
176
- },
177
- children: wide ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
178
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
179
- "aria-hidden": true,
180
- children: "⌘"
181
- }),
182
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
183
- style: {
184
- flex: 1,
185
- textAlign: "left",
186
- whiteSpace: "nowrap",
187
- overflow: "hidden",
188
- textOverflow: "ellipsis"
189
- },
190
- children: ["Agent · ", active.label]
191
- }),
192
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
193
- style: styleBadge,
194
- children: "open"
195
- })
196
- ] }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
197
- "aria-hidden": true,
198
- children: "⌘"
199
- })
200
- }), open && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
201
- style: styleMenu,
202
- children: agents.map((agent) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
203
- href: agent.path,
204
- style: {
205
- ...styleItem(agent.path === here),
206
- textDecoration: "none"
207
- },
208
- "aria-current": agent.path === here ? "page" : void 0,
209
- onClick: () => {
210
- setOpen(false);
211
- },
212
- children: agent.path === here ? `${agent.label} ✓` : agent.label
213
- }, agent.key))
214
- })]
215
- });
216
- }
217
-
218
- //#endregion
219
- //#region src/client/index.ts
220
- /** Required services (cordis fiber inject): the slot registry. */
221
- const inject = ["slots"];
222
- /**
223
- * Mount the selector. Degrades silently when the slot service is absent (a
224
- * composition without the sidebar renders nothing — a footer action is an
225
- * optional occupant by contract).
226
- *
227
- * @param ctx - client root context.
228
- */
229
- function apply(ctx) {
230
- ctx.inject(["slots"], (raw) => {
231
- const scope = raw;
232
- scope.effect(() => scope.slots.inject("sidebar.footer.action", () => scope.slots.register({
233
- name: "sidebar.footer.action",
234
- id: "agent-runtime"
235
- }, RuntimeSeat)), "agent-hub: runtime footer action");
236
- });
237
- }
238
-
239
- //#endregion
240
- exports.apply = apply;
241
- exports.inject = inject;
242
- return module.exports; } });
@@ -1,36 +0,0 @@
1
- /**
2
- * The `agentPreset` session projection, owned by the bridge.
3
- *
4
- * Upstream registers this fold from the `dsh-agent-presets` package, which our
5
- * patch disables (OMP replaces preset composition wholesale). But the Web UI
6
- * depends on the projection regardless: the preset hero chip renders only when
7
- * `session.projectionValues.agentPreset` resolves (`presetOf` in
8
- * ui-agent-preset/seat-store.ts), and the session-header label reads it too.
9
- * Without a registrant the projection is absent for every bridge session and
10
- * both surfaces stay blank — roster or no roster (that was the "no omp mode"
11
- * bug: the roster service answered `agentPresets/list` 200, yet nothing drove
12
- * the per-session projection the chip gates on).
13
- *
14
- * Same fold as upstream (packages/preset/agent-presets/src/session.ts):
15
- * initialized from the creation header, advanced by `agent-preset/selected`
16
- * events, which this bridge already synthesizes (`"omp"`) on every session it
17
- * prepares. Registered under the provider's own fiber via
18
- * `ctx.inject(['sessionProjections'])`, so the key lives exactly as long as
19
- * the provider is mounted.
20
- */
21
- import { z } from "zod";
22
- const agentPresetSchema = z.union([z.string(), z.null()]);
23
- /** Current Session preset, initialized from its header and advanced by selection events. */
24
- export const ompAgentPresetProjection = {
25
- key: "agentPreset",
26
- stateSchema: agentPresetSchema,
27
- // omp-web is single-preset: default every session to "omp" so the header
28
- // chip resolves for scan-native (never-resumed) sessions too, instead of
29
- // only those whose log carries an `agent-preset/selected` event.
30
- init: (header) => header.agentPreset ?? "omp",
31
- apply: (state, event) => event.type === "agent-preset/selected"
32
- ? event.data.agentPreset
33
- : state,
34
- wire: { viewSchema: agentPresetSchema, view: (state) => state },
35
- stateVersion: 1,
36
- };
@@ -1,86 +0,0 @@
1
- /**
2
- * OMP runtime app home bootstrap — idempotently creates the runtime's OMP home
3
- * (`<DSH_HOME>/agents/omp/.omp`) and seeds it with the OMP config (config.yml /
4
- * mcp.json / models.yml / .env) copied once from `~/.omp/agent`. Fail-soft: any
5
- * error is reported and the host boot continues — the app home is derived state,
6
- * never a boot gate.
7
- */
8
- import { copyFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
9
- import { join } from "node:path";
10
- import { OMP_HOME, OMP_NATIVE_HOME } from "./knobs.js";
11
- /** Config files seeded into the app home from the native OMP agent dir. */
12
- export const APP_HOME_CONFIG_FILES = ["config.yml", "mcp.json", "models.yml", ".env"];
13
- /**
14
- * Comma/space separated `mcpServers` names the launcher refuses to inherit
15
- * (`AW_OMP_MCP_EXCLUDE=zai-vision`). Deployment policy lives in the launcher, so
16
- * this module never names a vendor.
17
- */
18
- export const OMP_MCP_EXCLUDE_ENV = "AW_OMP_MCP_EXCLUDE";
19
- /** Native OMP agent dir (`<OMP_NATIVE_HOME>/agent`) — the copy source. */
20
- function defaultSourceAgentDir() {
21
- return join(OMP_NATIVE_HOME, "agent");
22
- }
23
- /** Parse {@link OMP_MCP_EXCLUDE_ENV} into server names. */
24
- function excludedMcpServers() {
25
- return (process.env[OMP_MCP_EXCLUDE_ENV] ?? "")
26
- .split(/[\s,]+/)
27
- .map((name) => name.trim())
28
- .filter((name) => name !== "");
29
- }
30
- /**
31
- * Drop excluded stdio MCP servers from the app home's `mcp.json`.
32
- *
33
- * Why this exists: the native `~/.omp/agent/mcp.json` carries a `npx -y
34
- * @z_ai/mcp-server@latest` stdio server, and every spawned MCP child is a real
35
- * process (a live npx install ~200 MB) that this runtime does not need. Seeding
36
- * copies the file verbatim, so the filter runs after seeding and is idempotent:
37
- * it only rewrites the document when a listed server was actually present.
38
- */
39
- function pruneMcpServers(appHome, names, warn) {
40
- if (names.length === 0)
41
- return;
42
- const file = join(appHome, "mcp.json");
43
- if (!existsSync(file))
44
- return;
45
- const parsed = JSON.parse(readFileSync(file, "utf8"));
46
- const servers = parsed.mcpServers;
47
- if (servers === undefined || typeof servers !== "object" || servers === null)
48
- return;
49
- const removed = names.filter((name) => Object.hasOwn(servers, name));
50
- if (removed.length === 0)
51
- return;
52
- for (const name of removed)
53
- delete servers[name];
54
- writeFileSync(file, `${JSON.stringify(parsed, null, 2)}\n`);
55
- warn?.(`omp-provider: pruned MCP servers from ${file}: ${removed.join(", ")}`);
56
- }
57
- /**
58
- * Ensure the app home exists and is seeded. Never overwrites an existing file
59
- * (an already-provisioned app home wins); a missing source file is skipped.
60
- * Returns the resolved app home path.
61
- */
62
- export function ensureOmpAppHome(options = {}) {
63
- const appHome = options.appHome ?? OMP_HOME;
64
- const source = options.sourceAgentDir ?? defaultSourceAgentDir();
65
- const files = options.files ?? APP_HOME_CONFIG_FILES;
66
- try {
67
- mkdirSync(appHome, { recursive: true });
68
- for (const name of files) {
69
- const dest = join(appHome, name);
70
- if (existsSync(dest))
71
- continue;
72
- const src = join(source, name);
73
- if (!existsSync(src))
74
- continue;
75
- copyFileSync(src, dest);
76
- }
77
- // Deployment policy, data-side: a seeded/kept `mcp.json` may still carry
78
- // heavy stdio servers this runtime must not inherit (a vendor name does not
79
- // belong in adapter code, so the launcher names them here).
80
- pruneMcpServers(appHome, options.excludeMcpServers ?? excludedMcpServers(), options.warn);
81
- }
82
- catch (error) {
83
- options.warn?.(`omp-provider: app-home bootstrap failed (fail-soft): ${String(error)}`);
84
- }
85
- return appHome;
86
- }
@@ -1,29 +0,0 @@
1
- /**
2
- * The `agentPreset` session projection, owned by the adapter.
3
- *
4
- * Upstream registers this fold from the `dsh-agent-presets` package, which our
5
- * patch disables (the pi provider replaces preset composition wholesale).
6
- * But the Web UI depends on the projection regardless: the preset hero chip
7
- * renders only when `session.projectionValues.agentPreset` resolves, and the
8
- * session-header label reads it too. Without a registrant the projection is
9
- * absent for every adapter session and both surfaces stay blank (the omp
10
- * line's "no mode" bug).
11
- *
12
- * Same fold as upstream; adapter-pi is single-preset: default every session
13
- * to "pi" so the header chip resolves for scan-native (never-resumed)
14
- * sessions too. Registered under the provider's own fiber via
15
- * `ctx.inject(['sessionProjections'])`.
16
- */
17
- import { z } from "zod";
18
- const agentPresetSchema = z.union([z.string(), z.null()]);
19
- /** Current Session preset, initialized from its header and advanced by selection events. */
20
- export const piAgentPresetProjection = {
21
- key: "agentPreset",
22
- stateSchema: agentPresetSchema,
23
- init: (header) => header.agentPreset ?? "pi",
24
- apply: (state, event) => event.type === "agent-preset/selected"
25
- ? event.data.agentPreset
26
- : state,
27
- wire: { viewSchema: agentPresetSchema, view: (state) => state },
28
- stateVersion: 1,
29
- };
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes