super-dsh 0.1.2 → 0.1.3-d

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.
@@ -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,23 +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 (PROD_HOMES.includes(path) || PROD_HOMES.some((p) => path.startsWith(`${p}/`))) {
21
- throw new Error(`agy-sessions: refusing prod home as ${label}: ${path}`);
22
- }
23
- }
24
16
  /**
25
17
  * The adapter's DSH-side world home. Form-A (boot home = DSH home root) nests
26
- * `agents/agy`; Form-B (already `<root>/agents/agy`) passes through. Prod-guarded.
18
+ * `agents/agy`; Form-B (already `<root>/agents/agy`) passes through.
27
19
  */
28
20
  export function resolveAgyWorldHome(home) {
29
21
  const base = resolve(home ?? process.env.DSH_HOME ?? join(process.cwd(), ".tests", "aw"));
30
22
  const dir = basename(base) === "agy" && basename(dirname(base)) === "agents" ? base : join(base, "agents", "agy");
31
- assertNotProdHome(dir, "agy world home");
32
23
  return dir;
33
24
  }
34
25
  export function sessionMapPath(home) {
@@ -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
@@ -57,8 +57,10 @@
57
57
  import { query as officialQuery } from "@anthropic-ai/claude-agent-sdk";
58
58
  import { InputQueue } from "./input-queue.js";
59
59
  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";
60
+ /** Host Claude Code binary driven through the SDK bridge (spec ruling R5).
61
+ * PATH-resolved like any host CLI: $CLAUDE_EXECUTABLE wins, else a bare
62
+ * "claude" the SDK spawns through PATH. No machine-specific path ships. */
63
+ export const DEFAULT_CLAUDE_EXECUTABLE = "claude";
62
64
  const defaultFactory = (o) => officialQuery({
63
65
  prompt: o.prompt,
64
66
  options: o.options,
@@ -9,14 +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
- const p = resolve(path);
16
- if (PROD_HOMES.includes(p) || PROD_HOMES.some((prod) => p.startsWith(`${prod}/`))) {
17
- throw new Error(`agent-claude: refusing prod home "${p}" for ${label} — set DSH_HOME to the test home`);
18
- }
19
- }
20
13
  /**
21
14
  * The Claude app home: the NATIVE `~/.claude`, prod-home guarded. An ambient
22
15
  * `CLAUDE_CONFIG_DIR` wins (tests pin an isolated home that way); the adapter
@@ -24,6 +17,5 @@ export function assertNotProdHome(path, label) {
24
17
  */
25
18
  export function resolveClaudeHome() {
26
19
  const claudeHome = resolve(process.env.CLAUDE_CONFIG_DIR ?? join(homedir(), ".claude"));
27
- assertNotProdHome(claudeHome, "claudeHome");
28
20
  return claudeHome;
29
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,12 +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 (PROD_HOMES.includes(path) || PROD_HOMES.some((p) => path.startsWith(`${p}/`))) {
26
- throw new Error(`codex-store: refusing prod home as ${label}: ${path}`);
27
- }
28
- }
29
23
  /**
30
24
  * Resolve the Codex CLI's app-data home — the NATIVE `~/.codex` (user ruling
31
25
  * 2026-09-17, pi precedent): the installed app keeps its own home, so the
@@ -42,11 +36,9 @@ export function assertNotProdHome(path, label) {
42
36
  export function resolveCodexHome() {
43
37
  if (process.env.CODEX_HOME !== undefined) {
44
38
  const env = resolve(process.env.CODEX_HOME);
45
- assertNotProdHome(env, "codex home");
46
39
  return env;
47
40
  }
48
41
  const native = join(homedir(), ".codex");
49
- assertNotProdHome(native, "codex home");
50
42
  return native;
51
43
  }
52
44
  /**
@@ -56,7 +48,6 @@ export function resolveCodexHome() {
56
48
  */
57
49
  export function useCodexHome(path) {
58
50
  const resolved = resolve(path);
59
- assertNotProdHome(resolved, "codex home");
60
51
  return resolved;
61
52
  }
62
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,15 +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 (PROD_HOMES.includes(path) || PROD_HOMES.some((p) => path.startsWith(`${p}/`))) {
28
- throw new Error(`hermes-store: refusing prod home as ${label}: ${path}`);
29
- }
30
- }
31
23
  /**
32
24
  * The adapter's DSH-side state dir — `<dshHome>/agents/hermes`. This is DSH-SIDE
33
25
  * adapter state (the identity map), NOT hermes data: hermes keeps its native
@@ -40,13 +32,12 @@ function assertNotProdHome(path, label) {
40
32
  * - Form-B: the boot-provided home is ALREADY the world home
41
33
  * (`<root>/agents/hermes`) — passed through as-is, never double-nested.
42
34
  * Precedence: explicit home (boot-provided `dshHomePath`), then `$DSH_HOME`,
43
- * then the line's historical test-home default. Prod-guarded.
35
+ * then the line's historical test-home default.
44
36
  */
45
37
  export function resolveHermesAppDir(home) {
46
38
  const base = resolve(home ?? process.env.DSH_HOME ?? join(process.cwd(), ".tests", "aw"));
47
39
  // Form-B world home is already `<root>/agents/hermes` — never double-nest.
48
40
  const dir = basename(base) === "hermes" && basename(dirname(base)) === "agents" ? base : join(base, "agents", "hermes");
49
- assertNotProdHome(dir, "hermes app dir");
50
41
  return dir;
51
42
  }
52
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, rmSync, symlinkSync, writeFileSync } from 'node:fs';
35
+ import { existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, realpathSync, rmSync, symlinkSync, writeFileSync } from 'node:fs';
36
36
  import { dirname, join } from 'node:path';
37
37
  import { fileURLToPath } from 'node:url';
38
38
  import { createRequire } from 'node:module';
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
@@ -103,20 +150,32 @@ function provisionWorldProfileUnchecked(opts) {
103
150
  rmSync(dst, { recursive: true, force: true });
104
151
  symlinkSync(target, dst);
105
152
  }
106
- // The harness scope rides along as ONE scope-level link into the first
107
- // `@deepseek-ai` directory visible from this module (the shared heal farm
108
- // in a dsh home, the repo farm in dev) — every `@deepseek-ai/*` row of the
109
- // world composition resolves through it without farming per package.
110
- for (const searchPath of createRequire(import.meta.url).resolve.paths(`${HARNESS_SCOPE}/x`) ?? []) {
111
- const scopeDir = join(searchPath, HARNESS_SCOPE);
112
- if (!existsSync(scopeDir))
153
+ // The harness scope for the world tree is a REAL scope directory of
154
+ // per-package symlinks UNIONED from two authoritative sources (farm first,
155
+ // installation fills the gaps — dev3 evidence: farm 244 entries missing 16
156
+ // newer packages the install's 260 has; ctx0 survives via the app-boot
157
+ // install-anchored resolver fallback, but a tree with an explicit bare
158
+ // base gets no such fallback). A single scope-level link cannot express
159
+ // that union, and a resolve.paths() walk from this module can pick the
160
+ // PROFILE's own partial pnpm scope (2 entries on dev3) — never use it.
161
+ const ANCHOR = resolveInstallAnchor();
162
+ const scopeSources = [
163
+ join(resolveDshHome(), 'profiles', 'node_modules', HARNESS_SCOPE),
164
+ join(dirname(ANCHOR), 'node_modules', HARNESS_SCOPE),
165
+ ];
166
+ const scopeDst = join(linkRoot, HARNESS_SCOPE);
167
+ rmSync(scopeDst, { recursive: true, force: true });
168
+ mkdirSync(scopeDst, { recursive: true });
169
+ const linked = new Set();
170
+ for (const scopeSrc of scopeSources) {
171
+ if (!existsSync(scopeSrc))
113
172
  continue;
114
- const dst = join(linkRoot, HARNESS_SCOPE);
115
- const st = lstatSync(dst, { throwIfNoEntry: false });
116
- if (st)
117
- rmSync(dst, { recursive: true, force: true });
118
- symlinkSync(scopeDir, dst);
119
- break;
173
+ for (const name of readdirSync(scopeSrc)) {
174
+ if (name.startsWith('.') || linked.has(name))
175
+ continue;
176
+ symlinkSync(join(scopeSrc, name), join(scopeDst, name));
177
+ linked.add(name);
178
+ }
120
179
  }
121
180
  return join(opts.worldHome, 'profiles', 'node_modules') + '/';
122
181
  }
@@ -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,19 +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 (PROD_HOMES.includes(path) || PROD_HOMES.some((p) => path.startsWith(`${p}/`))) {
25
- throw new Error(`pi-home: refusing prod home as ${label}: ${path}`);
26
- }
27
- }
28
21
  /**
29
22
  * Resolve the adapter's DSH-side state dir — `<dshHomePath>/agents/pi`.
30
23
  * Precedence: explicit home (boot-provided `dshHomePath`), then `$DSH_HOME`,
31
- * then the line's historical test-home default. Prod-guarded.
24
+ * then the line's historical test-home default.
32
25
  */
33
26
  export function resolvePiStateDir(home) {
34
27
  if (home !== undefined) {
@@ -37,16 +30,13 @@ export function resolvePiStateDir(home) {
37
30
  // — that tree IS the pi world's root, so the state dir is the home itself
38
31
  // (no second nest). Line/standalone form: nest once under agents/pi.
39
32
  if (resolved.endsWith(join("agents", "pi"))) {
40
- assertNotProdHome(resolved, "pi state dir");
41
33
  return resolved;
42
34
  }
43
35
  const dir = join(resolved, "agents", "pi");
44
- assertNotProdHome(dir, "pi state dir");
45
36
  return dir;
46
37
  }
47
38
  const fallbackHome = resolve(process.env.DSH_HOME ?? join(process.cwd(), ".tests", "aw"));
48
39
  const dir = join(fallbackHome, "agents", "pi");
49
- assertNotProdHome(dir, "pi state dir");
50
40
  return dir;
51
41
  }
52
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": {
@@ -0,0 +1,242 @@
1
+ window.__ModuleLoader__.load({ id: "super-dsh", factory: (require) => {
2
+ var module = { exports: {} }; var exports = module.exports;
3
+ //#region rolldown:runtime
4
+ var __create = Object.create;
5
+ var __defProp = Object.defineProperty;
6
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
7
+ var __getOwnPropNames = Object.getOwnPropertyNames;
8
+ var __getProtoOf = Object.getPrototypeOf;
9
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
12
+ key = keys[i];
13
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
14
+ get: ((k) => from[k]).bind(null, key),
15
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
16
+ });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
21
+ value: mod,
22
+ enumerable: true
23
+ }) : target, mod));
24
+
25
+ //#endregion
26
+ let react = require("react");
27
+ react = __toESM(react);
28
+ let react_jsx_runtime = require("react/jsx-runtime");
29
+ react_jsx_runtime = __toESM(react_jsx_runtime);
30
+
31
+ //#region src/client/RuntimeSeat.tsx
32
+ const NATIVE = {
33
+ key: "native",
34
+ label: "DSH",
35
+ path: "/"
36
+ };
37
+ /** Fallback labels for the read-only face (which only reports keys). */
38
+ const RUNTIME_LABELS = {
39
+ native: "DSH",
40
+ omp: "OMP",
41
+ codex: "Codex"
42
+ };
43
+ function fromGlobal() {
44
+ const agents = globalThis.__DSH_AGENT_ROSTER__?.agents;
45
+ if (!Array.isArray(agents)) return void 0;
46
+ const links = [];
47
+ for (const entry of agents) {
48
+ if (typeof entry !== "object" || entry === null) continue;
49
+ const { key, label, path } = entry;
50
+ if (typeof key !== "string" || typeof path !== "string") continue;
51
+ links.push({
52
+ key,
53
+ label: typeof label === "string" ? label : RUNTIME_LABELS[key] ?? key,
54
+ path
55
+ });
56
+ }
57
+ return links.length > 0 ? links : void 0;
58
+ }
59
+ /** Normalize the current mount root: `/omp` and `/omp/` are the same page. */
60
+ function currentPath() {
61
+ const pathname = typeof location === "undefined" ? "/" : location.pathname;
62
+ if (pathname === "" || pathname === "/") return "/";
63
+ return pathname.endsWith("/") ? pathname : `${pathname}/`;
64
+ }
65
+ function RuntimeSeat({ wide }) {
66
+ const [agents, setAgents] = react.useState(() => fromGlobal() ?? [NATIVE]);
67
+ const [open, setOpen] = react.useState(false);
68
+ const rootRef = react.useRef(null);
69
+ react.useEffect(() => {
70
+ let cancelled = false;
71
+ fetch("/api/agent-runtime", { credentials: "same-origin" }).then((r) => r.ok ? r.json() : Promise.reject(/* @__PURE__ */ new Error(`HTTP ${r.status}`))).then((j) => {
72
+ if (cancelled) return;
73
+ if (Array.isArray(j?.agents)) {
74
+ const listed = [];
75
+ for (const entry of j.agents) {
76
+ if (typeof entry !== "object" || entry === null) continue;
77
+ const { key, label, path } = entry;
78
+ if (typeof key !== "string" || typeof path !== "string") continue;
79
+ listed.push({
80
+ key,
81
+ label: typeof label === "string" ? label : RUNTIME_LABELS[key] ?? key,
82
+ path
83
+ });
84
+ }
85
+ if (listed.length > 0) {
86
+ setAgents(listed);
87
+ return;
88
+ }
89
+ }
90
+ if (!Array.isArray(j?.available)) return;
91
+ const links = [];
92
+ for (const key of j.available) {
93
+ if (typeof key !== "string") continue;
94
+ links.push(key === "native" ? NATIVE : {
95
+ key,
96
+ label: RUNTIME_LABELS[key] ?? key,
97
+ path: `/${key}/`
98
+ });
99
+ }
100
+ if (links.length > 0) setAgents(links);
101
+ }).catch(() => {});
102
+ return () => {
103
+ cancelled = true;
104
+ };
105
+ }, []);
106
+ react.useEffect(() => {
107
+ if (!open) return;
108
+ const onDown = (event) => {
109
+ if (rootRef.current !== null && !rootRef.current.contains(event.target)) setOpen(false);
110
+ };
111
+ document.addEventListener("mousedown", onDown);
112
+ return () => document.removeEventListener("mousedown", onDown);
113
+ }, [open]);
114
+ const here = currentPath();
115
+ const active = agents.find((agent) => agent.path === here) ?? NATIVE;
116
+ const styleBase = {
117
+ display: "flex",
118
+ alignItems: "center",
119
+ gap: 8,
120
+ width: "100%",
121
+ padding: wide ? "7px 10px" : "7px 0",
122
+ justifyContent: wide ? "flex-start" : "center",
123
+ border: "none",
124
+ borderRadius: 8,
125
+ background: "transparent",
126
+ color: "inherit",
127
+ font: "inherit",
128
+ fontSize: 13,
129
+ cursor: "pointer",
130
+ position: "relative"
131
+ };
132
+ const styleBadge = {
133
+ fontSize: 10,
134
+ lineHeight: 1.4,
135
+ padding: "1px 6px",
136
+ borderRadius: 999,
137
+ background: "color-mix(in srgb, currentColor 12%, transparent)",
138
+ whiteSpace: "nowrap"
139
+ };
140
+ const styleMenu = {
141
+ position: "absolute",
142
+ bottom: "calc(100% + 6px)",
143
+ left: 6,
144
+ right: 6,
145
+ zIndex: 40,
146
+ background: "var(--dsh-surface, #26262b)",
147
+ border: "1px solid color-mix(in srgb, currentColor 18%, transparent)",
148
+ borderRadius: 10,
149
+ boxShadow: "0 8px 24px rgba(0,0,0,.35)",
150
+ overflow: "hidden"
151
+ };
152
+ const styleItem = (isActive) => ({
153
+ display: "block",
154
+ width: "100%",
155
+ padding: "8px 12px",
156
+ border: "none",
157
+ background: isActive ? "color-mix(in srgb, currentColor 10%, transparent)" : "transparent",
158
+ color: "inherit",
159
+ font: "inherit",
160
+ fontSize: 13,
161
+ textAlign: "left",
162
+ cursor: "pointer"
163
+ });
164
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
165
+ ref: rootRef,
166
+ style: {
167
+ position: "relative",
168
+ width: "100%"
169
+ },
170
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
171
+ type: "button",
172
+ style: styleBase,
173
+ title: "Agent runtime — picking one opens that runtime's mount (/omp/, /codex/, …)",
174
+ onClick: () => {
175
+ setOpen((v) => !v);
176
+ },
177
+ children: wide ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
178
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
179
+ "aria-hidden": true,
180
+ children: "⌘"
181
+ }),
182
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
183
+ style: {
184
+ flex: 1,
185
+ textAlign: "left",
186
+ whiteSpace: "nowrap",
187
+ overflow: "hidden",
188
+ textOverflow: "ellipsis"
189
+ },
190
+ children: ["Agent · ", active.label]
191
+ }),
192
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
193
+ style: styleBadge,
194
+ children: "open"
195
+ })
196
+ ] }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
197
+ "aria-hidden": true,
198
+ children: "⌘"
199
+ })
200
+ }), open && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
201
+ style: styleMenu,
202
+ children: agents.map((agent) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
203
+ href: agent.path,
204
+ style: {
205
+ ...styleItem(agent.path === here),
206
+ textDecoration: "none"
207
+ },
208
+ "aria-current": agent.path === here ? "page" : void 0,
209
+ onClick: () => {
210
+ setOpen(false);
211
+ },
212
+ children: agent.path === here ? `${agent.label} ✓` : agent.label
213
+ }, agent.key))
214
+ })]
215
+ });
216
+ }
217
+
218
+ //#endregion
219
+ //#region src/client/index.ts
220
+ /** Required services (cordis fiber inject): the slot registry. */
221
+ const inject = ["slots"];
222
+ /**
223
+ * Mount the selector. Degrades silently when the slot service is absent (a
224
+ * composition without the sidebar renders nothing — a footer action is an
225
+ * optional occupant by contract).
226
+ *
227
+ * @param ctx - client root context.
228
+ */
229
+ function apply(ctx) {
230
+ ctx.inject(["slots"], (raw) => {
231
+ const scope = raw;
232
+ scope.effect(() => scope.slots.inject("sidebar.footer.action", () => scope.slots.register({
233
+ name: "sidebar.footer.action",
234
+ id: "agent-runtime"
235
+ }, RuntimeSeat)), "agent-hub: runtime footer action");
236
+ });
237
+ }
238
+
239
+ //#endregion
240
+ exports.apply = apply;
241
+ exports.inject = inject;
242
+ return module.exports; } });
package/cordis.patch.yml CHANGED
@@ -16,8 +16,11 @@
16
16
  # Profile-layer values (webserver port/host, settings path) stay in the USER's
17
17
  # profile patch layer, never here.
18
18
  - insert:
19
+ # BARE package row: subpath rows (…/world/omp) are permanently not client
20
+ # rows in client-modules' scan (exactPackageSpecifier), so THIS row is
21
+ # what registers the package's client half — the sidebar selector.
19
22
  - id: agent-hub
20
- name: 'super-dsh/hub'
23
+ name: 'super-dsh'
21
24
  - id: aw-agent-adapter-omp
22
25
  name: 'super-dsh/world/omp'
23
26
  - id: aw-agent-adapter-codex
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "super-dsh",
3
- "version": "0.1.2",
3
+ "version": "0.1.3-d",
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",
@@ -9,6 +9,7 @@
9
9
  "url": "git+https://github.com/pgmi-builds/superd.git"
10
10
  },
11
11
  "exports": {
12
+ ".": "./agent-hub/dist/index.js",
12
13
  "./hub": "./agent-hub/dist/index.js",
13
14
  "./join": "./agent-hub/dist/world-join.js",
14
15
  "./world/omp": "./agent-omp/dist/world-plugin.js",
@@ -17,12 +18,13 @@
17
18
  "./world/pi": "./agent-pi/dist/world-plugin.js",
18
19
  "./world/hermes": "./agent-hermes/dist/world-plugin.js",
19
20
  "./world/agy": "./agent-agy/dist/world-plugin.js",
20
- "./client": "./agent-hub/lib/client/index.js",
21
+ "./client": "./client/index.js",
21
22
  "./cordis.patch.yml": "./cordis.patch.yml",
22
23
  "./package.json": "./package.json"
23
24
  },
24
25
  "files": [
25
26
  "cordis.patch.yml",
27
+ "client",
26
28
  "README.md",
27
29
  "agent-hub/dist",
28
30
  "agent-hub/lib",