super-dsh 0.1.9 → 0.1.10-e

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 (178) hide show
  1. package/README.md +25 -3
  2. package/agent-agy/cordis.patch.yml +7 -4
  3. package/agent-agy/dist/agent.d.ts +12 -11
  4. package/agent-agy/dist/agy-auth-gateway.d.ts +124 -0
  5. package/agent-agy/dist/agy-auth-gateway.js +233 -0
  6. package/agent-agy/dist/agy-auth.d.ts +153 -0
  7. package/agent-agy/dist/agy-auth.js +179 -0
  8. package/agent-agy/dist/agy-cli-client.d.ts +39 -9
  9. package/agent-agy/dist/agy-cli-client.js +82 -18
  10. package/agent-agy/dist/agy-store.d.ts +8 -0
  11. package/agent-agy/dist/index.d.ts +46 -16
  12. package/agent-agy/dist/index.js +82 -56
  13. package/agent-agy/dist/models.d.ts +70 -0
  14. package/agent-agy/dist/models.js +102 -3
  15. package/agent-agy/package.json +7 -5
  16. package/agent-agy-sdk/cordis.patch.yml +58 -0
  17. package/agent-agy-sdk/dist/adapter.d.ts +15 -0
  18. package/agent-agy-sdk/dist/adapter.js +42 -0
  19. package/agent-agy-sdk/dist/agent-preset-agy.d.ts +27 -0
  20. package/agent-agy-sdk/dist/agent-preset-agy.js +32 -0
  21. package/agent-agy-sdk/dist/agent.d.ts +138 -0
  22. package/agent-agy-sdk/dist/agent.js +494 -0
  23. package/{agent-agy → agent-agy-sdk}/dist/agy-client.d.ts +26 -6
  24. package/{agent-agy → agent-agy-sdk}/dist/agy-client.js +43 -25
  25. package/agent-agy-sdk/dist/agy-sessions.d.ts +25 -0
  26. package/agent-agy-sdk/dist/agy-sessions.js +107 -0
  27. package/agent-agy-sdk/dist/agy-store.d.ts +39 -0
  28. package/agent-agy-sdk/dist/agy-store.js +83 -0
  29. package/agent-agy-sdk/dist/inbox.d.ts +26 -0
  30. package/agent-agy-sdk/dist/inbox.js +53 -0
  31. package/agent-agy-sdk/dist/index.d.ts +93 -0
  32. package/agent-agy-sdk/dist/index.js +476 -0
  33. package/agent-agy-sdk/dist/models.d.ts +41 -0
  34. package/agent-agy-sdk/dist/models.js +74 -0
  35. package/agent-agy-sdk/dist/sdk-venv.d.ts +76 -0
  36. package/agent-agy-sdk/dist/sdk-venv.js +173 -0
  37. package/agent-agy-sdk/dist/world-plugin.d.ts +10 -0
  38. package/agent-agy-sdk/dist/world-plugin.js +82 -0
  39. package/agent-agy-sdk/package.json +64 -0
  40. package/agent-claude/dist/adapter.js +106 -31
  41. package/agent-claude/dist/agent.js +154 -17
  42. package/agent-claude/dist/claude-client.js +84 -43
  43. package/agent-claude/dist/claude-launch.js +101 -0
  44. package/agent-claude/dist/claude-native-config.js +169 -0
  45. package/agent-claude/dist/claude-provider-gateway.js +340 -0
  46. package/agent-claude/dist/claude-providers.js +391 -0
  47. package/agent-claude/dist/claude-route.js +152 -0
  48. package/agent-claude/dist/index.js +214 -37
  49. package/agent-claude/dist/models.js +14 -0
  50. package/agent-claude/dist/sdk-runtime.js +320 -0
  51. package/agent-claude/package.json +6 -4
  52. package/agent-codex/README.md +141 -36
  53. package/agent-codex/cordis.patch.yml +14 -10
  54. package/agent-codex/dist/adapter.js +64 -28
  55. package/agent-codex/dist/agent.js +255 -81
  56. package/agent-codex/dist/app-server-approvals.js +165 -0
  57. package/agent-codex/dist/app-server-client.js +723 -0
  58. package/agent-codex/dist/app-server-events.js +432 -0
  59. package/agent-codex/dist/app-server-protocol.js +95 -0
  60. package/agent-codex/dist/app-server-wire.js +299 -0
  61. package/agent-codex/dist/codex-launch.js +78 -0
  62. package/agent-codex/dist/codex-native-config.js +392 -0
  63. package/agent-codex/dist/codex-provider-gateway.js +402 -0
  64. package/agent-codex/dist/codex-providers.js +376 -0
  65. package/agent-codex/dist/codex-route.js +86 -0
  66. package/agent-codex/dist/index.js +256 -115
  67. package/agent-codex/dist/permission.js +75 -1
  68. package/agent-codex/package.json +1 -2
  69. package/agent-codex-sdk/README.md +79 -0
  70. package/agent-codex-sdk/cordis.patch.yml +81 -0
  71. package/agent-codex-sdk/dist/adapter.js +91 -0
  72. package/agent-codex-sdk/dist/agent-preset-codex.js +32 -0
  73. package/agent-codex-sdk/dist/agent.js +1085 -0
  74. package/agent-codex-sdk/dist/codex-native-config.js +392 -0
  75. package/agent-codex-sdk/dist/codex-provider-gateway.js +402 -0
  76. package/agent-codex-sdk/dist/codex-providers.js +376 -0
  77. package/agent-codex-sdk/dist/codex-route.js +86 -0
  78. package/{agent-codex/dist/codex-client.js → agent-codex-sdk/dist/codex-sdk-client.js} +253 -32
  79. package/agent-codex-sdk/dist/codex-sdk-launch.js +92 -0
  80. package/agent-codex-sdk/dist/codex-store.js +180 -0
  81. package/agent-codex-sdk/dist/inbox.js +53 -0
  82. package/agent-codex-sdk/dist/index.js +739 -0
  83. package/agent-codex-sdk/dist/permission.js +71 -0
  84. package/agent-codex-sdk/dist/sdk-runtime.js +307 -0
  85. package/agent-codex-sdk/dist/session-map.js +167 -0
  86. package/agent-codex-sdk/dist/world-plugin.js +93 -0
  87. package/agent-codex-sdk/package.json +79 -0
  88. package/agent-codex-sdk/scripts/fetch-sdk-runtime.mjs +57 -0
  89. package/agent-omp/README.md +72 -55
  90. package/agent-omp/dist/agent.js +36 -11
  91. package/agent-omp/dist/index.js +92 -52
  92. package/agent-omp/dist/lazy-rpc.js +11 -4
  93. package/agent-omp/dist/omp-cli.js +114 -97
  94. package/agent-omp/dist/omp-store.js +12 -4
  95. package/agent-omp/dist/permission.js +70 -5
  96. package/agent-omp/dist/rpc-client.js +409 -0
  97. package/agent-omp/dist/world-plugin.js +36 -3
  98. package/agent-omp/package.json +2 -6
  99. package/agent-omp-sdk/README.md +103 -0
  100. package/agent-omp-sdk/cordis.patch.yml +108 -0
  101. package/agent-omp-sdk/dist/adapter.d.ts +21 -0
  102. package/agent-omp-sdk/dist/adapter.js +36 -0
  103. package/agent-omp-sdk/dist/agent-preset-omp.d.ts +31 -0
  104. package/agent-omp-sdk/dist/agent-preset-omp.js +32 -0
  105. package/agent-omp-sdk/dist/agent.d.ts +64 -0
  106. package/agent-omp-sdk/dist/agent.js +1178 -0
  107. package/agent-omp-sdk/dist/discovery.d.ts +57 -0
  108. package/agent-omp-sdk/dist/discovery.js +116 -0
  109. package/agent-omp-sdk/dist/inbox.d.ts +28 -0
  110. package/agent-omp-sdk/dist/inbox.js +53 -0
  111. package/agent-omp-sdk/dist/index.d.ts +60 -0
  112. package/agent-omp-sdk/dist/index.js +632 -0
  113. package/agent-omp-sdk/dist/knobs.d.ts +34 -0
  114. package/agent-omp-sdk/dist/knobs.js +50 -0
  115. package/agent-omp-sdk/dist/lazy-rpc.d.ts +98 -0
  116. package/agent-omp-sdk/dist/lazy-rpc.js +178 -0
  117. package/agent-omp-sdk/dist/mobile/zoom-guard.d.ts +187 -0
  118. package/agent-omp-sdk/dist/mobile/zoom-guard.js +294 -0
  119. package/agent-omp-sdk/dist/mobile-boot.d.ts +49 -0
  120. package/agent-omp-sdk/dist/mobile-boot.js +38 -0
  121. package/agent-omp-sdk/dist/models.d.ts +39 -0
  122. package/agent-omp-sdk/dist/models.js +299 -0
  123. package/agent-omp-sdk/dist/omp-cli.d.ts +67 -0
  124. package/agent-omp-sdk/dist/omp-cli.js +164 -0
  125. package/agent-omp-sdk/dist/omp-disk-discovery.d.ts +27 -0
  126. package/agent-omp-sdk/dist/omp-disk-discovery.js +178 -0
  127. package/agent-omp-sdk/dist/omp-executable.d.ts +2 -0
  128. package/agent-omp-sdk/dist/omp-executable.js +30 -0
  129. package/agent-omp-sdk/dist/omp-store.d.ts +134 -0
  130. package/agent-omp-sdk/dist/omp-store.js +526 -0
  131. package/agent-omp-sdk/dist/pairing.d.ts +7 -0
  132. package/agent-omp-sdk/dist/pairing.js +45 -0
  133. package/agent-omp-sdk/dist/permission.d.ts +138 -0
  134. package/agent-omp-sdk/dist/permission.js +161 -0
  135. package/agent-omp-sdk/dist/protocol.d.ts +189 -0
  136. package/agent-omp-sdk/dist/rpc-types.d.ts +77 -0
  137. package/agent-omp-sdk/dist/rpc-types.js +1 -0
  138. package/agent-omp-sdk/dist/sdk-client.d.ts +160 -0
  139. package/{agent-omp → agent-omp-sdk}/dist/sdk-client.js +108 -56
  140. package/agent-omp-sdk/dist/sdk-runtime.d.ts +211 -0
  141. package/agent-omp-sdk/dist/sdk-runtime.js +418 -0
  142. package/agent-omp-sdk/dist/sidecar-client.d.ts +87 -0
  143. package/agent-omp-sdk/dist/sidecar-client.js +197 -0
  144. package/agent-omp-sdk/dist/store/adapter.d.ts +17 -0
  145. package/agent-omp-sdk/dist/store/adapter.js +47 -0
  146. package/agent-omp-sdk/dist/store/db.d.ts +70 -0
  147. package/agent-omp-sdk/dist/store/db.js +210 -0
  148. package/agent-omp-sdk/dist/store/index.d.ts +23 -0
  149. package/agent-omp-sdk/dist/store/index.js +59 -0
  150. package/agent-omp-sdk/dist/store/reconcile.d.ts +15 -0
  151. package/agent-omp-sdk/dist/store/reconcile.js +51 -0
  152. package/agent-omp-sdk/dist/store/schema.d.ts +8 -0
  153. package/agent-omp-sdk/dist/store/schema.js +40 -0
  154. package/agent-omp-sdk/dist/transport.d.ts +49 -0
  155. package/agent-omp-sdk/dist/transport.js +35 -0
  156. package/agent-omp-sdk/dist/world-home.d.ts +4 -0
  157. package/agent-omp-sdk/dist/world-home.js +23 -0
  158. package/agent-omp-sdk/dist/world-plugin.d.ts +10 -0
  159. package/agent-omp-sdk/dist/world-plugin.js +137 -0
  160. package/agent-omp-sdk/package.json +87 -0
  161. package/client/index.js +1204 -93
  162. package/cordis.patch.yml +64 -0
  163. package/package.json +17 -8
  164. package/superd-hub/dist/client/agent-settings.d.ts +210 -0
  165. package/superd-hub/dist/client/agent-settings.js +300 -0
  166. package/superd-hub/dist/client/roster.js +6 -0
  167. package/superd-hub/dist/client/runtime-settings-api.d.ts +76 -0
  168. package/superd-hub/dist/client/runtime-settings-api.js +137 -0
  169. package/superd-hub/dist/client/switch.d.ts +165 -0
  170. package/superd-hub/dist/client/switch.js +295 -0
  171. package/superd-hub/lib/client/index.js +1204 -93
  172. package/agent-codex/dist/models.js +0 -152
  173. package/agent-omp/dist/sidecar-client.js +0 -195
  174. /package/{agent-agy → agent-agy-sdk}/bridge/agy_bridge.py +0 -0
  175. /package/{agent-agy → agent-agy-sdk}/bridge/gemini_openai_server.mjs +0 -0
  176. /package/{agent-codex/dist/codex-events.js → agent-codex-sdk/dist/codex-sdk-events.js} +0 -0
  177. /package/{agent-omp → agent-omp-sdk}/dist/protocol.js +0 -0
  178. /package/{agent-omp → agent-omp-sdk}/sidecar/main.ts +0 -0
@@ -0,0 +1,173 @@
1
+ /**
2
+ * sdk-venv.ts — the lazy, durable Python venv the SDK bridge runs on.
3
+ *
4
+ * 2026-10-02 user ruling (spec §4.2): this package declares NO Python
5
+ * dependency and ships NO postinstall/allow-scripts hook. Nothing is fetched at
6
+ * install time; the FIRST real use fetches the venv into the world home, where
7
+ * it is durable across sessions, restarts and package upgrades. A second use
8
+ * reuses it (idempotent), and a FAILED fetch leaves a trace on disk instead of
9
+ * silently degrading into a confusing bridge crash.
10
+ *
11
+ * Why the world home rather than the package root: the package root is the
12
+ * installed tarball — read-only in every real consumer install, and shared by
13
+ * every world (the CLI one included). The world home is per-runtime, writable,
14
+ * and already the home of this adapter's own state.
15
+ *
16
+ * The bootstrap is two idempotent steps, so a half-built venv heals in place
17
+ * rather than being thrown away and re-downloaded:
18
+ * 1. `<worldHome>/sdk-venv/bin/python` missing → `python3 -m venv <dir>`
19
+ * 2. `<worldHome>/sdk-venv.json` marker missing → `pip install google-antigravity`
20
+ */
21
+ import { execFileSync } from "node:child_process";
22
+ import { appendFileSync, existsSync, mkdirSync, readFileSync, rmSync, statSync, writeFileSync } from "node:fs";
23
+ import { join } from "node:path";
24
+ /** The Python distribution the bridge imports (`bridge/agy_bridge.py`). */
25
+ export const SDK_PYTHON_PACKAGE = "google-antigravity";
26
+ export function sdkVenvLayout(worldHome) {
27
+ const dir = join(worldHome, "sdk-venv");
28
+ return {
29
+ dir,
30
+ python: join(dir, "bin", "python"),
31
+ pip: join(dir, "bin", "pip"),
32
+ marker: join(worldHome, "sdk-venv.json"),
33
+ errorLog: join(worldHome, "sdk-venv.error.log"),
34
+ lock: join(worldHome, "sdk-venv.lock"),
35
+ };
36
+ }
37
+ /** Read the install marker; undefined when absent or unreadable. */
38
+ export function readSdkVenvRecord(worldHome) {
39
+ const { marker } = sdkVenvLayout(worldHome);
40
+ if (!existsSync(marker))
41
+ return undefined;
42
+ try {
43
+ const parsed = JSON.parse(readFileSync(marker, "utf8"));
44
+ return typeof parsed === "object" && parsed !== null ? parsed : undefined;
45
+ }
46
+ catch {
47
+ return undefined;
48
+ }
49
+ }
50
+ /** Fast path: the complete venv already exists → the interpreter to use. */
51
+ export function resolveSdkPython(worldHome) {
52
+ const layout = sdkVenvLayout(worldHome);
53
+ return existsSync(layout.python) && existsSync(layout.marker) ? layout.python : undefined;
54
+ }
55
+ const DEFAULTS = {
56
+ basePython: "python3",
57
+ lockTimeoutMs: 30 * 60 * 1000,
58
+ lockPollMs: 1000,
59
+ lockStaleMs: 30 * 60 * 1000,
60
+ };
61
+ function defaultRun(cmd, args) {
62
+ execFileSync(cmd, args, { stdio: ["ignore", "pipe", "pipe"] });
63
+ }
64
+ /**
65
+ * Return the interpreter path for `<worldHome>`'s durable venv, fetching it
66
+ * first when it is absent or incomplete.
67
+ *
68
+ * Idempotent: a complete venv short-circuits without touching the network.
69
+ * Failures append to `<worldHome>/sdk-venv.error.log` and throw a single
70
+ * actionable error — never a partial venv left behind a success marker.
71
+ */
72
+ export async function ensureSdkVenv(worldHome, opts = {}) {
73
+ const layout = sdkVenvLayout(worldHome);
74
+ const now = opts.now ?? Date.now;
75
+ const sleep = opts.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
76
+ const run = opts.run ?? defaultRun;
77
+ const ready = resolveSdkPython(worldHome);
78
+ if (ready !== undefined)
79
+ return ready;
80
+ mkdirSync(worldHome, { recursive: true });
81
+ // `acquired === false` means a peer finished the fetch while we waited: the
82
+ // lock is not ours and MUST NOT be released by this caller.
83
+ const acquired = await acquireLock(worldHome, layout, now, sleep, opts);
84
+ if (!acquired)
85
+ return layout.python;
86
+ try {
87
+ // Re-check inside the lock: a concurrent bootstrap may have finished while
88
+ // we waited, in which case this caller pays nothing.
89
+ const done = resolveSdkPython(worldHome);
90
+ if (done !== undefined)
91
+ return done;
92
+ const basePython = opts.basePython ?? process.env.AGY_SDK_BASE_PYTHON ?? DEFAULTS.basePython;
93
+ const stale = existsSync(layout.python);
94
+ try {
95
+ opts.trace?.(`sdk-venv: fetching ${SDK_PYTHON_PACKAGE} into ${layout.dir}`);
96
+ if (!stale)
97
+ run(basePython, ["-m", "venv", layout.dir]);
98
+ run(layout.pip, ["install", "-q", SDK_PYTHON_PACKAGE]);
99
+ if (!existsSync(layout.python)) {
100
+ throw new Error(`venv created but ${layout.python} is missing`);
101
+ }
102
+ const record = {
103
+ package: SDK_PYTHON_PACKAGE,
104
+ python: layout.python,
105
+ installedAt: new Date(now()).toISOString(),
106
+ createdWith: basePython,
107
+ };
108
+ writeFileSync(layout.marker, JSON.stringify(record, null, 2) + "\n");
109
+ rmSync(layout.errorLog, { force: true });
110
+ opts.trace?.(`sdk-venv: ready (${layout.python})`);
111
+ return layout.python;
112
+ }
113
+ catch (error) {
114
+ const detail = error instanceof Error ? error.message : String(error);
115
+ const stamp = new Date(now()).toISOString();
116
+ try {
117
+ appendFileSync(layout.errorLog, `[${stamp}] ${SDK_PYTHON_PACKAGE} fetch failed: ${detail}\n`);
118
+ }
119
+ catch {
120
+ /* the trace is best-effort; the throw below is the contract */
121
+ }
122
+ throw new Error(`agy-sdk: could not fetch the Python SDK venv (${SDK_PYTHON_PACKAGE}) at ${layout.dir}: ${detail}. ` +
123
+ `Install it by hand with \`npm run fetch-venv\` (or set AGY_PYTHON to an interpreter that has it). ` +
124
+ `Trace: ${layout.errorLog}`);
125
+ }
126
+ }
127
+ finally {
128
+ rmSync(layout.lock, { recursive: true, force: true });
129
+ }
130
+ }
131
+ /**
132
+ * mkdir-based mutex with stale-lock reclamation.
133
+ *
134
+ * Resolves `true` when THIS caller owns the lock (and must release it), `false`
135
+ * when a peer completed the fetch while we waited (nothing to release, the
136
+ * venv is ready). Throws when the wait budget is exhausted.
137
+ */
138
+ async function acquireLock(worldHome, layout, now, sleep, opts) {
139
+ const timeout = opts.lockTimeoutMs ?? DEFAULTS.lockTimeoutMs;
140
+ const poll = opts.lockPollMs ?? DEFAULTS.lockPollMs;
141
+ const staleMs = opts.lockStaleMs ?? DEFAULTS.lockStaleMs;
142
+ const deadline = now() + timeout;
143
+ for (;;) {
144
+ try {
145
+ mkdirSync(layout.lock);
146
+ return true;
147
+ }
148
+ catch (error) {
149
+ if (error.code !== "EEXIST")
150
+ throw error;
151
+ }
152
+ // Someone holds it. Another process may have finished the fetch already.
153
+ if (resolveSdkPython(worldHome) !== undefined)
154
+ return false;
155
+ let ageMs = 0;
156
+ try {
157
+ ageMs = now() - statSync(layout.lock).mtimeMs;
158
+ }
159
+ catch {
160
+ continue; // released between the mkdir attempt and the stat — retry now
161
+ }
162
+ if (ageMs > staleMs) {
163
+ opts.trace?.(`sdk-venv: stealing stale lock (age ${Math.round(ageMs / 1000)}s)`);
164
+ rmSync(layout.lock, { recursive: true, force: true });
165
+ continue;
166
+ }
167
+ if (now() >= deadline) {
168
+ throw new Error(`agy-sdk: timed out waiting for a concurrent SDK venv fetch (lock ${layout.lock}). ` +
169
+ `Remove the lock directory if no fetch is running.`);
170
+ }
171
+ await sleep(poll);
172
+ }
173
+ }
@@ -0,0 +1,10 @@
1
+ export declare const name = "agent-agy-sdk";
2
+ /** Structural slice of the ctx0 services the mount needs. */
3
+ interface HostContext {
4
+ provide(name: string, value: unknown): void;
5
+ inject(deps: string[], callback: (ctx: unknown) => void): unknown;
6
+ effect?(callback: () => () => void, label?: string): unknown;
7
+ get(name: string): unknown;
8
+ }
9
+ export declare function apply(ctx: HostContext): void;
10
+ export {};
@@ -0,0 +1,82 @@
1
+ /**
2
+ * agent-agy — the Antigravity (agy) adapter's WORLD plugin (spec S2):
3
+ * activation IS roster membership.
4
+ *
5
+ * AW-B data-plane shape (DL1–DL5 → path-separation T-D), mirroring
6
+ * `@pgmi-builds/agent-omp/world` and `@pgmi-builds/agent-codex/world` so the
7
+ * hub sees every foreign runtime through one shape: the world is spawned as a
8
+ * sibling ROOT context with NO listener and NO webui composition
9
+ * (`worldMountPatches`) — a pure data plane behind the hub's `/hub` family.
10
+ *
11
+ * 1. ctx0 publishes the host mount record (the world's addressability
12
+ * entry — no webServer, no fence: those legs retired with the world
13
+ * pages) before spawn;
14
+ * 2. the world's entry row provides the virtual `webServer` (a silent
15
+ * sink) plus the neutral `webRuntime` facts its connection row injects;
16
+ * 3. the hub's `/hub` family answers `?agent=agy` traffic in ctx0's auth
17
+ * domain and dispatches into this world's gateway instance (the
18
+ * per-label `/<label>/api` + `/<label>/api/remote.mux` mounts retired
19
+ * in T-C, `mountWorld` deleted in T-D).
20
+ */
21
+ import { mkdirSync } from 'node:fs';
22
+ import { resolveDshHome } from '@deepseek-ai/dsh-home-paths';
23
+ import { join } from 'node:path';
24
+ import { spawnWorld, registerAgent, setReady, registerForeignTarget, registerHostMount, worldMountPatches, provisionWorldProfile, resolveInstallAnchor, } from '../../superd-hub/dist/index.js';
25
+ export const name = 'agent-agy-sdk';
26
+ /**
27
+ * Runtime key — also the mount label. Deliberately NOT `agy`: the hub's roster
28
+ * (registerAgent) hard-throws on a duplicate key, and this row ships alongside
29
+ * the CLI row in the same composite. Distinct keys keep both independently
30
+ * toggleable and make the "both enabled" mistake survivable.
31
+ */
32
+ const KEY = 'agy-sdk';
33
+ export function apply(ctx) {
34
+ registerAgent({ key: KEY, label: 'Antigravity (SDK)', ready: false });
35
+ // Harness resolver (env → ~/.dsh): a consumer install has no DSH_HOME and
36
+ // no cwd contract — deriving the world root from cwd spawns worlds into a
37
+ // garbage tree or throws inside apply() and kills the whole host boot.
38
+ const root = resolveDshHome();
39
+ // Nested home: the world's DSH data lives INSIDE `agents/<label>` (sessions
40
+ // / settings / workspaces, and the adapter's dsh-sessions.json mapping).
41
+ // agy-sdk: the world home carries the DSH-side state AND the lazily fetched
42
+ // durable Python venv (sdk-venv.ts); nothing is nested for the SDK itself.
43
+ const worldHome = join(root, 'agents', KEY);
44
+ mkdirSync(join(worldHome, 'profiles'), { recursive: true });
45
+ // Publish story: a foreign install has no line bootstrap, so the nested
46
+ // profile + @pgmi-builds links are provisioned HERE (idempotent).
47
+ provisionWorldProfile({
48
+ key: KEY,
49
+ adapterPkg: '@pgmi-builds/agent-agy-sdk',
50
+ worldHome,
51
+ });
52
+ const world = (async () => {
53
+ // T-D: no ctx0 listening-stack wait — the mount record is addressability
54
+ // only and the /hub family wires its own gate in ctx0 (gateway.ts).
55
+ const dropHostMount = registerHostMount({ key: KEY, labelPath: `/${KEY}` });
56
+ const ctxW = await spawnWorld({
57
+ appName: `superd-${KEY}`,
58
+ profileName: 'web',
59
+ installAnchor: resolveInstallAnchor(ctx), // lazy: never at module scope — import must stay side-effect-free
60
+ home: worldHome,
61
+ dataHome: worldHome,
62
+ // The host's live table carries this world: spawnWorld republishes a
63
+ // widened successor before boot imports anything (spec §2.1), and
64
+ // @pgmi-builds rows resolve from the profile-local links written above.
65
+ host: ctx,
66
+ extraPatches: worldMountPatches(KEY),
67
+ });
68
+ const gateway = ctxW.get('typertGateway');
69
+ registerForeignTarget({ key: KEY, gateway });
70
+ setReady(KEY, true);
71
+ ctx.effect?.(() => () => {
72
+ dropHostMount();
73
+ }, `agent-${KEY}: mount`);
74
+ return ctxW;
75
+ })().catch((cause) => {
76
+ // A failed world degrades to a not-ready roster row; a rejected provided
77
+ // promise would fail the entire host boot (loader entry apply).
78
+ console.error(`[super-dsh] ${KEY} world failed:`, cause);
79
+ return null;
80
+ });
81
+ ctx.provide(`superd.world.${KEY}`, world);
82
+ }
@@ -0,0 +1,64 @@
1
+ {
2
+ "name": "@pgmi-builds/agent-agy-sdk",
3
+ "version": "0.1.0",
4
+ "description": "Google Antigravity (Gemini) provider for DeepSeek Harness (dsh) — the OPT-IN SDK transport: drives the google-antigravity Python SDK through a JSONL stdio bridge (bridge/agy_bridge.py, localharness embedded). Auth: adapter-side/GEMINI_API_KEY key, else Vertex over ADC. The agy CLI is never invoked — that is @pgmi-builds/agent-agy. Delivered DISABLED by default (roster key `agy-sdk`): the CLI adapter is the primary path because it reuses the user's existing Antigravity environment. No Python dependency is declared anywhere and there is no postinstall/allow-scripts hook — the durable venv is fetched into the world home on first real use (src/sdk-venv.ts, `npm run fetch-venv`).",
5
+ "type": "module",
6
+ "exports": {
7
+ ".": "./dist/index.js",
8
+ "./world": "./dist/world-plugin.js"
9
+ },
10
+ "files": [
11
+ "dist",
12
+ "bridge",
13
+ "cordis.patch.yml"
14
+ ],
15
+ "dsh": {
16
+ "bundle": {
17
+ "patch": "./cordis.patch.yml"
18
+ }
19
+ },
20
+ "scripts": {
21
+ "build": "tsc -p tsconfig.json",
22
+ "test": "node --test test/*.test.mjs",
23
+ "fetch-venv": "node scripts/fetch-venv.mjs"
24
+ },
25
+ "dependencies": {
26
+ "zod": "3.25.76"
27
+ },
28
+ "peerDependencies": {
29
+ "@deepseek-ai/cordis": "^4.0.1",
30
+ "@deepseek-ai/dsh-agent": ">=0.1.5-0 <0.3.0-0",
31
+ "@deepseek-ai/dsh-llm": ">=0.1.5-0 <0.3.0-0",
32
+ "@deepseek-ai/dsh-scope": ">=0.1.5-0 <0.3.0-0",
33
+ "@deepseek-ai/dsh-session": ">=0.1.5-0 <0.3.0-0",
34
+ "@deepseek-ai/dsh-session-persistence": ">=0.1.5-0 <0.3.0-0"
35
+ },
36
+ "peerDependenciesMeta": {
37
+ "@deepseek-ai/cordis": {
38
+ "optional": true
39
+ },
40
+ "@deepseek-ai/dsh-agent": {
41
+ "optional": true
42
+ },
43
+ "@deepseek-ai/dsh-llm": {
44
+ "optional": true
45
+ },
46
+ "@deepseek-ai/dsh-scope": {
47
+ "optional": true
48
+ },
49
+ "@deepseek-ai/dsh-session": {
50
+ "optional": true
51
+ },
52
+ "@deepseek-ai/dsh-session-persistence": {
53
+ "optional": true
54
+ }
55
+ },
56
+ "devDependencies": {
57
+ "@types/node": "^26.2.0",
58
+ "typescript": "^5.6.0"
59
+ },
60
+ "publishConfig": {
61
+ "access": "public"
62
+ },
63
+ "main": "dist/index.js"
64
+ }
@@ -4,8 +4,23 @@
4
4
  * The browser model selector never touches the Claude agent directly: it is an
5
5
  * RPC round-trip through the apiproxy, which reads `ctx.llm.listProviders /
6
6
  * listModels / resolveModel` to build the catalog. This adapter answers those
7
- * queries from the models Claude actually reported (`models.ts`) under the
8
- * single provider route `claude`.
7
+ * queries from TWO sources, one route each (the codex twin's one-route-per-
8
+ * provider shape, 2026-10-04 F-A rework):
9
+ *
10
+ * - the fixed native route `claude` serves the OBSERVED catalog only (raw
11
+ * ids — what the CLI itself reports, `models.ts`); its group stays "Claude".
12
+ * - one route PER configured provider (route id = provider id) serves that
13
+ * provider's curated `models[]` (RAW model ids, `claude-providers.ts`).
14
+ *
15
+ * The route/model composition therefore yields selection ids identical to the
16
+ * old composite keys (`deepseek/deepseek-flash`, `glm/glm-5.3`), so route seeds
17
+ * and logged selections keep working — the route half simply moved from the
18
+ * hardcoded `claude` to the provider id itself.
19
+ *
20
+ * The curated half follows the codex twin's rule exactly: the store is read
21
+ * LIVE on every call, so a panel edit is visible to the next catalog query
22
+ * without re-registration. An absent `worldHome` means observed-only (the
23
+ * settings-UI round trip and the unit tests).
9
24
  *
10
25
  * The route id must be `claude`, NOT `claude-code`: the upstream package
11
26
  * `@deepseek-ai/dsh-subagent-claude-code` already occupies the subagent
@@ -14,47 +29,107 @@
14
29
  * `stream` is never dispatched: Claude owns generation through its own SDK
15
30
  * thread, so the adapter only serves catalog/metadata queries. It throws
16
31
  * rather than fabricating a wire route the harness would misuse.
32
+ *
33
+ * @module agent-claude/adapter
17
34
  */
18
35
  import { LlmAdapter, LlmError, ReasoningEffortId, } from "@deepseek-ai/dsh-llm";
36
+ import { readProviderStore } from "./claude-providers.js";
19
37
  import { readModelCatalog } from "./models.js";
20
- /** The one provider route every observed Claude model is served under. */
38
+ /** The fixed native route every observed Claude model is served under. */
21
39
  export const CLAUDE_PROVIDER_ID = "claude";
22
- /** Human-readable provider name for selectors and diagnostics. */
40
+ /** Human-readable provider name for the fixed native route. */
23
41
  const CLAUDE_PROVIDER_NAME = "Claude";
42
+ /** Whether a provider may be registered as a model route. */
43
+ export function routableProvider(entry) {
44
+ return entry.models.length > 0;
45
+ }
46
+ /** The route ids a store currently contributes to `ctx.llm`: the fixed `claude`
47
+ * route first, then one route per provider that has models (store order). */
48
+ export function routeIds(store) {
49
+ return [CLAUDE_PROVIDER_ID, ...store.providers.filter(routableProvider).map((entry) => entry.id)];
50
+ }
24
51
  export class ClaudeLlmAdapter extends LlmAdapter {
25
- providerInfo(_provider) {
26
- return { id: CLAUDE_PROVIDER_ID, name: CLAUDE_PROVIDER_NAME };
52
+ worldHome;
53
+ /**
54
+ * @param worldHome - the world's DSH home, holding the curated provider
55
+ * store in `<worldHome>/claude-providers.json`. Read on every call (the
56
+ * codex twin's rule), so a panel edit is visible to the next catalog query
57
+ * without re-registration. Absent = observed-only (the fixed `claude` route).
58
+ */
59
+ constructor(worldHome) {
60
+ super();
61
+ this.worldHome = worldHome;
62
+ }
63
+ /** The curated store entry a provider route id names, or `undefined`. */
64
+ curatedProvider(providerId) {
65
+ if (this.worldHome === undefined)
66
+ return undefined;
67
+ return readProviderStore(this.worldHome).providers.find((entry) => entry.id === providerId);
68
+ }
69
+ providerInfo(provider) {
70
+ if (provider === CLAUDE_PROVIDER_ID)
71
+ return { id: CLAUDE_PROVIDER_ID, name: CLAUDE_PROVIDER_NAME };
72
+ // The display name is the entry's label — for a provider folded in from the
73
+ // user's own settings that is its endpoint URL, the only name it supplies.
74
+ return { id: provider, name: this.curatedProvider(provider)?.label ?? provider };
27
75
  }
28
- async listModels(_provider) {
29
- return readModelCatalog().models.map((model) => ({
30
- provider: CLAUDE_PROVIDER_ID,
76
+ async listModels(provider) {
77
+ if (provider === CLAUDE_PROVIDER_ID) {
78
+ // Observed catalog only, raw ids exactly as the CLI reported them.
79
+ return readModelCatalog().models.map((model) => ({
80
+ provider: CLAUDE_PROVIDER_ID,
81
+ id: model.id,
82
+ name: model.label,
83
+ ...(model.description === undefined ? {} : { description: model.description }),
84
+ }));
85
+ }
86
+ const entry = this.curatedProvider(provider);
87
+ if (entry === undefined)
88
+ return [];
89
+ return entry.models.map((model) => ({
90
+ provider,
31
91
  id: model.id,
32
- name: model.label,
33
- ...(model.description === undefined ? {} : { description: model.description }),
92
+ name: model.displayName ?? model.id,
34
93
  }));
35
94
  }
36
- async resolveModel(_provider, model) {
37
- const found = readModelCatalog().models.find((candidate) => candidate.id === model);
38
- if (found === undefined) {
95
+ async resolveModel(provider, model) {
96
+ if (provider === CLAUDE_PROVIDER_ID) {
97
+ // Observed catalog (primary; unchanged behavior for the native route).
98
+ const found = readModelCatalog().models.find((candidate) => candidate.id === model);
99
+ if (found !== undefined) {
100
+ return {
101
+ provider: CLAUDE_PROVIDER_ID,
102
+ id: found.id,
103
+ name: found.label,
104
+ ...(found.description === undefined ? {} : { description: found.description }),
105
+ // Only a positive window is real metadata: an absent or zero window must
106
+ // never become `context: { contextWindow: 0 }`.
107
+ ...(found.contextWindow !== undefined && found.contextWindow > 0
108
+ ? { context: { contextWindow: found.contextWindow } }
109
+ : {}),
110
+ // The CLI's advertised effort levels become adapter-owned reasoning
111
+ // efforts (omp thinking.efforts parity); the CLI names no default, so
112
+ // none is invented.
113
+ ...(found.reasoningEfforts !== undefined && found.reasoningEfforts.length > 0
114
+ ? { reasoning: { efforts: found.reasoningEfforts.map((effort) => ({ id: ReasoningEffortId(effort), name: effort })) } }
115
+ : {}),
116
+ };
117
+ }
39
118
  throw new LlmError(`Claude provider "${CLAUDE_PROVIDER_ID}" does not serve model "${model}"`, "MODEL_NOT_FOUND");
40
119
  }
41
- return {
42
- provider: CLAUDE_PROVIDER_ID,
43
- id: found.id,
44
- name: found.label,
45
- ...(found.description === undefined ? {} : { description: found.description }),
46
- // Only a positive window is real metadata: an absent or zero window must
47
- // never become `context: { contextWindow: 0 }`.
48
- ...(found.contextWindow !== undefined && found.contextWindow > 0
49
- ? { context: { contextWindow: found.contextWindow } }
50
- : {}),
51
- // The CLI's advertised effort levels become adapter-owned reasoning
52
- // efforts (omp thinking.efforts parity); the CLI names no default, so
53
- // none is invented.
54
- ...(found.reasoningEfforts !== undefined && found.reasoningEfforts.length > 0
55
- ? { reasoning: { efforts: found.reasoningEfforts.map((effort) => ({ id: ReasoningEffortId(effort), name: effort })) } }
56
- : {}),
57
- };
120
+ const entry = this.curatedProvider(provider);
121
+ const curated = entry?.models.find((candidate) => candidate.id === model);
122
+ if (entry !== undefined && curated !== undefined) {
123
+ return {
124
+ provider,
125
+ id: curated.id,
126
+ name: curated.displayName ?? curated.id,
127
+ ...(curated.contextWindow !== undefined && curated.contextWindow > 0
128
+ ? { context: { contextWindow: curated.contextWindow } }
129
+ : {}),
130
+ };
131
+ }
132
+ throw new LlmError(`Claude provider "${provider}" does not serve model "${model}"`, "MODEL_NOT_FOUND");
58
133
  }
59
134
  stream(_options) {
60
135
  throw new LlmError("the Claude adapter does not stream: Claude owns generation through its SDK thread", "UNSUPPORTED_STREAM");