super-dsh 0.3.3 → 0.3.4-c
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 +15 -14
- package/agent-agy/dist/world-plugin.js +1 -0
- package/agent-agy/package.json +6 -6
- package/agent-agy-sdk/dist/world-plugin.js +1 -0
- package/agent-agy-sdk/package.json +5 -5
- package/agent-claude/package.json +8 -8
- package/agent-codex/dist/world-plugin.js +1 -0
- package/agent-codex/package.json +7 -7
- package/agent-codex-sdk/dist/world-plugin.js +1 -0
- package/agent-codex-sdk/package.json +7 -7
- package/agent-hermes/bridge/hermes-ws-bridge.py +273 -0
- package/agent-hermes/dist/agent.js +27 -4
- package/agent-hermes/dist/hermes-client.js +55 -10
- package/agent-hermes/dist/index.js +12 -3
- package/agent-hermes/dist/world-plugin.js +1 -0
- package/agent-hermes/package.json +7 -7
- package/agent-omp/dist/world-plugin.js +1 -0
- package/agent-omp/package.json +8 -8
- package/agent-omp-sdk/dist/world-plugin.js +1 -0
- package/agent-omp-sdk/package.json +8 -8
- package/agent-pi/dist/world-plugin.js +1 -0
- package/agent-pi/package.json +7 -7
- package/client/index.js +106 -249
- package/cordis.patch.yml +0 -6
- package/package.json +23 -27
- package/remote/plugin.d.ts +93 -20
- package/remote/plugin.js +921 -452
- package/remote/provenance.json +15 -13
- package/superd-hub/dist/fusion-transport.js +0 -1
- package/superd-hub/dist/world-join.js +1 -0
- package/superd-hub/dist/world-provision.d.ts +4 -0
- package/superd-hub/dist/world-provision.js +37 -0
- package/superd-hub/lib/client/index.js +106 -249
- package/superd-hub/package.json +11 -11
- package/superd-hub/dist/bundle-setup.d.ts +0 -27
- package/superd-hub/dist/bundle-setup.js +0 -94
- package/superd-hub/dist/client/companion-api.d.ts +0 -5
- package/superd-hub/dist/client/companion-api.js +0 -30
- package/superd-hub/dist/companion-contract.d.ts +0 -9
- package/superd-hub/dist/companion-contract.js +0 -1
- package/superd-hub/dist/companions.d.ts +0 -30
- package/superd-hub/dist/companions.js +0 -211
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* HermesGatewayClient — the reusable TUI-gateway client seam (AW-H Task 3).
|
|
3
3
|
*
|
|
4
|
-
* One client = one
|
|
5
|
-
* stdio
|
|
4
|
+
* One client = one gateway child bound to one gateway session. Transports:
|
|
5
|
+
* `stdio` spawns `python -m tui_gateway.entry` (owns the Hermes home
|
|
6
|
+
* exclusively); `attach` (SUPERD_HERMES_TRANSPORT=attach) spawns the
|
|
7
|
+
* WS-attach bridge — same stdio ndjson JSON-RPC contract, frames relayed to
|
|
8
|
+
* the profile's canonical gateway WebSocket; `auto` (default) = stdio first,
|
|
9
|
+
* flips to attach on the gateway ownership refusal (resolveHermesTransportMode).
|
|
6
10
|
* follow the upstream reference client `ui-tui/src/gatewayClient.ts` and the
|
|
7
11
|
* Task 1 spike (`src/spike.ts`, live-pinned protocol facts):
|
|
8
12
|
*
|
|
@@ -64,6 +68,7 @@ import { spawn, execFile } from "node:child_process";
|
|
|
64
68
|
import { existsSync, readFileSync } from "node:fs";
|
|
65
69
|
import { homedir } from "node:os";
|
|
66
70
|
import { delimiter, resolve, join } from "node:path";
|
|
71
|
+
import { fileURLToPath } from "node:url";
|
|
67
72
|
import { promisify } from "node:util";
|
|
68
73
|
import { prepareHermesNativePlugin } from "@pgmi-builds/superd-hub/foreign-native";
|
|
69
74
|
import { createInterface } from "node:readline";
|
|
@@ -166,6 +171,28 @@ export function loadHermesDotEnv() {
|
|
|
166
171
|
return {};
|
|
167
172
|
}
|
|
168
173
|
}
|
|
174
|
+
export function resolveHermesTransportMode(dotEnv = {}) {
|
|
175
|
+
const raw = (process.env.SUPERD_HERMES_TRANSPORT?.trim() || dotEnv.SUPERD_HERMES_TRANSPORT?.trim() || "auto").toLowerCase();
|
|
176
|
+
return raw === "stdio" || raw === "attach" ? raw : "auto";
|
|
177
|
+
}
|
|
178
|
+
/** The hermes-side refusal that makes stdio impossible while a resident
|
|
179
|
+
* gateway holds the home: `... is owned by a running gateway; attach to it
|
|
180
|
+
* instead` (hermes' own exit text, observed 2026-11-02 on PC + dev3). */
|
|
181
|
+
const GATEWAY_OWNERSHIP_REFUSAL = /owned by a running gateway/i;
|
|
182
|
+
/** Process-wide sticky: a resident gateway owns `~/.hermes`; every future
|
|
183
|
+
* spawn in this process (any client) skips the doomed stdio attempt. */
|
|
184
|
+
let gatewayOwnershipDetected = false;
|
|
185
|
+
/** Test-only: clear the sticky auto-attach flip between tests. */
|
|
186
|
+
export function resetHermesAutoAttachForTests() {
|
|
187
|
+
gatewayOwnershipDetected = false;
|
|
188
|
+
}
|
|
189
|
+
/** The WS-attach bridge script, shipped at the package root (`bridge/`). */
|
|
190
|
+
export function hermesBridgeScriptPath() {
|
|
191
|
+
const path = fileURLToPath(new URL("../bridge/hermes-ws-bridge.py", import.meta.url));
|
|
192
|
+
if (!existsSync(path))
|
|
193
|
+
throw new Error(`hermes ws-attach bridge missing: ${path}`);
|
|
194
|
+
return path;
|
|
195
|
+
}
|
|
169
196
|
function asRecord(value) {
|
|
170
197
|
if (value === null || typeof value !== "object" || Array.isArray(value))
|
|
171
198
|
return null;
|
|
@@ -196,6 +223,8 @@ export class HermesGatewayClient {
|
|
|
196
223
|
#readySettled = false;
|
|
197
224
|
/** Pre-ready respawn attempts (full-lazy ruling: bounded at SPAWN_ATTEMPTS). */
|
|
198
225
|
#spawnAttempts = 0;
|
|
226
|
+
/** Transport used by the CURRENT child attempt (drives the auto-attach flip). */
|
|
227
|
+
#transport = "stdio";
|
|
199
228
|
#readyTimer = null;
|
|
200
229
|
#killTimer = null;
|
|
201
230
|
#failure = null;
|
|
@@ -244,6 +273,13 @@ export class HermesGatewayClient {
|
|
|
244
273
|
const attempt = this.#spawnAttempts;
|
|
245
274
|
const root = resolveHermesRoot();
|
|
246
275
|
const python = resolveHermesPython(root);
|
|
276
|
+
const dotEnv = loadHermesDotEnv();
|
|
277
|
+
const mode = resolveHermesTransportMode(dotEnv);
|
|
278
|
+
// auto: stdio first; once a resident gateway's ownership refusal is seen,
|
|
279
|
+
// the whole process flips to attach (sticky — later clients skip the
|
|
280
|
+
// doomed stdio attempt entirely). Explicit stdio/attach never flip.
|
|
281
|
+
const transport = mode === "attach" || (mode === "auto" && gatewayOwnershipDetected) ? "attach" : "stdio";
|
|
282
|
+
this.#transport = transport;
|
|
247
283
|
const env = { ...(opts.env ?? process.env) };
|
|
248
284
|
if (this.#hubSession !== undefined)
|
|
249
285
|
env.SUPERD_HUB_SESSION = this.#hubSession;
|
|
@@ -253,7 +289,7 @@ export class HermesGatewayClient {
|
|
|
253
289
|
// pi runtimes load their own native `.env`; the hermes gateway child does
|
|
254
290
|
// not, and the harness env carries no provider keys — without this fill
|
|
255
291
|
// every provider request dies as quota/auth regardless of model.
|
|
256
|
-
for (const [dotKey, dotValue] of Object.entries(
|
|
292
|
+
for (const [dotKey, dotValue] of Object.entries(dotEnv)) {
|
|
257
293
|
if (env[dotKey] === undefined || env[dotKey] === "")
|
|
258
294
|
env[dotKey] = dotValue;
|
|
259
295
|
}
|
|
@@ -266,12 +302,11 @@ export class HermesGatewayClient {
|
|
|
266
302
|
delete env.HERMES_CWD;
|
|
267
303
|
delete env.HERMES_TUI_GATEWAY_URL;
|
|
268
304
|
delete env.HERMES_TUI_SIDECAR_URL;
|
|
269
|
-
|
|
270
|
-
command: python,
|
|
271
|
-
args: ["-m", "tui_gateway.entry"],
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
});
|
|
305
|
+
const childSpec = transport === "attach"
|
|
306
|
+
? { command: python, args: [hermesBridgeScriptPath()], cwd: opts.cwd ?? root, env }
|
|
307
|
+
: { command: python, args: ["-m", "tui_gateway.entry"], cwd: opts.cwd ?? root, env };
|
|
308
|
+
this.#trace(`spawn transport=${transport} cmd=${childSpec.command} args=${JSON.stringify(childSpec.args)}`);
|
|
309
|
+
this.#child = gatewayFactory(childSpec);
|
|
275
310
|
// The ready gate is created ONCE and survives every pre-ready respawn —
|
|
276
311
|
// replacing it would orphan callers awaiting the earlier object.
|
|
277
312
|
if (this.#readyPromise === null) {
|
|
@@ -283,7 +318,9 @@ export class HermesGatewayClient {
|
|
|
283
318
|
// surface an unhandledRejection when this gate rejects (timeout/close).
|
|
284
319
|
this.#readyPromise.catch(() => { });
|
|
285
320
|
}
|
|
286
|
-
|
|
321
|
+
// attach: gateway discovery (5s) or an idle-exit daemon start (ensure
|
|
322
|
+
// timeout 30s) can exceed the stdio boot budget before gateway.ready.
|
|
323
|
+
const readyTimeoutMs = opts.readyTimeoutMs ?? (transport === "attach" ? 45_000 : READY_TIMEOUT_MS);
|
|
287
324
|
this.#readyTimer = setTimeout(() => {
|
|
288
325
|
this.#preReadyFailure(new Error(`timed out waiting for gateway.ready after ${readyTimeoutMs}ms (spawn attempt ${attempt}/${HERMES_SPAWN_ATTEMPTS}); stderr tail:\n${this.#stderrTail()}`));
|
|
289
326
|
}, readyTimeoutMs);
|
|
@@ -924,6 +961,10 @@ export class HermesGatewayClient {
|
|
|
924
961
|
this.#fail(error);
|
|
925
962
|
return;
|
|
926
963
|
}
|
|
964
|
+
if (!gatewayOwnershipDetected && this.#transport === "stdio" && GATEWAY_OWNERSHIP_REFUSAL.test(error.message)) {
|
|
965
|
+
gatewayOwnershipDetected = true;
|
|
966
|
+
this.#trace("gateway ownership refusal in spawn failure — auto-attach engaged for future spawns");
|
|
967
|
+
}
|
|
927
968
|
if (this.#spawnAttempts < HERMES_SPAWN_ATTEMPTS) {
|
|
928
969
|
this.#trace(`pre-ready failure on spawn attempt ${this.#spawnAttempts}/${HERMES_SPAWN_ATTEMPTS} — respawning: ${error.message.slice(0, 200)}`);
|
|
929
970
|
this.#discardChildQuietly();
|
|
@@ -1019,6 +1060,10 @@ export class HermesGatewayClient {
|
|
|
1019
1060
|
if (this.#stderrLines.length > STDERR_RING)
|
|
1020
1061
|
this.#stderrLines.shift();
|
|
1021
1062
|
this.#trace(`stderr: ${trimmed.slice(0, 240)}`);
|
|
1063
|
+
if (!gatewayOwnershipDetected && this.#transport === "stdio" && GATEWAY_OWNERSHIP_REFUSAL.test(trimmed)) {
|
|
1064
|
+
gatewayOwnershipDetected = true;
|
|
1065
|
+
this.#trace("gateway ownership refusal on stderr — auto-attach engaged for future spawns");
|
|
1066
|
+
}
|
|
1022
1067
|
}
|
|
1023
1068
|
#stderrTail() {
|
|
1024
1069
|
return this.#stderrLines.slice(-20).join("\n");
|
|
@@ -364,9 +364,18 @@ export class HermesProvider extends Service {
|
|
|
364
364
|
throw new Error(`cannot resume session "${id}": no Hermes gateway session is recorded for this Dash session id`);
|
|
365
365
|
}
|
|
366
366
|
const persistence = this.requirePersistence("resume");
|
|
367
|
-
if (
|
|
368
|
-
|
|
369
|
-
|
|
367
|
+
if (record.gatewayStoredSessionId === null || record.gatewayStoredSessionId === undefined) {
|
|
368
|
+
const events = await readStoredEvents(persistence, id, options.signal);
|
|
369
|
+
if (events.some(event => event.type === "turn/start" || event.type === "user/message" || event.type === "assistant/message")) {
|
|
370
|
+
if (events.some(event => event.type === "assistant/message")) {
|
|
371
|
+
// Completed turns but no durable id: a record from before the adapter captured ids.
|
|
372
|
+
throw new Error(`cannot resume session "${id}": no durable gateway session id is recorded (this record predates durable-id capture; re-create the session)`);
|
|
373
|
+
}
|
|
374
|
+
// Turn content with no assistant output and no durable id: the gateway never produced a
|
|
375
|
+
// session for this record (cold-start failure — e.g. the native home was owned by a
|
|
376
|
+
// running gateway). Nothing in it reached the model, so resume has nothing to attach to.
|
|
377
|
+
throw new Error(`cannot resume session "${id}": no durable gateway session id is recorded (the Hermes gateway failed before this session was created; its recorded turn never reached the model — re-create the session)`);
|
|
378
|
+
}
|
|
370
379
|
}
|
|
371
380
|
// Spawn cwd comes from the recorded pairing — re-realpath and re-verify.
|
|
372
381
|
const spawnCwd = validatedCwd(record.cwd);
|
|
@@ -26,13 +26,13 @@
|
|
|
26
26
|
},
|
|
27
27
|
"peerDependencies": {
|
|
28
28
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
29
|
-
"@deepseek-ai/dsh-agent": ">=0.2.
|
|
30
|
-
"@deepseek-ai/dsh-agent-presets": ">=0.2.
|
|
31
|
-
"@deepseek-ai/dsh-llm": ">=0.2.
|
|
32
|
-
"@deepseek-ai/dsh-scope": ">=0.2.
|
|
33
|
-
"@deepseek-ai/dsh-session": ">=0.2.
|
|
34
|
-
"@deepseek-ai/dsh-session-persistence": ">=0.2.
|
|
35
|
-
"@deepseek-ai/dsh-typert-protocol": ">=0.2.
|
|
29
|
+
"@deepseek-ai/dsh-agent": ">=0.2.0-0 <1.0.0-0",
|
|
30
|
+
"@deepseek-ai/dsh-agent-presets": ">=0.2.0-0 <1.0.0-0",
|
|
31
|
+
"@deepseek-ai/dsh-llm": ">=0.2.0-0 <1.0.0-0",
|
|
32
|
+
"@deepseek-ai/dsh-scope": ">=0.2.0-0 <1.0.0-0",
|
|
33
|
+
"@deepseek-ai/dsh-session": ">=0.2.0-0 <1.0.0-0",
|
|
34
|
+
"@deepseek-ai/dsh-session-persistence": ">=0.2.0-0 <1.0.0-0",
|
|
35
|
+
"@deepseek-ai/dsh-typert-protocol": ">=0.2.0-0 <1.0.0-0",
|
|
36
36
|
"@pgmi-builds/superd-hub": "*"
|
|
37
37
|
},
|
|
38
38
|
"peerDependenciesMeta": {
|
package/agent-omp/package.json
CHANGED
|
@@ -34,14 +34,14 @@
|
|
|
34
34
|
"dependencies": {},
|
|
35
35
|
"peerDependencies": {
|
|
36
36
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
37
|
-
"@deepseek-ai/dsh-agent": ">=0.2.
|
|
38
|
-
"@deepseek-ai/dsh-agent-presets": ">=0.2.
|
|
39
|
-
"@deepseek-ai/dsh-llm": ">=0.2.
|
|
40
|
-
"@deepseek-ai/dsh-scope": ">=0.2.
|
|
41
|
-
"@deepseek-ai/dsh-session": ">=0.2.
|
|
42
|
-
"@deepseek-ai/dsh-session-persistence": ">=0.2.
|
|
43
|
-
"@deepseek-ai/dsh-typert-protocol": ">=0.2.
|
|
44
|
-
"@deepseek-ai/dsh-home-paths": ">=0.2.
|
|
37
|
+
"@deepseek-ai/dsh-agent": ">=0.2.0-0 <1.0.0-0",
|
|
38
|
+
"@deepseek-ai/dsh-agent-presets": ">=0.2.0-0 <1.0.0-0",
|
|
39
|
+
"@deepseek-ai/dsh-llm": ">=0.2.0-0 <1.0.0-0",
|
|
40
|
+
"@deepseek-ai/dsh-scope": ">=0.2.0-0 <1.0.0-0",
|
|
41
|
+
"@deepseek-ai/dsh-session": ">=0.2.0-0 <1.0.0-0",
|
|
42
|
+
"@deepseek-ai/dsh-session-persistence": ">=0.2.0-0 <1.0.0-0",
|
|
43
|
+
"@deepseek-ai/dsh-typert-protocol": ">=0.2.0-0 <1.0.0-0",
|
|
44
|
+
"@deepseek-ai/dsh-home-paths": ">=0.2.0-0 <1.0.0-0",
|
|
45
45
|
"@pgmi-builds/superd-hub": "*"
|
|
46
46
|
},
|
|
47
47
|
"peerDependenciesMeta": {
|
|
@@ -26,14 +26,14 @@
|
|
|
26
26
|
"dependencies": {},
|
|
27
27
|
"peerDependencies": {
|
|
28
28
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
29
|
-
"@deepseek-ai/dsh-agent": ">=0.2.
|
|
30
|
-
"@deepseek-ai/dsh-agent-presets": ">=0.2.
|
|
31
|
-
"@deepseek-ai/dsh-llm": ">=0.2.
|
|
32
|
-
"@deepseek-ai/dsh-scope": ">=0.2.
|
|
33
|
-
"@deepseek-ai/dsh-session": ">=0.2.
|
|
34
|
-
"@deepseek-ai/dsh-session-persistence": ">=0.2.
|
|
35
|
-
"@deepseek-ai/dsh-typert-protocol": ">=0.2.
|
|
36
|
-
"@deepseek-ai/dsh-home-paths": ">=0.2.
|
|
29
|
+
"@deepseek-ai/dsh-agent": ">=0.2.0-0 <1.0.0-0",
|
|
30
|
+
"@deepseek-ai/dsh-agent-presets": ">=0.2.0-0 <1.0.0-0",
|
|
31
|
+
"@deepseek-ai/dsh-llm": ">=0.2.0-0 <1.0.0-0",
|
|
32
|
+
"@deepseek-ai/dsh-scope": ">=0.2.0-0 <1.0.0-0",
|
|
33
|
+
"@deepseek-ai/dsh-session": ">=0.2.0-0 <1.0.0-0",
|
|
34
|
+
"@deepseek-ai/dsh-session-persistence": ">=0.2.0-0 <1.0.0-0",
|
|
35
|
+
"@deepseek-ai/dsh-typert-protocol": ">=0.2.0-0 <1.0.0-0",
|
|
36
|
+
"@deepseek-ai/dsh-home-paths": ">=0.2.0-0 <1.0.0-0",
|
|
37
37
|
"@pgmi-builds/superd-hub": "*"
|
|
38
38
|
},
|
|
39
39
|
"peerDependenciesMeta": {
|
package/agent-pi/package.json
CHANGED
|
@@ -27,13 +27,13 @@
|
|
|
27
27
|
},
|
|
28
28
|
"peerDependencies": {
|
|
29
29
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
30
|
-
"@deepseek-ai/dsh-agent": ">=0.2.
|
|
31
|
-
"@deepseek-ai/dsh-agent-presets": ">=0.2.
|
|
32
|
-
"@deepseek-ai/dsh-llm": ">=0.2.
|
|
33
|
-
"@deepseek-ai/dsh-scope": ">=0.2.
|
|
34
|
-
"@deepseek-ai/dsh-session": ">=0.2.
|
|
35
|
-
"@deepseek-ai/dsh-session-persistence": ">=0.2.
|
|
36
|
-
"@deepseek-ai/dsh-typert-protocol": ">=0.2.
|
|
30
|
+
"@deepseek-ai/dsh-agent": ">=0.2.0-0 <1.0.0-0",
|
|
31
|
+
"@deepseek-ai/dsh-agent-presets": ">=0.2.0-0 <1.0.0-0",
|
|
32
|
+
"@deepseek-ai/dsh-llm": ">=0.2.0-0 <1.0.0-0",
|
|
33
|
+
"@deepseek-ai/dsh-scope": ">=0.2.0-0 <1.0.0-0",
|
|
34
|
+
"@deepseek-ai/dsh-session": ">=0.2.0-0 <1.0.0-0",
|
|
35
|
+
"@deepseek-ai/dsh-session-persistence": ">=0.2.0-0 <1.0.0-0",
|
|
36
|
+
"@deepseek-ai/dsh-typert-protocol": ">=0.2.0-0 <1.0.0-0",
|
|
37
37
|
"@pgmi-builds/superd-hub": "*"
|
|
38
38
|
},
|
|
39
39
|
"peerDependenciesMeta": {
|