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.
- package/README.md +25 -3
- package/agent-agy/cordis.patch.yml +7 -4
- package/agent-agy/dist/agent.d.ts +12 -11
- package/agent-agy/dist/agy-auth-gateway.d.ts +124 -0
- package/agent-agy/dist/agy-auth-gateway.js +233 -0
- package/agent-agy/dist/agy-auth.d.ts +153 -0
- package/agent-agy/dist/agy-auth.js +179 -0
- package/agent-agy/dist/agy-cli-client.d.ts +39 -9
- package/agent-agy/dist/agy-cli-client.js +82 -18
- package/agent-agy/dist/agy-store.d.ts +8 -0
- package/agent-agy/dist/index.d.ts +46 -16
- package/agent-agy/dist/index.js +82 -56
- package/agent-agy/dist/models.d.ts +70 -0
- package/agent-agy/dist/models.js +102 -3
- package/agent-agy/package.json +7 -5
- package/agent-agy-sdk/cordis.patch.yml +58 -0
- package/agent-agy-sdk/dist/adapter.d.ts +15 -0
- package/agent-agy-sdk/dist/adapter.js +42 -0
- package/agent-agy-sdk/dist/agent-preset-agy.d.ts +27 -0
- package/agent-agy-sdk/dist/agent-preset-agy.js +32 -0
- package/agent-agy-sdk/dist/agent.d.ts +138 -0
- package/agent-agy-sdk/dist/agent.js +494 -0
- package/{agent-agy → agent-agy-sdk}/dist/agy-client.d.ts +26 -6
- package/{agent-agy → agent-agy-sdk}/dist/agy-client.js +43 -25
- package/agent-agy-sdk/dist/agy-sessions.d.ts +25 -0
- package/agent-agy-sdk/dist/agy-sessions.js +107 -0
- package/agent-agy-sdk/dist/agy-store.d.ts +39 -0
- package/agent-agy-sdk/dist/agy-store.js +83 -0
- package/agent-agy-sdk/dist/inbox.d.ts +26 -0
- package/agent-agy-sdk/dist/inbox.js +53 -0
- package/agent-agy-sdk/dist/index.d.ts +93 -0
- package/agent-agy-sdk/dist/index.js +476 -0
- package/agent-agy-sdk/dist/models.d.ts +41 -0
- package/agent-agy-sdk/dist/models.js +74 -0
- package/agent-agy-sdk/dist/sdk-venv.d.ts +76 -0
- package/agent-agy-sdk/dist/sdk-venv.js +173 -0
- package/agent-agy-sdk/dist/world-plugin.d.ts +10 -0
- package/agent-agy-sdk/dist/world-plugin.js +82 -0
- package/agent-agy-sdk/package.json +64 -0
- package/agent-claude/dist/adapter.js +106 -31
- package/agent-claude/dist/agent.js +154 -17
- package/agent-claude/dist/claude-client.js +84 -43
- package/agent-claude/dist/claude-launch.js +101 -0
- package/agent-claude/dist/claude-native-config.js +169 -0
- package/agent-claude/dist/claude-provider-gateway.js +340 -0
- package/agent-claude/dist/claude-providers.js +391 -0
- package/agent-claude/dist/claude-route.js +152 -0
- package/agent-claude/dist/index.js +214 -37
- package/agent-claude/dist/models.js +14 -0
- package/agent-claude/dist/sdk-runtime.js +320 -0
- package/agent-claude/package.json +6 -4
- package/agent-codex/README.md +141 -36
- package/agent-codex/cordis.patch.yml +14 -10
- package/agent-codex/dist/adapter.js +64 -28
- package/agent-codex/dist/agent.js +255 -81
- package/agent-codex/dist/app-server-approvals.js +165 -0
- package/agent-codex/dist/app-server-client.js +723 -0
- package/agent-codex/dist/app-server-events.js +432 -0
- package/agent-codex/dist/app-server-protocol.js +95 -0
- package/agent-codex/dist/app-server-wire.js +299 -0
- package/agent-codex/dist/codex-launch.js +78 -0
- package/agent-codex/dist/codex-native-config.js +392 -0
- package/agent-codex/dist/codex-provider-gateway.js +402 -0
- package/agent-codex/dist/codex-providers.js +376 -0
- package/agent-codex/dist/codex-route.js +86 -0
- package/agent-codex/dist/index.js +256 -115
- package/agent-codex/dist/permission.js +75 -1
- package/agent-codex/package.json +1 -2
- package/agent-codex-sdk/README.md +79 -0
- package/agent-codex-sdk/cordis.patch.yml +81 -0
- package/agent-codex-sdk/dist/adapter.js +91 -0
- package/agent-codex-sdk/dist/agent-preset-codex.js +32 -0
- package/agent-codex-sdk/dist/agent.js +1085 -0
- package/agent-codex-sdk/dist/codex-native-config.js +392 -0
- package/agent-codex-sdk/dist/codex-provider-gateway.js +402 -0
- package/agent-codex-sdk/dist/codex-providers.js +376 -0
- package/agent-codex-sdk/dist/codex-route.js +86 -0
- package/{agent-codex/dist/codex-client.js → agent-codex-sdk/dist/codex-sdk-client.js} +253 -32
- package/agent-codex-sdk/dist/codex-sdk-launch.js +92 -0
- package/agent-codex-sdk/dist/codex-store.js +180 -0
- package/agent-codex-sdk/dist/inbox.js +53 -0
- package/agent-codex-sdk/dist/index.js +739 -0
- package/agent-codex-sdk/dist/permission.js +71 -0
- package/agent-codex-sdk/dist/sdk-runtime.js +307 -0
- package/agent-codex-sdk/dist/session-map.js +167 -0
- package/agent-codex-sdk/dist/world-plugin.js +93 -0
- package/agent-codex-sdk/package.json +79 -0
- package/agent-codex-sdk/scripts/fetch-sdk-runtime.mjs +57 -0
- package/agent-omp/README.md +72 -55
- package/agent-omp/dist/agent.js +36 -11
- package/agent-omp/dist/index.js +92 -52
- package/agent-omp/dist/lazy-rpc.js +11 -4
- package/agent-omp/dist/omp-cli.js +114 -97
- package/agent-omp/dist/omp-store.js +12 -4
- package/agent-omp/dist/permission.js +70 -5
- package/agent-omp/dist/rpc-client.js +409 -0
- package/agent-omp/dist/world-plugin.js +36 -3
- package/agent-omp/package.json +2 -6
- package/agent-omp-sdk/README.md +103 -0
- package/agent-omp-sdk/cordis.patch.yml +108 -0
- package/agent-omp-sdk/dist/adapter.d.ts +21 -0
- package/agent-omp-sdk/dist/adapter.js +36 -0
- package/agent-omp-sdk/dist/agent-preset-omp.d.ts +31 -0
- package/agent-omp-sdk/dist/agent-preset-omp.js +32 -0
- package/agent-omp-sdk/dist/agent.d.ts +64 -0
- package/agent-omp-sdk/dist/agent.js +1178 -0
- package/agent-omp-sdk/dist/discovery.d.ts +57 -0
- package/agent-omp-sdk/dist/discovery.js +116 -0
- package/agent-omp-sdk/dist/inbox.d.ts +28 -0
- package/agent-omp-sdk/dist/inbox.js +53 -0
- package/agent-omp-sdk/dist/index.d.ts +60 -0
- package/agent-omp-sdk/dist/index.js +632 -0
- package/agent-omp-sdk/dist/knobs.d.ts +34 -0
- package/agent-omp-sdk/dist/knobs.js +50 -0
- package/agent-omp-sdk/dist/lazy-rpc.d.ts +98 -0
- package/agent-omp-sdk/dist/lazy-rpc.js +178 -0
- package/agent-omp-sdk/dist/mobile/zoom-guard.d.ts +187 -0
- package/agent-omp-sdk/dist/mobile/zoom-guard.js +294 -0
- package/agent-omp-sdk/dist/mobile-boot.d.ts +49 -0
- package/agent-omp-sdk/dist/mobile-boot.js +38 -0
- package/agent-omp-sdk/dist/models.d.ts +39 -0
- package/agent-omp-sdk/dist/models.js +299 -0
- package/agent-omp-sdk/dist/omp-cli.d.ts +67 -0
- package/agent-omp-sdk/dist/omp-cli.js +164 -0
- package/agent-omp-sdk/dist/omp-disk-discovery.d.ts +27 -0
- package/agent-omp-sdk/dist/omp-disk-discovery.js +178 -0
- package/agent-omp-sdk/dist/omp-executable.d.ts +2 -0
- package/agent-omp-sdk/dist/omp-executable.js +30 -0
- package/agent-omp-sdk/dist/omp-store.d.ts +134 -0
- package/agent-omp-sdk/dist/omp-store.js +526 -0
- package/agent-omp-sdk/dist/pairing.d.ts +7 -0
- package/agent-omp-sdk/dist/pairing.js +45 -0
- package/agent-omp-sdk/dist/permission.d.ts +138 -0
- package/agent-omp-sdk/dist/permission.js +161 -0
- package/agent-omp-sdk/dist/protocol.d.ts +189 -0
- package/agent-omp-sdk/dist/rpc-types.d.ts +77 -0
- package/agent-omp-sdk/dist/rpc-types.js +1 -0
- package/agent-omp-sdk/dist/sdk-client.d.ts +160 -0
- package/{agent-omp → agent-omp-sdk}/dist/sdk-client.js +108 -56
- package/agent-omp-sdk/dist/sdk-runtime.d.ts +211 -0
- package/agent-omp-sdk/dist/sdk-runtime.js +418 -0
- package/agent-omp-sdk/dist/sidecar-client.d.ts +87 -0
- package/agent-omp-sdk/dist/sidecar-client.js +197 -0
- package/agent-omp-sdk/dist/store/adapter.d.ts +17 -0
- package/agent-omp-sdk/dist/store/adapter.js +47 -0
- package/agent-omp-sdk/dist/store/db.d.ts +70 -0
- package/agent-omp-sdk/dist/store/db.js +210 -0
- package/agent-omp-sdk/dist/store/index.d.ts +23 -0
- package/agent-omp-sdk/dist/store/index.js +59 -0
- package/agent-omp-sdk/dist/store/reconcile.d.ts +15 -0
- package/agent-omp-sdk/dist/store/reconcile.js +51 -0
- package/agent-omp-sdk/dist/store/schema.d.ts +8 -0
- package/agent-omp-sdk/dist/store/schema.js +40 -0
- package/agent-omp-sdk/dist/transport.d.ts +49 -0
- package/agent-omp-sdk/dist/transport.js +35 -0
- package/agent-omp-sdk/dist/world-home.d.ts +4 -0
- package/agent-omp-sdk/dist/world-home.js +23 -0
- package/agent-omp-sdk/dist/world-plugin.d.ts +10 -0
- package/agent-omp-sdk/dist/world-plugin.js +137 -0
- package/agent-omp-sdk/package.json +87 -0
- package/client/index.js +1204 -93
- package/cordis.patch.yml +64 -0
- package/package.json +17 -8
- package/superd-hub/dist/client/agent-settings.d.ts +210 -0
- package/superd-hub/dist/client/agent-settings.js +300 -0
- package/superd-hub/dist/client/roster.js +6 -0
- package/superd-hub/dist/client/runtime-settings-api.d.ts +76 -0
- package/superd-hub/dist/client/runtime-settings-api.js +137 -0
- package/superd-hub/dist/client/switch.d.ts +165 -0
- package/superd-hub/dist/client/switch.js +295 -0
- package/superd-hub/lib/client/index.js +1204 -93
- package/agent-codex/dist/models.js +0 -152
- package/agent-omp/dist/sidecar-client.js +0 -195
- /package/{agent-agy → agent-agy-sdk}/bridge/agy_bridge.py +0 -0
- /package/{agent-agy → agent-agy-sdk}/bridge/gemini_openai_server.mjs +0 -0
- /package/{agent-codex/dist/codex-events.js → agent-codex-sdk/dist/codex-sdk-events.js} +0 -0
- /package/{agent-omp → agent-omp-sdk}/dist/protocol.js +0 -0
- /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
|
|
8
|
-
*
|
|
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
|
|
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
|
|
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
|
-
|
|
26
|
-
|
|
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(
|
|
29
|
-
|
|
30
|
-
|
|
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.
|
|
33
|
-
...(model.description === undefined ? {} : { description: model.description }),
|
|
92
|
+
name: model.displayName ?? model.id,
|
|
34
93
|
}));
|
|
35
94
|
}
|
|
36
|
-
async resolveModel(
|
|
37
|
-
|
|
38
|
-
|
|
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
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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");
|