super-dsh 0.1.3-c → 0.1.3-g

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.
@@ -122,6 +122,8 @@ let SingleAgyPresetRoster = (() => {
122
122
  },
123
123
  ],
124
124
  authorable: this.authorable,
125
+ // 0.1.6 AgentPresetRoster: unnamed new sessions may pick a mode (our preset table).
126
+ modeSelectionEnabled: true,
125
127
  };
126
128
  }
127
129
  async remoteRead(agentPreset) {
@@ -1,3 +1,4 @@
1
+ /** Prod homes that must never be resolved into (repo red line). */
1
2
  /** One persisted DSH → Antigravity conversation pairing. */
2
3
  export interface AgySessionRecord {
3
4
  /** The SDK conversation id; `null` until the first turn materializes it. */
@@ -12,7 +13,7 @@ export interface AgySessionRecord {
12
13
  export type AgySessionMap = Record<string, AgySessionRecord>;
13
14
  /**
14
15
  * The adapter's DSH-side world home. Form-A (boot home = DSH home root) nests
15
- * `agents/agy`; Form-B (already `<root>/agents/agy`) passes through. Prod-guarded.
16
+ * `agents/agy`; Form-B (already `<root>/agents/agy`) passes through.
16
17
  */
17
18
  export declare function resolveAgyWorldHome(home?: string): string;
18
19
  export declare function sessionMapPath(home?: string): string;
@@ -12,25 +12,14 @@
12
12
  * `conversationId` is `null` until the first turn materializes it.
13
13
  */
14
14
  import { mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from "node:fs";
15
- import { homedir } from "node:os";
16
15
  import { basename, dirname, join, resolve } from "node:path";
17
- /** Prod homes that must never be resolved into (repo red line). */
18
- const PROD_HOMES = [join(homedir(), ".dsh"), join(homedir(), ".superd")];
19
- function assertNotProdHome(path, label) {
20
- if (process.env.SUPERD_DEV_REDLINE !== "1")
21
- return; // published install: the host dsh home (~/.dsh on consumers) is authoritative — the S3/S7 world layout lives under it. Dev lines set SUPERD_DEV_REDLINE=1 (repo red line: ~/.dsh is Dash prod).
22
- if (PROD_HOMES.includes(path) || PROD_HOMES.some((p) => path.startsWith(`${p}/`))) {
23
- throw new Error(`agy-sessions: refusing prod home as ${label}: ${path}`);
24
- }
25
- }
26
16
  /**
27
17
  * The adapter's DSH-side world home. Form-A (boot home = DSH home root) nests
28
- * `agents/agy`; Form-B (already `<root>/agents/agy`) passes through. Prod-guarded.
18
+ * `agents/agy`; Form-B (already `<root>/agents/agy`) passes through.
29
19
  */
30
20
  export function resolveAgyWorldHome(home) {
31
21
  const base = resolve(home ?? process.env.DSH_HOME ?? join(process.cwd(), ".tests", "aw"));
32
22
  const dir = basename(base) === "agy" && basename(dirname(base)) === "agents" ? base : join(base, "agents", "agy");
33
- assertNotProdHome(dir, "agy world home");
34
23
  return dir;
35
24
  }
36
25
  export function sessionMapPath(home) {
@@ -19,7 +19,7 @@
19
19
  import { realpathSync, statSync } from "node:fs";
20
20
  import { join } from "node:path";
21
21
  import { Service } from "@deepseek-ai/cordis";
22
- import { emitAgentEvent, installModelSelection } from "@deepseek-ai/dsh-agent";
22
+ import { installModelSelection } from "@deepseek-ai/dsh-agent";
23
23
  import { SessionLogOffset, SessionPreparation, interruptedTurnClosers, } from "@deepseek-ai/dsh-session";
24
24
  import { AgyBridgeClient } from "./agy-client.js";
25
25
  import { AgyCliClient } from "./agy-cli-client.js";
@@ -464,8 +464,9 @@ async function setupAndPublish(loopCtx, ownerCtx, id, agentOptions, setup, sessi
464
464
  agent.ctx.sessions.announce(session);
465
465
  }
466
466
  detachAgent = loopCtx.agents.enter(agent, parentAgent);
467
- loopCtx.agents.announce(agent);
468
- emitAgentEvent(loopCtx, agent, "agent/session-start", { source });
467
+ // 0.1.6: announce(agent, source) is required, async, and emits agent/created
468
+ // itself — the manual agent/session-start emission is gone upstream.
469
+ await loopCtx.agents.announce(agent, source);
469
470
  let disposed = false;
470
471
  let unfollowOwner;
471
472
  const dispose = async () => {
@@ -16,12 +16,10 @@
16
16
  import { mkdirSync } from 'node:fs';
17
17
  import { resolveDshHome } from '@deepseek-ai/dsh-home-paths';
18
18
  import { join } from 'node:path';
19
- import { spawnWorld, registerAgent, setReady, registerForeignTarget, registerHostMount, mountWorld, worldMountPatches, provisionWorldProfile, } from '../../agent-hub/dist/index.js';
19
+ import { spawnWorld, registerAgent, setReady, registerForeignTarget, registerHostMount, mountWorld, worldMountPatches, provisionWorldProfile, resolveInstallAnchor, } from '../../agent-hub/dist/index.js';
20
20
  export const name = 'aw.agent-adapter-agy';
21
21
  /** Runtime key — also the mount label. */
22
22
  const KEY = 'agy';
23
- const ANCHOR = process.env.SUPERD_DSH_ANCHOR
24
- ?? '/home/u1/.local/lib/node_modules/@deepseek-ai/dsh/package.json';
25
23
  export function apply(ctx) {
26
24
  registerAgent({ key: KEY, label: 'Antigravity', ready: false });
27
25
  // Harness resolver (env → ~/.dsh): a consumer install has no DSH_HOME and
@@ -62,7 +60,7 @@ export function apply(ctx) {
62
60
  const ctxW = await spawnWorld({
63
61
  appName: `aw-${KEY}`,
64
62
  profileName: 'web',
65
- installAnchor: ANCHOR,
63
+ installAnchor: resolveInstallAnchor(), // lazy: never at module scope — import must stay side-effect-free
66
64
  home: worldHome,
67
65
  dataHome: worldHome,
68
66
  // Adapter-local bundle names resolve from the profile's own
@@ -54,16 +54,35 @@
54
54
  * every push is queued in order and there is no separate follow-up channel.
55
55
  * `steer` differs by pushing with `priority: "now"`.
56
56
  */
57
+ import { existsSync } from "node:fs";
58
+ import { homedir } from "node:os";
59
+ import { join } from "node:path";
57
60
  import { query as officialQuery } from "@anthropic-ai/claude-agent-sdk";
58
61
  import { InputQueue } from "./input-queue.js";
59
62
  import { projectClaudeEvent } from "./claude-events.js";
60
- /** Host Claude Code binary driven through the SDK's bridge (spec ruling R5). */
61
- export const DEFAULT_CLAUDE_EXECUTABLE = "/home/u1/.local/bin/claude";
63
+ /** Host Claude Code binary driven through the SDK bridge (spec ruling R5).
64
+ * PATH-resolved like any host CLI: $CLAUDE_EXECUTABLE wins, else a bare
65
+ * "claude" the SDK spawns through PATH. No machine-specific path ships. */
66
+ export const DEFAULT_CLAUDE_EXECUTABLE = "claude";
62
67
  const defaultFactory = (o) => officialQuery({
63
68
  prompt: o.prompt,
64
69
  options: o.options,
65
70
  });
66
- const defaultExecutableResolver = () => process.env.CLAUDE_EXECUTABLE ?? DEFAULT_CLAUDE_EXECUTABLE;
71
+ const defaultExecutableResolver = () => process.env.CLAUDE_EXECUTABLE ?? resolveClaudeExecutable();
72
+ /** PATH first, then the common native-installer locations (a service unit
73
+ * PATH may not include ~/.local/bin — dev3 2026-09-22: "native binary not
74
+ * found at claude" mid-session). */
75
+ function resolveClaudeExecutable() {
76
+ for (const dir of (process.env.PATH ?? "").split(":").filter(Boolean)) {
77
+ if (existsSync(join(dir, "claude")))
78
+ return DEFAULT_CLAUDE_EXECUTABLE;
79
+ }
80
+ for (const candidate of [join(homedir(), ".local/bin/claude"), "/usr/local/bin/claude"]) {
81
+ if (existsSync(candidate))
82
+ return candidate;
83
+ }
84
+ return DEFAULT_CLAUDE_EXECUTABLE;
85
+ }
67
86
  let factory = defaultFactory;
68
87
  let executableResolver = defaultExecutableResolver;
69
88
  let refcount = 0;
@@ -9,16 +9,7 @@
9
9
  */
10
10
  import { homedir } from "node:os";
11
11
  import { join, resolve } from "node:path";
12
- const PROD_HOMES = [join(homedir(), ".dsh"), join(homedir(), ".superd")];
13
12
  /** Refuse any path that resolves into a production DSH home (repo red line). */
14
- export function assertNotProdHome(path, label) {
15
- if (process.env.SUPERD_DEV_REDLINE !== "1")
16
- return; // published install: the host dsh home (~/.dsh on consumers) is authoritative — the S3/S7 world layout lives under it. Dev lines set SUPERD_DEV_REDLINE=1 (repo red line: ~/.dsh is Dash prod).
17
- const p = resolve(path);
18
- if (PROD_HOMES.includes(p) || PROD_HOMES.some((prod) => p.startsWith(`${prod}/`))) {
19
- throw new Error(`agent-claude: refusing prod home "${p}" for ${label} — set DSH_HOME to the test home`);
20
- }
21
- }
22
13
  /**
23
14
  * The Claude app home: the NATIVE `~/.claude`, prod-home guarded. An ambient
24
15
  * `CLAUDE_CONFIG_DIR` wins (tests pin an isolated home that way); the adapter
@@ -26,6 +17,5 @@ export function assertNotProdHome(path, label) {
26
17
  */
27
18
  export function resolveClaudeHome() {
28
19
  const claudeHome = resolve(process.env.CLAUDE_CONFIG_DIR ?? join(homedir(), ".claude"));
29
- assertNotProdHome(claudeHome, "claudeHome");
30
20
  return claudeHome;
31
21
  }
@@ -26,23 +26,20 @@
26
26
  */
27
27
  import { existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from "node:fs";
28
28
  import { dirname, join, resolve } from "node:path";
29
- import { assertNotProdHome } from "./claude-home.js";
30
29
  /**
31
30
  * The adapter's DSH-side state dir — the world's DSH home root
32
31
  * (`<dshHome>/agents/claude`), never the Claude app home. Precedence:
33
32
  * explicit world home (boot-provided `dshHomePath`), then `$DSH_HOME` (a hub
34
33
  * home, so the world layout nests `agents/claude`), then the line's
35
- * historical test-home default. Prod-guarded.
34
+ * historical test-home default.
36
35
  */
37
36
  export function resolveClaudeStateDir(home) {
38
37
  if (home !== undefined) {
39
38
  const dir = resolve(home);
40
- assertNotProdHome(dir, "claude state dir");
41
39
  return dir;
42
40
  }
43
41
  const fallbackHome = resolve(process.env.DSH_HOME ?? join(process.cwd(), ".tests", "aw"));
44
42
  const dir = join(fallbackHome, "agents", "claude");
45
- assertNotProdHome(dir, "claude state dir");
46
43
  return dir;
47
44
  }
48
45
  /** The map file's path at the world DSH-home root. */
@@ -20,14 +20,6 @@ import { closeSync, openSync, readdirSync, readSync, statSync } from "node:fs";
20
20
  import { homedir } from "node:os";
21
21
  import { join, resolve } from "node:path";
22
22
  /** Prod homes that must never be resolved into (repo red line). */
23
- const PROD_HOMES = [join(homedir(), ".dsh"), join(homedir(), ".superd")];
24
- export function assertNotProdHome(path, label) {
25
- if (process.env.SUPERD_DEV_REDLINE !== "1")
26
- return; // published install: the host dsh home (~/.dsh on consumers) is authoritative — the S3/S7 world layout lives under it. Dev lines set SUPERD_DEV_REDLINE=1 (repo red line: ~/.dsh is Dash prod).
27
- if (PROD_HOMES.includes(path) || PROD_HOMES.some((p) => path.startsWith(`${p}/`))) {
28
- throw new Error(`codex-store: refusing prod home as ${label}: ${path}`);
29
- }
30
- }
31
23
  /**
32
24
  * Resolve the Codex CLI's app-data home — the NATIVE `~/.codex` (user ruling
33
25
  * 2026-09-17, pi precedent): the installed app keeps its own home, so the
@@ -44,11 +36,9 @@ export function assertNotProdHome(path, label) {
44
36
  export function resolveCodexHome() {
45
37
  if (process.env.CODEX_HOME !== undefined) {
46
38
  const env = resolve(process.env.CODEX_HOME);
47
- assertNotProdHome(env, "codex home");
48
39
  return env;
49
40
  }
50
41
  const native = join(homedir(), ".codex");
51
- assertNotProdHome(native, "codex home");
52
42
  return native;
53
43
  }
54
44
  /**
@@ -58,7 +48,6 @@ export function resolveCodexHome() {
58
48
  */
59
49
  export function useCodexHome(path) {
60
50
  const resolved = resolve(path);
61
- assertNotProdHome(resolved, "codex home");
62
51
  return resolved;
63
52
  }
64
53
  /** Bounded read budget: `session_meta` is the FIRST line, so this is generous. */
@@ -19,7 +19,6 @@
19
19
  */
20
20
  import { existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from "node:fs";
21
21
  import { dirname, join, resolve } from "node:path";
22
- import { assertNotProdHome } from "./codex-store.js";
23
22
  /** An `Error` carrying a stable {@link CodexResumeErrorCode}. */
24
23
  export class CodexResumeError extends Error {
25
24
  code;
@@ -35,17 +34,15 @@ export class CodexResumeError extends Error {
35
34
  * (`<dshHome>/agents/codex`), never the codex app home. Precedence: explicit
36
35
  * world home (boot-provided `dshHomePath`), then `$DSH_HOME` (a hub home, so
37
36
  * the world layout nests `agents/codex`), then the line's historical test-home
38
- * default. Prod-guarded.
37
+ * default.
39
38
  */
40
39
  export function resolveCodexStateDir(home) {
41
40
  if (home !== undefined) {
42
41
  const dir = resolve(home);
43
- assertNotProdHome(dir, "codex state dir");
44
42
  return dir;
45
43
  }
46
44
  const fallbackHome = resolve(process.env.DSH_HOME ?? join(process.cwd(), ".tests", "aw"));
47
45
  const dir = join(fallbackHome, "agents", "codex");
48
- assertNotProdHome(dir, "codex state dir");
49
46
  return dir;
50
47
  }
51
48
  /** The map file's path at the world DSH-home root. */
@@ -16,12 +16,10 @@
16
16
  import { mkdirSync } from 'node:fs';
17
17
  import { resolveDshHome } from '@deepseek-ai/dsh-home-paths';
18
18
  import { join } from 'node:path';
19
- import { spawnWorld, registerAgent, setReady, registerForeignTarget, registerHostMount, mountWorld, worldMountPatches, provisionWorldProfile, } from '../../agent-hub/dist/index.js';
19
+ import { spawnWorld, registerAgent, setReady, registerForeignTarget, registerHostMount, mountWorld, worldMountPatches, provisionWorldProfile, resolveInstallAnchor, } from '../../agent-hub/dist/index.js';
20
20
  export const name = 'aw.agent-adapter-codex';
21
21
  /** Runtime key — also the mount label. */
22
22
  const KEY = 'codex';
23
- const ANCHOR = process.env.SUPERD_DSH_ANCHOR
24
- ?? '/home/u1/.local/lib/node_modules/@deepseek-ai/dsh/package.json';
25
23
  export function apply(ctx) {
26
24
  registerAgent({ key: KEY, label: 'Codex', ready: false });
27
25
  // Harness resolver (env → ~/.dsh): a consumer install has no DSH_HOME and
@@ -61,7 +59,7 @@ export function apply(ctx) {
61
59
  const ctxW = await spawnWorld({
62
60
  appName: `aw-${KEY}`,
63
61
  profileName: 'web',
64
- installAnchor: ANCHOR,
62
+ installAnchor: resolveInstallAnchor(), // lazy: never at module scope — import must stay side-effect-free
65
63
  home: worldHome,
66
64
  dataHome: worldHome,
67
65
  // Adapter-local bundle names resolve from the profile's own
@@ -24,7 +24,6 @@
24
24
  "dependencies": {
25
25
  "@openai/codex": "0.154.0",
26
26
  "@openai/codex-sdk": "0.154.0",
27
- "@pgmi-builds/agent-hub": "file:../agent-hub",
28
27
  "zod": "3.25.76"
29
28
  },
30
29
  "peerDependencies": {
@@ -35,7 +34,8 @@
35
34
  "@deepseek-ai/dsh-scope": "0.1.5-rc.2",
36
35
  "@deepseek-ai/dsh-session": "0.1.5-rc.2",
37
36
  "@deepseek-ai/dsh-session-persistence": "0.1.5-rc.2",
38
- "@deepseek-ai/dsh-typert-protocol": "0.1.5-rc.2"
37
+ "@deepseek-ai/dsh-typert-protocol": "0.1.5-rc.2",
38
+ "@pgmi-builds/agent-hub": "*"
39
39
  },
40
40
  "peerDependenciesMeta": {
41
41
  "@deepseek-ai/cordis": {
@@ -61,6 +61,9 @@
61
61
  },
62
62
  "@deepseek-ai/dsh-typert-protocol": {
63
63
  "optional": true
64
+ },
65
+ "@pgmi-builds/agent-hub": {
66
+ "optional": true
64
67
  }
65
68
  },
66
69
  "devDependencies": {
@@ -19,17 +19,7 @@
19
19
  * degrades to "unknown session" rather than breaking every operation.
20
20
  */
21
21
  import { existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from "node:fs";
22
- import { homedir } from "node:os";
23
22
  import { basename, dirname, join, resolve } from "node:path";
24
- /** Prod homes that must never be resolved into (repo red line). */
25
- const PROD_HOMES = [join(homedir(), ".dsh"), join(homedir(), ".superd")];
26
- function assertNotProdHome(path, label) {
27
- if (process.env.SUPERD_DEV_REDLINE !== "1")
28
- return; // published install: the host dsh home (~/.dsh on consumers) is authoritative — the S3/S7 world layout lives under it. Dev lines set SUPERD_DEV_REDLINE=1 (repo red line: ~/.dsh is Dash prod).
29
- if (PROD_HOMES.includes(path) || PROD_HOMES.some((p) => path.startsWith(`${p}/`))) {
30
- throw new Error(`hermes-store: refusing prod home as ${label}: ${path}`);
31
- }
32
- }
33
23
  /**
34
24
  * The adapter's DSH-side state dir — `<dshHome>/agents/hermes`. This is DSH-SIDE
35
25
  * adapter state (the identity map), NOT hermes data: hermes keeps its native
@@ -42,13 +32,12 @@ function assertNotProdHome(path, label) {
42
32
  * - Form-B: the boot-provided home is ALREADY the world home
43
33
  * (`<root>/agents/hermes`) — passed through as-is, never double-nested.
44
34
  * Precedence: explicit home (boot-provided `dshHomePath`), then `$DSH_HOME`,
45
- * then the line's historical test-home default. Prod-guarded.
35
+ * then the line's historical test-home default.
46
36
  */
47
37
  export function resolveHermesAppDir(home) {
48
38
  const base = resolve(home ?? process.env.DSH_HOME ?? join(process.cwd(), ".tests", "aw"));
49
39
  // Form-B world home is already `<root>/agents/hermes` — never double-nest.
50
40
  const dir = basename(base) === "hermes" && basename(dirname(base)) === "agents" ? base : join(base, "agents", "hermes");
51
- assertNotProdHome(dir, "hermes app dir");
52
41
  return dir;
53
42
  }
54
43
  /** The map file's path inside the adapter's DSH-side app dir. */
@@ -17,12 +17,10 @@
17
17
  import { mkdirSync } from 'node:fs';
18
18
  import { resolveDshHome } from '@deepseek-ai/dsh-home-paths';
19
19
  import { join } from 'node:path';
20
- import { spawnWorld, registerAgent, setReady, registerForeignTarget, registerHostMount, mountWorld, worldMountPatches, provisionWorldProfile, } from '../../agent-hub/dist/index.js';
20
+ import { spawnWorld, registerAgent, setReady, registerForeignTarget, registerHostMount, mountWorld, worldMountPatches, provisionWorldProfile, resolveInstallAnchor, } from '../../agent-hub/dist/index.js';
21
21
  export const name = 'aw.agent-adapter-hermes';
22
22
  /** Runtime key — also the mount label. */
23
23
  const KEY = 'hermes';
24
- const ANCHOR = process.env.SUPERD_DSH_ANCHOR
25
- ?? '/home/u1/.local/lib/node_modules/@deepseek-ai/dsh/package.json';
26
24
  export function apply(ctx) {
27
25
  registerAgent({ key: KEY, label: 'Hermes', ready: false });
28
26
  // Harness resolver (env → ~/.dsh): a consumer install has no DSH_HOME and
@@ -66,7 +64,7 @@ export function apply(ctx) {
66
64
  const ctxW = await spawnWorld({
67
65
  appName: `aw-${KEY}`,
68
66
  profileName: 'web',
69
- installAnchor: ANCHOR,
67
+ installAnchor: resolveInstallAnchor(), // lazy: never at module scope — import must stay side-effect-free
70
68
  home: worldHome,
71
69
  dataHome: worldHome,
72
70
  // Adapter-local bundle names resolve from the profile's own
@@ -22,7 +22,6 @@
22
22
  "test": "node --test test/*.test.mjs"
23
23
  },
24
24
  "dependencies": {
25
- "@pgmi-builds/agent-hub": "file:../agent-hub",
26
25
  "zod": "3.25.76"
27
26
  },
28
27
  "peerDependencies": {
@@ -33,7 +32,8 @@
33
32
  "@deepseek-ai/dsh-scope": "0.1.5-rc.2",
34
33
  "@deepseek-ai/dsh-session": "0.1.5-rc.2",
35
34
  "@deepseek-ai/dsh-session-persistence": "0.1.5-rc.2",
36
- "@deepseek-ai/dsh-typert-protocol": "0.1.5-rc.2"
35
+ "@deepseek-ai/dsh-typert-protocol": "0.1.5-rc.2",
36
+ "@pgmi-builds/agent-hub": "*"
37
37
  },
38
38
  "peerDependenciesMeta": {
39
39
  "@deepseek-ai/cordis": {
@@ -59,6 +59,9 @@
59
59
  },
60
60
  "@deepseek-ai/dsh-typert-protocol": {
61
61
  "optional": true
62
+ },
63
+ "@pgmi-builds/agent-hub": {
64
+ "optional": true
62
65
  }
63
66
  },
64
67
  "devDependencies": {
@@ -13,7 +13,7 @@ export { handleAgentRuntime, registerSelectorRpc, AGENT_RUNTIME_RPC_PATH, regist
13
13
  export { registerForeignTarget, unregisterForeignTarget, getTarget, listRuntimeKeys, type ForeignTarget, type GatewayFace } from './targets.js';
14
14
  export { registerAgent, unregisterAgent, setReady, listAgents, onRosterChanged, type RosterEntry } from './roster.js';
15
15
  export { spawnWorld, type SpawnWorldOptions } from './spawn-world.js';
16
- export { provisionWorldProfile, type ProvisionWorldOptions } from './world-provision.js';
16
+ export { provisionWorldProfile, resolveInstallAnchor, type ProvisionWorldOptions } from './world-provision.js';
17
17
  export { claimLabel, labelOf, releaseLabel, listLabels, type LabelClaim, type ClaimOptions } from './labels.js';
18
18
  export { WorldWebServer, stripLabelFromUrl, type WorldWebRoute, type WorldWebUpgradeRoute, type RealWebServerFace } from './world-web-server.js';
19
19
  export { parseClientRequest, serverResponse, serverError, serverResult, wireErrorOf, EnvelopeError, type ClientRequestEnvelope, type WireError } from './envelope.js';
@@ -13,7 +13,7 @@ export { handleAgentRuntime, registerSelectorRpc, AGENT_RUNTIME_RPC_PATH, regist
13
13
  export { registerForeignTarget, unregisterForeignTarget, getTarget, listRuntimeKeys } from './targets.js';
14
14
  export { registerAgent, unregisterAgent, setReady, listAgents, onRosterChanged } from './roster.js';
15
15
  export { spawnWorld } from './spawn-world.js';
16
- export { provisionWorldProfile } from './world-provision.js';
16
+ export { provisionWorldProfile, resolveInstallAnchor } from './world-provision.js';
17
17
  export { claimLabel, labelOf, releaseLabel, listLabels } from './labels.js';
18
18
  export { WorldWebServer, stripLabelFromUrl } from './world-web-server.js';
19
19
  export { parseClientRequest, serverResponse, serverError, serverResult, wireErrorOf, EnvelopeError } from './envelope.js';
@@ -31,14 +31,12 @@ import { join } from 'node:path';
31
31
  import { registerAgent, setReady } from './roster.js';
32
32
  import { registerForeignTarget } from './targets.js';
33
33
  import { spawnWorld } from './spawn-world.js';
34
- import { provisionWorldProfile } from './world-provision.js';
34
+ import { provisionWorldProfile, resolveInstallAnchor } from './world-provision.js';
35
35
  import { registerHostMount } from './world-host.js';
36
36
  import { mountWorld } from './carrier.js';
37
37
  import { worldMountPatches } from './world-mount.js';
38
38
  /** Stable Cordis plugin name. */
39
39
  export const name = 'aw.world.join';
40
- const ANCHOR = process.env.SUPERD_DSH_ANCHOR
41
- ?? '/home/u1/.local/lib/node_modules/@deepseek-ai/dsh/package.json';
42
40
  /** Apply the join. @param ctx - the CTX0 root context. @param config - `{ key, label? }`. */
43
41
  export function apply(ctx, config) {
44
42
  const key = typeof config?.key === 'string' ? config.key : undefined;
@@ -86,7 +84,7 @@ export function apply(ctx, config) {
86
84
  const ctxW = await spawnWorld({
87
85
  appName: `aw-${key}`,
88
86
  profileName: 'web',
89
- installAnchor: ANCHOR,
87
+ installAnchor: resolveInstallAnchor(), // lazy: never at module scope — import must stay side-effect-free
90
88
  home: worldHome,
91
89
  dataHome: worldHome,
92
90
  // Adapter-local bundle names resolve from the profile's own
@@ -1,3 +1,17 @@
1
+ /**
2
+ * Resolve the running dsh installation's package.json — the anchor worlds
3
+ * resolve `@deepseek-ai` bundles and the fallback closure from.
4
+ *
5
+ * Precedence: `$SUPERD_DSH_ANCHOR` (the repo dev lines' contract — the
6
+ * launcher pins the checkout build), then a walk UP from the
7
+ * `@deepseek-ai/dsh-app-boot` this module resolved (the host always provides
8
+ * it) to the nearest ancestor package named `@deepseek-ai/dsh` — the
9
+ * packaged-install layout (`<install>/@deepseek-ai/dsh/node_modules/
10
+ * @deepseek-ai/dsh-app-boot`) lands on the install root in two hops. No
11
+ * machine-specific path ships in code.
12
+ * @throws when neither yields an installation (mis-launched composition).
13
+ */
14
+ export declare function resolveInstallAnchor(): string;
1
15
  export interface ProvisionWorldOptions {
2
16
  /** Runtime key — also the mount label and the `agents/<key>` home segment. */
3
17
  key: string;
@@ -32,14 +32,61 @@
32
32
  * or null when the adapter sibling does not exist next to the hub (a foreign
33
33
  * composition this module does not own — keep the caller's env/fallback path).
34
34
  */
35
- import { existsSync, lstatSync, mkdirSync, readdirSync, rmSync, symlinkSync, writeFileSync } from 'node:fs';
35
+ import { existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, realpathSync, rmSync, statSync, symlinkSync, writeFileSync } from 'node:fs';
36
36
  import { dirname, join } from 'node:path';
37
37
  import { fileURLToPath } from 'node:url';
38
+ import { createRequire } from 'node:module';
38
39
  import { resolveDshHome } from '@deepseek-ai/dsh-home-paths';
39
40
  const HUB_SCOPE = '@pgmi-builds';
40
41
  const HARNESS_SCOPE = '@deepseek-ai';
41
42
  /** The profile bundles every world tree composes besides its adapter. */
42
43
  const WORLD_BASE_BUNDLES = ['@deepseek-ai/dsh-base', '@deepseek-ai/dsh-web-app'];
44
+ /**
45
+ * Resolve the running dsh installation's package.json — the anchor worlds
46
+ * resolve `@deepseek-ai` bundles and the fallback closure from.
47
+ *
48
+ * Precedence: `$SUPERD_DSH_ANCHOR` (the repo dev lines' contract — the
49
+ * launcher pins the checkout build), then a walk UP from the
50
+ * `@deepseek-ai/dsh-app-boot` this module resolved (the host always provides
51
+ * it) to the nearest ancestor package named `@deepseek-ai/dsh` — the
52
+ * packaged-install layout (`<install>/@deepseek-ai/dsh/node_modules/
53
+ * @deepseek-ai/dsh-app-boot`) lands on the install root in two hops. No
54
+ * machine-specific path ships in code.
55
+ * @throws when neither yields an installation (mis-launched composition).
56
+ */
57
+ export function resolveInstallAnchor() {
58
+ const fromEnv = process.env.SUPERD_DSH_ANCHOR;
59
+ if (fromEnv !== undefined && fromEnv !== '')
60
+ return fromEnv;
61
+ let dir = dirname(resolveHostPackageDir('@deepseek-ai/dsh-app-boot'));
62
+ while (true) {
63
+ const manifest = join(dir, 'package.json');
64
+ if (existsSync(manifest)) {
65
+ try {
66
+ const name = JSON.parse(readFileSync(manifest, 'utf8')).name;
67
+ if (name === '@deepseek-ai/dsh')
68
+ return manifest;
69
+ }
70
+ catch { /* malformed intermediate manifest — keep walking */ }
71
+ }
72
+ const parent = dirname(dir);
73
+ if (parent === dir) {
74
+ throw new Error('super-dsh: cannot derive the dsh installation anchor (set SUPERD_DSH_ANCHOR)');
75
+ }
76
+ dir = parent;
77
+ }
78
+ }
79
+ /** First `node_modules` search-path candidate that exists for a specifier,
80
+ * resolved to its REALPATH — farm and pnpm links must not leak into the
81
+ * ancestor walk (the install tree only exists behind the symlink). */
82
+ function resolveHostPackageDir(spec) {
83
+ for (const searchPath of createRequire(import.meta.url).resolve.paths(`${spec}/x`) ?? []) {
84
+ const candidate = join(searchPath, spec);
85
+ if (existsSync(join(candidate, 'package.json')))
86
+ return realpathSync(candidate);
87
+ }
88
+ throw new Error(`super-dsh: cannot resolve ${spec} from the running host`);
89
+ }
43
90
  /**
44
91
  * Provision one world's nested profile (idempotent: rewrites profile files,
45
92
  * re-links packages — lstat-safe against dangling links). Returns the
@@ -58,6 +105,46 @@ export function provisionWorldProfile(opts) {
58
105
  return null;
59
106
  }
60
107
  }
108
+ /**
109
+ * A source-checkout (pnpm workspace) splits the @deepseek-ai closure across
110
+ * the workspace packages' OWN node_modules (apps/cli links only its direct
111
+ * deps; bundle/web-app carries the UI closure, bundle/base the runtimes).
112
+ * When the anchor sits inside a pnpm workspace, every package-level scope is
113
+ * a union source. Packaged installs have no pnpm-workspace.yaml and return
114
+ * nothing — their single install tree is already complete (dev3 evidence).
115
+ */
116
+ function workspaceHarnessScopes(anchorDir) {
117
+ let root = anchorDir;
118
+ while (root !== undefined && !existsSync(join(root, 'pnpm-workspace.yaml'))) {
119
+ const parent = dirname(root);
120
+ root = parent === root ? undefined : parent;
121
+ }
122
+ if (root === undefined)
123
+ return [];
124
+ const scopes = [];
125
+ const collect = (base, depth) => {
126
+ if (!existsSync(base))
127
+ return;
128
+ const scope = join(base, 'node_modules', HARNESS_SCOPE);
129
+ if (existsSync(scope))
130
+ scopes.push(scope);
131
+ if (depth === 0)
132
+ return;
133
+ for (const entry of readdirSync(base)) {
134
+ if (entry === 'node_modules' || entry.startsWith('.'))
135
+ continue;
136
+ // Bare files under group dirs (packages/AGENTS.md — the docs/06 §2.1
137
+ // phantom-package trap) must not abort the whole enumeration.
138
+ if (!statSync(join(base, entry), { throwIfNoEntry: false })?.isDirectory())
139
+ continue;
140
+ collect(join(base, entry), depth - 1);
141
+ }
142
+ };
143
+ collect(join(root, 'packages'), 2);
144
+ collect(join(root, 'vendor'), 1);
145
+ collect(join(root, 'apps'), 1);
146
+ return scopes;
147
+ }
61
148
  function provisionWorldProfileUnchecked(opts) {
62
149
  // Single-pack topology: this module lives at `<line>/agent-hub/dist/`, and
63
150
  // every adapter is a SIBLING directory (`<line>/agent-<key>`) — the same
@@ -111,11 +198,11 @@ function provisionWorldProfileUnchecked(opts) {
111
198
  // base gets no such fallback). A single scope-level link cannot express
112
199
  // that union, and a resolve.paths() walk from this module can pick the
113
200
  // PROFILE's own partial pnpm scope (2 entries on dev3) — never use it.
114
- const ANCHOR = process.env.SUPERD_DSH_ANCHOR
115
- ?? '/home/u1/.local/lib/node_modules/@deepseek-ai/dsh/package.json';
201
+ const ANCHOR = resolveInstallAnchor();
116
202
  const scopeSources = [
117
203
  join(resolveDshHome(), 'profiles', 'node_modules', HARNESS_SCOPE),
118
204
  join(dirname(ANCHOR), 'node_modules', HARNESS_SCOPE),
205
+ ...workspaceHarnessScopes(dirname(ANCHOR)),
119
206
  ];
120
207
  const scopeDst = join(linkRoot, HARNESS_SCOPE);
121
208
  rmSync(scopeDst, { recursive: true, force: true });
@@ -15,12 +15,10 @@
15
15
  import { mkdirSync } from 'node:fs';
16
16
  import { resolveDshHome } from '@deepseek-ai/dsh-home-paths';
17
17
  import { join } from 'node:path';
18
- import { spawnWorld, registerAgent, setReady, registerForeignTarget, registerHostMount, mountWorld, worldMountPatches, provisionWorldProfile, } from '../../agent-hub/dist/index.js';
18
+ import { spawnWorld, registerAgent, setReady, registerForeignTarget, registerHostMount, mountWorld, worldMountPatches, provisionWorldProfile, resolveInstallAnchor, } from '../../agent-hub/dist/index.js';
19
19
  export const name = 'aw.agent-adapter-omp';
20
20
  /** Runtime key — also the mount label. */
21
21
  const KEY = 'omp';
22
- const ANCHOR = process.env.SUPERD_DSH_ANCHOR
23
- ?? '/home/u1/.local/lib/node_modules/@deepseek-ai/dsh/package.json';
24
22
  export function apply(ctx) {
25
23
  registerAgent({ key: KEY, label: 'OMP', ready: false });
26
24
  // Harness resolver (env → ~/.dsh): a consumer install has no DSH_HOME and
@@ -61,7 +59,7 @@ export function apply(ctx) {
61
59
  const ctxW = await spawnWorld({
62
60
  appName: `aw-${KEY}`,
63
61
  profileName: 'web',
64
- installAnchor: ANCHOR,
62
+ installAnchor: resolveInstallAnchor(), // lazy: never at module scope — import must stay side-effect-free
65
63
  home: worldHome,
66
64
  dataHome: worldHome,
67
65
  // Adapter-local bundle names resolve from the profile's own
@@ -33,8 +33,7 @@
33
33
  },
34
34
  "dependencies": {
35
35
  "@oh-my-pi/pi-coding-agent": "^18.1.14",
36
- "bun": "^1.4.2",
37
- "@pgmi-builds/agent-hub": "file:../agent-hub"
36
+ "bun": "^1.4.2"
38
37
  },
39
38
  "peerDependencies": {
40
39
  "@deepseek-ai/cordis": "^4.0.1",
@@ -45,7 +44,8 @@
45
44
  "@deepseek-ai/dsh-session": "0.1.5-rc.2",
46
45
  "@deepseek-ai/dsh-session-persistence": "0.1.5-rc.2",
47
46
  "@deepseek-ai/dsh-typert-protocol": "0.1.5-rc.2",
48
- "@deepseek-ai/dsh-home-paths": "0.1.5-rc.2"
47
+ "@deepseek-ai/dsh-home-paths": "0.1.5-rc.2",
48
+ "@pgmi-builds/agent-hub": "*"
49
49
  },
50
50
  "peerDependenciesMeta": {
51
51
  "@deepseek-ai/cordis": {
@@ -74,6 +74,9 @@
74
74
  },
75
75
  "@deepseek-ai/dsh-home-paths": {
76
76
  "optional": true
77
+ },
78
+ "@pgmi-builds/agent-hub": {
79
+ "optional": true
77
80
  }
78
81
  },
79
82
  "devDependencies": {
@@ -16,21 +16,12 @@
16
16
  * pi never reads this tree; it is DSH bookkeeping in the same class as the
17
17
  * DSH session log.
18
18
  */
19
- import { homedir } from "node:os";
20
19
  import { join, resolve } from "node:path";
21
20
  /** Prod homes that must never be resolved into (repo red line). */
22
- const PROD_HOMES = [join(homedir(), ".dsh"), join(homedir(), ".superd")];
23
- export function assertNotProdHome(path, label) {
24
- if (process.env.SUPERD_DEV_REDLINE !== "1")
25
- return; // published install: the host dsh home (~/.dsh on consumers) is authoritative — the S3/S7 world layout lives under it. Dev lines set SUPERD_DEV_REDLINE=1 (repo red line: ~/.dsh is Dash prod).
26
- if (PROD_HOMES.includes(path) || PROD_HOMES.some((p) => path.startsWith(`${p}/`))) {
27
- throw new Error(`pi-home: refusing prod home as ${label}: ${path}`);
28
- }
29
- }
30
21
  /**
31
22
  * Resolve the adapter's DSH-side state dir — `<dshHomePath>/agents/pi`.
32
23
  * Precedence: explicit home (boot-provided `dshHomePath`), then `$DSH_HOME`,
33
- * then the line's historical test-home default. Prod-guarded.
24
+ * then the line's historical test-home default.
34
25
  */
35
26
  export function resolvePiStateDir(home) {
36
27
  if (home !== undefined) {
@@ -39,16 +30,13 @@ export function resolvePiStateDir(home) {
39
30
  // — that tree IS the pi world's root, so the state dir is the home itself
40
31
  // (no second nest). Line/standalone form: nest once under agents/pi.
41
32
  if (resolved.endsWith(join("agents", "pi"))) {
42
- assertNotProdHome(resolved, "pi state dir");
43
33
  return resolved;
44
34
  }
45
35
  const dir = join(resolved, "agents", "pi");
46
- assertNotProdHome(dir, "pi state dir");
47
36
  return dir;
48
37
  }
49
38
  const fallbackHome = resolve(process.env.DSH_HOME ?? join(process.cwd(), ".tests", "aw"));
50
39
  const dir = join(fallbackHome, "agents", "pi");
51
- assertNotProdHome(dir, "pi state dir");
52
40
  return dir;
53
41
  }
54
42
  /** The dsh↔pi session mapping file inside the state dir. */
@@ -16,12 +16,10 @@
16
16
  import { mkdirSync } from 'node:fs';
17
17
  import { resolveDshHome } from '@deepseek-ai/dsh-home-paths';
18
18
  import { join } from 'node:path';
19
- import { spawnWorld, registerAgent, setReady, registerForeignTarget, registerHostMount, mountWorld, worldMountPatches, provisionWorldProfile, } from '../../agent-hub/dist/index.js';
19
+ import { spawnWorld, registerAgent, setReady, registerForeignTarget, registerHostMount, mountWorld, worldMountPatches, provisionWorldProfile, resolveInstallAnchor, } from '../../agent-hub/dist/index.js';
20
20
  export const name = 'aw.agent-adapter-pi';
21
21
  /** Runtime key — also the mount label. */
22
22
  const KEY = 'pi';
23
- const ANCHOR = process.env.SUPERD_DSH_ANCHOR
24
- ?? '/home/u1/.local/lib/node_modules/@deepseek-ai/dsh/package.json';
25
23
  export function apply(ctx) {
26
24
  registerAgent({ key: KEY, label: 'Pi', ready: false });
27
25
  // Harness resolver (env → ~/.dsh): a consumer install has no DSH_HOME and
@@ -62,7 +60,7 @@ export function apply(ctx) {
62
60
  const ctxW = await spawnWorld({
63
61
  appName: `aw-${KEY}`,
64
62
  profileName: 'web',
65
- installAnchor: ANCHOR,
63
+ installAnchor: resolveInstallAnchor(), // lazy: never at module scope — import must stay side-effect-free
66
64
  home: worldHome,
67
65
  dataHome: worldHome,
68
66
  // Adapter-local bundle names resolve from the profile's own
@@ -23,7 +23,6 @@
23
23
  },
24
24
  "dependencies": {
25
25
  "@earendil-works/pi-coding-agent": "0.84.2",
26
- "@pgmi-builds/agent-hub": "file:../agent-hub",
27
26
  "zod": "3.25.76"
28
27
  },
29
28
  "peerDependencies": {
@@ -34,7 +33,8 @@
34
33
  "@deepseek-ai/dsh-scope": "0.1.5-rc.2",
35
34
  "@deepseek-ai/dsh-session": "0.1.5-rc.2",
36
35
  "@deepseek-ai/dsh-session-persistence": "0.1.5-rc.2",
37
- "@deepseek-ai/dsh-typert-protocol": "0.1.5-rc.2"
36
+ "@deepseek-ai/dsh-typert-protocol": "0.1.5-rc.2",
37
+ "@pgmi-builds/agent-hub": "*"
38
38
  },
39
39
  "peerDependenciesMeta": {
40
40
  "@deepseek-ai/cordis": {
@@ -60,6 +60,9 @@
60
60
  },
61
61
  "@deepseek-ai/dsh-typert-protocol": {
62
62
  "optional": true
63
+ },
64
+ "@pgmi-builds/agent-hub": {
65
+ "optional": true
63
66
  }
64
67
  },
65
68
  "devDependencies": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "super-dsh",
3
- "version": "0.1.3-c",
3
+ "version": "0.1.3-g",
4
4
  "description": "Agent Worlds for the DeepSeek Harness (DSH) — one dsh plugin that mounts the agent hub (runtime selector, roster, per-runtime worlds) and joins local foreign-agent runtimes (OMP, Codex, Claude, Pi, Hermes, Antigravity) into the DSH Web UI. Each runtime keeps its native home and session store; the hub only bridges.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -75,19 +75,19 @@
75
75
  },
76
76
  "peerDependencies": {
77
77
  "@deepseek-ai/cordis": "^4.0.1",
78
- "@deepseek-ai/dsh-agent": "0.1.5-rc.2",
79
- "@deepseek-ai/dsh-agent-presets": "0.1.5-rc.2",
78
+ "@deepseek-ai/dsh-agent": "0.1.6-alpha.2",
79
+ "@deepseek-ai/dsh-agent-presets": "0.1.6-alpha.2",
80
80
  "@deepseek-ai/dsh-api-gateway": "*",
81
- "@deepseek-ai/dsh-commands": "0.1.5-rc.2",
82
- "@deepseek-ai/dsh-home-paths": "0.1.5-rc.2",
81
+ "@deepseek-ai/dsh-commands": "0.1.6-alpha.2",
82
+ "@deepseek-ai/dsh-home-paths": "0.1.6-alpha.2",
83
83
  "@deepseek-ai/dsh-host-webserver": "*",
84
- "@deepseek-ai/dsh-llm": "0.1.5-rc.2",
85
- "@deepseek-ai/dsh-scope": "0.1.5-rc.2",
86
- "@deepseek-ai/dsh-session": "0.1.5-rc.2",
87
- "@deepseek-ai/dsh-session-persistence": "0.1.5-rc.2",
88
- "@deepseek-ai/dsh-typert-protocol": "0.1.5-rc.2",
89
- "@deepseek-ai/dsh-user-approval": "0.1.5-rc.2",
90
- "@deepseek-ai/dsh-user-questions": "0.1.5-rc.2"
84
+ "@deepseek-ai/dsh-llm": "0.1.6-alpha.2",
85
+ "@deepseek-ai/dsh-scope": "0.1.6-alpha.2",
86
+ "@deepseek-ai/dsh-session": "0.1.6-alpha.2",
87
+ "@deepseek-ai/dsh-session-persistence": "0.1.6-alpha.2",
88
+ "@deepseek-ai/dsh-typert-protocol": "0.1.6-alpha.2",
89
+ "@deepseek-ai/dsh-user-approval": "0.1.6-alpha.2",
90
+ "@deepseek-ai/dsh-user-questions": "0.1.6-alpha.2"
91
91
  },
92
92
  "peerDependenciesMeta": {
93
93
  "@deepseek-ai/cordis": {