super-dsh 0.1.11 → 0.1.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/README.md +54 -6
  2. package/agent-agy/dist/agent.d.ts +4 -0
  3. package/agent-agy/dist/agent.js +41 -7
  4. package/agent-agy/dist/agy-cli-client.d.ts +12 -0
  5. package/agent-agy/dist/agy-cli-client.js +81 -13
  6. package/agent-agy/dist/index.js +13 -7
  7. package/agent-agy/package.json +5 -1
  8. package/agent-claude/dist/agent.js +67 -4
  9. package/agent-claude/dist/claude-client.js +46 -1
  10. package/agent-claude/dist/index.js +3 -0
  11. package/agent-claude/dist/sdk-runtime.js +2 -2
  12. package/agent-codex/dist/agent.js +33 -8
  13. package/agent-codex/dist/app-server-client.js +26 -3
  14. package/agent-codex/dist/app-server-protocol.js +6 -2
  15. package/agent-codex/dist/app-server-wire.js +23 -6
  16. package/agent-codex/dist/codex-native-config.js +6 -1
  17. package/agent-codex/dist/codex-runtime-fetch.js +293 -0
  18. package/agent-codex/dist/codex-runtime.js +12 -12
  19. package/agent-codex/dist/index.js +10 -4
  20. package/agent-codex/package.json +8 -3
  21. package/agent-codex-sdk/dist/sdk-runtime.js +1 -1
  22. package/agent-hermes/dist/hermes-client.js +44 -5
  23. package/agent-hermes/dist/index.js +10 -5
  24. package/agent-omp/dist/agent.js +36 -5
  25. package/agent-omp/dist/index.js +29 -6
  26. package/agent-omp/dist/lazy-rpc.js +11 -2
  27. package/agent-omp/dist/rpc-client.js +6 -1
  28. package/agent-pi/dist/agent.js +36 -9
  29. package/agent-pi/dist/index.js +6 -2
  30. package/agent-pi/dist/pi-client.js +13 -3
  31. package/cordis.patch.yml +10 -9
  32. package/package.json +6 -4
  33. package/superd-hub/dist/a2a-row.js +20 -3
  34. package/superd-hub/dist/connection-trust.d.ts +8 -0
  35. package/superd-hub/dist/connection-trust.js +16 -0
  36. package/superd-hub/dist/foreign-agy.d.ts +3 -0
  37. package/superd-hub/dist/foreign-agy.js +110 -0
  38. package/superd-hub/dist/foreign-claude.d.ts +4 -0
  39. package/superd-hub/dist/foreign-claude.js +160 -0
  40. package/superd-hub/dist/foreign-extension.d.ts +10 -0
  41. package/superd-hub/dist/foreign-extension.js +27 -0
  42. package/superd-hub/dist/foreign-hub.d.ts +27 -0
  43. package/superd-hub/dist/foreign-hub.js +243 -0
  44. package/superd-hub/dist/foreign-native.d.ts +4 -0
  45. package/superd-hub/dist/foreign-native.js +115 -0
  46. package/superd-hub/dist/web-trust.d.ts +14 -42
  47. package/superd-hub/dist/web-trust.js +18 -43
  48. package/superd-hub/package.json +14 -2
  49. package/agent-codex/README.md +0 -191
  50. package/agent-codex-sdk/README.md +0 -79
  51. package/agent-hermes/README.md +0 -145
  52. package/agent-omp/README.md +0 -94
  53. package/agent-omp-sdk/README.md +0 -103
  54. package/agent-pi/README.md +0 -67
@@ -1,145 +0,0 @@
1
- # @pgmi-builds/agent-hermes
2
-
3
- Hermes provider for DeepSeek Harness (dsh) — an AgentFactory that embeds the
4
- Nous Research Hermes Agent via the TUI gateway JSON-RPC (`python -m
5
- tui_gateway.entry`) and bridges its session surface into Dash Agent/Session
6
- contracts (Super D; parity round 2026-09-17 = Task M1 of
7
- `docs/superpowers/plans/2026-09-17-superd-five-adapter-parity-fixes.md`).
8
-
9
- ## Layout
10
-
11
- - `src/models.ts` — gateway `model.options` → Dash model catalog (trim rules,
12
- r4 id dedupe, provider-name cache, slug list). Pure + fail-soft.
13
- - `src/adapter.ts` — `HermesLlmAdapter`: one route per real gateway provider
14
- slug; `providerInfo` display names; ids stay verbatim selection strings.
15
- - `src/index.ts` — `HermesProvider` (AgentFactory): creation transaction,
16
- boot route registration + atomic swap, default-model push, session map.
17
- - `src/agent.ts` — `HermesAgent`: wire→DSH event bridge, usage conversion,
18
- turn-error classification, resume self-heal, title/todo mirroring.
19
- - `src/hermes-events.ts` — PURE gateway-event → omp-wire projector.
20
- - `src/hermes-client.ts` — one client = one gateway child = one session
21
- (spawn/env/ready/turn-settle/approval bridge; liveness getters; adoption
22
- listener; opt-in idle-probe reaper).
23
- - `src/hermes-store.ts` — `<dshHome>/agents/hermes/dsh-sessions.json` map.
24
- - `test/` — imports `dist/`; build first (`npm run build`), then
25
- `node --test test/*.test.mjs`. The world-plugin smoke needs the repo farm:
26
- run with `DSH_HOME=<repo>/.tests` (it refuses prod homes).
27
-
28
- ## Per-adapter rulings (2026-09-17 M1; recorded per dev-rules §4/§12)
29
-
30
- 1. **Model grouping by real provider slug** (RC-3 fix). Boot registers the
31
- single placeholder route `hermes` (the selector stays alive while the async
32
- probe runs); when the first `model.options` probe resolves, the
33
- registration atomically swaps to the DISTINCT surviving provider slugs
34
- (`AdapterRegistrationHandle.replace` — validated in full, one synchronous
35
- section). `listModels(provider)` filters by the entry's own `provider`;
36
- `resolveModel` matches the (provider, id) pair. Model ids are NEVER
37
- reformatted: they are the gateway's verbatim selection strings
38
- (`session.create {model}` / `/model <id>` consume them as-is — wire
39
- contract). The default-model push and the per-session route pin
40
- (`model/selection`, `request/context`) carry `{provider: slug, model: id}`,
41
- canonicalized through the catalog entry (the r4 dedupe gives every id ONE
42
- provider route, so a pinned route always resolves).
43
- 2. **Catalog trims** (the "579-model wall" fix), applied at mapping time in
44
- `mapHermesModelOptions`:
45
- - `source: "virtual"` rows drop (the `moa` synthesizer is not a selectable
46
- endpoint);
47
- - mirrored endpoints with IDENTICAL model-id sets collapse onto one row —
48
- first in gateway order wins, except a later `is_current` mirror displaces
49
- a non-current winner (fixture: `copilot`/`copilot-acp`,
50
- `zai-plan`/`zhipu`; 17 providers → 14 groups, 579 → 526 listed ids);
51
- - endpoints with MORE than 50 models reorder `featured_models` first
52
- (gateway order), remainder alphabetically; smaller rows keep gateway
53
- order (the 47-model openrouter row is untouched).
54
- The `authenticated !== true` filter predates this ruling and is unchanged.
55
- 3. **Cross-provider id dedupe stays (r4)**: an id listed under several slugs
56
- keeps ONE canonical route (first surviving row, current-row preferred).
57
- Rationale: the wire sends only the model id, so a duplicate listing would
58
- fabricate provider-specific selection the gateway cannot honor; canonical
59
- routes keep every pinned route resolvable. Consequence: multi-homed ids
60
- (e.g. `kimi-k3` under copilot/qwen-cn/kimi-cn) list under their canonical
61
- route only.
62
- 4. **`todo/write`** (typed transcript): the gateway's whole-list
63
- `todo.updated {todos, revision}` snapshot → wire `todo_updated` (projector;
64
- DSH-shaped items: trimmed content, status ∈ {pending, in_progress,
65
- completed}; `cancelled`/unknown statuses and duplicate/blank content drop —
66
- the DSH `todo/write` invariant has no cancelled status and forbids
67
- repeats) → the agent appends the log-only `todo/write {todos}` snapshot,
68
- only inside an open turn (upstream invariant), latest-wins. Log-only
69
- semantics kept (upstream `tool-todo` contract); the todo tool pair still
70
- renders through `tool_execution_*` as before.
71
- 5. **`session/title` mirror**: gateway `session.title {session_id, title}` →
72
- wire `session_title` (pi wire parity) → `session/title
73
- {title, messageSeqs: [], source:{kind:"provider", provider:"hermes"}}`,
74
- deduped, fail-soft, never affects the turn. The client-side `session.info`
75
- title capture stays (feeds `session.create`'s title + tracing).
76
- 6. **Turn usage** (RC-6 fix). Fixture verdict (`gateway-events.sample.json`
77
- index 13): the gateway's `total` is CONTEXT-WIDE, not per-message —
78
- `total 26805 = prompt 26803 + completion 2` and `prompt === context_used`
79
- (the whole re-sent window), so trusting it would inflate every turn.
80
- `convertUsage` therefore synthesizes the per-attempt-provable
81
- `totalTokens = inputTokens + outputTokens` (fixture: 19251 + 2 = 19253),
82
- which the DSH token-meter fold accepts (`normalizeUsage` needs `totalTokens`
83
- or BOTH cache buckets; the gateway shape has none — the pre-fix sample
84
- folded to `undefined` every turn). `reasoningTokens` rides only when
85
- `reasoning ≤ output` (Dash: reasoning ⊆ output; the fold rejects larger
86
- values). No cache tokens are invented (the gateway reports none —
87
- `cache_hit_pct` is a percentage).
88
- 7. **Resume self-heal over lazy spawn** (RC-4 fix, ruling 4 of the plan; full
89
- lazy spawn deferred):
90
- - The client exposes `usable` / `closed` / `failure` liveness getters.
91
- - On a CLIENT-TERMINAL failure (child exit, ready timeout, close — the
92
- client's `usable` is false) the agent's failure path — and the cold-start
93
- path — triggers the full idle-exit dispose (`#onIdleExit`), so the host
94
- unregisters the dead agent and re-resumes a FRESH client on the next
95
- prompt. Ordinary per-turn failures never dispose.
96
- - The spawn-grace reaper is now OPT-IN (`spawn({spawnGraceMs})`) and only
97
- the self-closing catalog-probe client arms it (env
98
- `HERMES_SPAWN_GRACE_MS`, default 10 min, `0` disables). AGENT-HELD
99
- clients never arm it: a view-time eager resume may legitimately sit
100
- unprompted far beyond any grace, and reaping it stamped the terminal
101
- "hermes gateway client closed" failure that wedged every later prompt
102
- (the reported wedge). Accepted trade-off until full lazy spawn lands: a
103
- resumed-but-never-prompted session pins its gateway child until the host
104
- disposes the agent (session close / owner unload).
105
- - Turn errors are CLASSIFIED instead of a bare UNKNOWN:
106
- `GatewayRpcError` 4001/4006 → `NATIVE_SESSION_GONE` (message names the
107
- stored gateway session), gateway child exit/error → `GATEWAY_CRASH`,
108
- dead client → `CLIENT_CLOSED`. The code renders in the Web UI error chip
109
- (`turn/end {kind:"error", error:{message, code}}`).
110
- - `stored_session_id` DRIFT tolerance: adoption
111
- (session.create/resume response) fires the client's `onAdopted` listener;
112
- the provider's map upsert always tracks the latest adopted pair, so a
113
- gateway that remints the durable key on resume cannot strand future
114
- resumes on a stale key.
115
- 8. **Model list / switching semantics** (unchanged, recorded): selection
116
- applies to the session's pinned route immediately (next request); a fresh
117
- session receives the model at `session.create`. The gateway resolves its
118
- own provider from the model id; the adapter does not second-guess it.
119
- 9. **Homes** (dev-rules §5/§13): the Hermes runtime keeps its native
120
- `~/.hermes` home — never redirected, never seeded. `<dshHome>/agents/hermes/`
121
- holds only the adapter's DSH-side state (`dsh-sessions.json`).
122
-
123
- ## Testing
124
-
125
- ```bash
126
- npm run build
127
- DSH_HOME=<repo>/.tests node --test test/*.test.mjs
128
- ```
129
-
130
- All unit/fixture tests fake the gateway child (`setGatewayFactory`) — no real
131
- python child in any test (the opt-in live suite was retired with the
132
- 2026-09-24 scenario retirement; whole-plugin scenarios run on the superd
133
- 4999 pack line).
134
-
135
- ## Trap: `npm install` materializes the hub link
136
-
137
- This package depends on `@pgmi-builds/superd-hub` via `file:../superd-hub`. A
138
- bare `npm install` replaces the symlink with a PHYSICAL copy → a second hub
139
- instance in the same process → every world webServer stays `pending` forever.
140
- After any `npm install` here, re-link it:
141
-
142
- ```bash
143
- rm -rf node_modules/@pgmi-builds/superd-hub
144
- ln -s ../../../../super-dsh/superd-hub node_modules/@pgmi-builds/superd-hub
145
- ```
@@ -1,94 +0,0 @@
1
- # @pgmi-builds/agent-omp(OMP adapter,RPC 线)
2
-
3
- OMP provider for DeepSeek Harness([dsh](https://www.npmjs.com/package/@deepseek-ai/dsh))。
4
-
5
- **不内嵌任何 OMP 代码副本**:适配器用操作员本机已在用的 `omp` binary,以 `omp --mode rpc` 子进程形态驱动,
6
- stdio 上跑 OMP 的 NDJSON 协议(v1),把 OMP 的 RPC 面(prompt / follow_up / steer / abort / get_state /
7
- get_messages / set_model / resume / compact)桥接进 Dash 的 Agent/Session 契约,标准 DSH Web UI 即可驱动 OMP 会话。
8
- 模型选择由 OMP 数据面的 `LlmAdapter` 承接(`config.yml` 的 `modelRoles`)。
9
-
10
- ## 集成形态
11
-
12
- ```
13
- dsh 宿主 (Node 22, 本包 dist/) 操作员本机的 omp binary
14
- omp-web 衔接层(agent/adapter/ ←→ `omp --mode rpc`(NDJSON v1 over stdio)
15
- replay/store/supervisor) ~/.omp 是其唯一的 app home
16
- ```
17
-
18
- - **没有 sidecar,没有 Bun,没有 SDK 依赖**:一会话一 `omp --mode rpc` 子进程,进程生命周期跟随会话。
19
- - **binary 解析**(`src/rpc-client.ts` 的 `resolveOmpExecutable()`):
20
- `$OMP_EXECUTABLE` → `PATH` 上的 `omp` → `~/.local/bin/omp` / `/usr/local/bin/omp` → 裸 `"omp"`(让 spawn 报 ENOENT)。
21
- - **进程组隔离**:子进程 `detached` 自成进程组,teardown 走 SIGTERM + 2s 宽限后 SIGKILL,保证 `omp` 及其工具子进程不残留。
22
-
23
- ## 安装与启用
24
-
25
- 本包是 `super-dsh` 单一交付包内的兄弟目录,**不单独安装**(`dsh plugin --profile <name> add super-dsh`),
26
- 也不需要预装任何 OMP SDK。唯一的外部前置条件 = **操作员机器上有 `omp`**:
27
-
28
- - 缺失时不静默回落:adapter 在 `apply()` 做一次二进制可解析性探测并打显式诊断,首轮 prompt 以 spawn 错误 fail loud 冒到会话。
29
- - 启用由包内 `cordis.patch.yml` 承担(挂 OMP provider + 禁用原生 agent-loop / llm 路由),profile 无需手改。
30
-
31
- ## Home 布局(两个 home,别混)
32
-
33
- | 名字 | 是什么 | 定义(`src/knobs.ts`) | 默认 |
34
- |---|---|---|---|
35
- | **`OMP_HOME`** | OMP runtime app home(`agent.db`/`models.db`/`sessions/` 的写入目标,也是数据面子进程的 cwd) | `$OMP_HOME ?? resolveOmpNativeHome()` | **原生 `~/.omp`**(`$OMP_HOME` 只作测试 / 适配器级隔离 knob) |
36
- | **`OMP_NATIVE_HOME`** | 操作员的原生 OMP 安装(TUI/CLI)读面:`agent/config.yml`、`agent/models.yml`、原生 session store | `$OMP_NATIVE_HOME ?? join(homedir(), ".omp")` | `~/.omp` |
37
- | `<DSH_HOME>/agents/omp/` | 该 world 的 **DSH** home(DSH 会话日志、storages、settings) | dsh 宿主解析 | 非 app home |
38
-
39
- - spawn **零重定向**:不把 `OMP_HOME` 喂给子进程;`~/.omp` 是唯一 OMP app home。
40
- - 绝不要把 `OMP_NATIVE_HOME` 指到空目录 / 测试 home——它是 models.yml 的读取来源,读空 ⇒ 适配器零 provider ⇒ `session/prompt` 报 `model-unavailable`。
41
-
42
- ## 数据面(`omp` 子进程)
43
-
44
- `src/omp-cli.ts` 把操作员 binary 作为模型目录与 `modelRoles` 的**第一源**(不吃 RPC 帧);原生 `~/.omp` 的文件只作失败回落与排序读面:
45
-
46
- - `omp models --json` → 凭证解析后的可用模型目录(含 agent.db 里的 OAuth/login key 等配置面看不见的凭证);子进程失败才回落磁盘 `models.db` ∪ `models.yml`(并打 stderr 提示)。
47
- - `omp config get modelRoles --json` → role → `"provider/model[:effort]"` 映射(含持久化的 `default` 选择),每次现读。
48
- - `omp config set modelRoles --json <obj>` → 整对象回写(拒绝点号 key),OMP 自己持久化 `modelRoles.default`。
49
- - provider 排序与 boot 期默认模型仍首选 `agent/config.yml` 磁盘读(`omp-store.ts` 的 mini-YAML 扫描),`ompModelRolesSync` 兜底。
50
- - 每次调用都按 `resolveOmpExecutable()` 现解析、`cwd = OMP_HOME`;**fail-soft**:binary 缺失/损坏/无响应 → 读 `undefined`、写 `false`,provider 永因 CLI 挂掉而 boot 失败。
51
-
52
- ## 实现要点
53
-
54
- - **传输**:`src/rpc-client.ts` 的 `OmpRpcClient` —— NDJSON 读取(按 `\n` 切帧)、`ready` 握手(默认 120s 上限,`OMP_READY_TIMEOUT_MS`)、
55
- per-command 响应 deadline(默认 30s,`OMP_COMMAND_TIMEOUT_MS`)、`on`/`onTitle`/`onFailure` 事件分发。
56
- - **不协商协议**:不发 `negotiate_protocol`,停在 v1 = 纯 NDJSON(旧读取器即正确)。协商到 v2 会切换到 >1MiB 分帧,需要重组器——列为已知 gap。
57
- - **lazy 铁律**:`src/lazy-rpc.ts` 的 `LazyOmpRpc` 是唯一 spawn 点,构造零 spawn;`prompt`/`followUp`/`steer`/`ensureStarted` 才拉起子进程,
58
- 被动查询(`getState`/`getSubagents`/`getSessionStats`/`getSystemPrompt`/`abort`/`sendRaw`)合成应答、绝不 spawn。
59
- `createAgent` 与 `resume` 两条路径都走它(resume 有映射时加 `--resume <ompFile>`),生成参数 `--approval-mode <mode>`。
60
- - **两平面**:dsh 原生 session log 是 WebUI 唯一读面(插件当 producer:OMP RPC 事件 → SessionEvent → `ctx.sessionPersistence`);
61
- OMP 原生会话文件是 runtime 权威(插件当 bridge:`bridge-store.sqlite` 只存 dsh↔omp 映射)。双份存储显式接受,单向阀 = 不回读。
62
- - **已删除面**(本 RPC 轮,2026-10-03):`src/sdk-client.ts`、`src/sidecar-client.ts`、`src/protocol.ts`、`sidecar/`,以及 SDK/Bun 依赖与 `test/sidecar-*.test.mjs`;`scripts/build-client.ts` 与 `src/client/`、`src/mobile/` 保留(client 半边与 sidecar 无关)。
63
-
64
- ## 协议与实测记录(2026-10-03)
65
-
66
- `ready` 帧实测:
67
-
68
- ```json
69
- {"type":"ready","protocolVersion":1,"supportedProtocolVersions":[1,2],
70
- "maxFrameBytes":1048576,"maxReassembledFrameBytes":67108864}
71
- ```
72
-
73
- - 只要求 `type === "ready"`;`protocolVersion` / `supportedProtocolVersions` / `maxFrameBytes` / `maxReassembledFrameBytes` 记录不校验。
74
- - 不协商的路径实测停在 v1;`get_state` / `get_available_models` 未协商也照常应答;事件词表
75
- (`agent_start` / `turn_start` / `message_start` / `message_update` / `message_end` / `tool_execution_start` / `tool_execution_end` / `turn_end` / `agent_end`)与 `agent.ts` 的 switch 对齐。
76
- - 已知 gap:v2 分帧未实现(单帧 >1MiB 靠大行承载);对 `omp` 版本门仅实测 v18.4.9。
77
-
78
- ## 测试
79
-
80
- ```bash
81
- npm run build # tsc -p tsconfig.json && tsc -p tsconfig.client.json
82
- node --test test/*.test.mjs # 全 fakes / 源级断言,零真 runtime、零真 omp spawn
83
- ```
84
-
85
- - `test/no-sidecar.test.mjs` = RPC 轮的删除面 + tick 门双重把守(源级断言:`src/` 不得再出现 SDK/sidecar client;
86
- `index.ts` 只能 `new LazyOmpRpc(`;tick 的目录刷新必须挂在 `liveOmpSessionExists` 上,并对编译后的 `dist/index.js` 跑行为真值表)。
87
- - `rpc-client` / `lazy-rpc` / `omp-cli-rpc` / `resolve-executable` / `package-contract` 覆盖传输、lazy 不变量、数据面与交付清单。
88
- - **场景级验证只走整包**:`super-dsh` 的 4999 pack 线(`test/start-4999.sh`)+ dev3 目标机实装;本目录不再有 per-agent 场景 rig。
89
-
90
- ## 历史
91
-
92
- 本包在 2026-10-03 前是内嵌 SDK + Bun 子进程(sidecar)线(SDK 事件 → SessionEvent,单进程多路复用);该线连同
93
- 762M SDK 树 + 76M bun 二进制一起从交付面删除,改用操作员本机 binary 的 RPC 传输(设计正本:
94
- `docs/specs/omp-rpc-transport/spec.md`)。
@@ -1,103 +0,0 @@
1
- # @pgmi-builds/agent-omp-sdk — OMP (SDK) adapter (opt-in)
2
-
3
- The **second** OMP adapter package, alongside `@pgmi-builds/agent-omp` (the RPC
4
- line). It is a complete, standalone copy of the pre-RPC-era OMP bridge — no
5
- shared code with the RPC package.
6
-
7
- - **World key** `omp-sdk`, roster label `OMP (SDK)`, world home
8
- `<dshHome>/agents/omp-sdk` (deliberately not `agents/omp`).
9
- - **Off by default**: the `agent-omp-sdk` row in the super-dsh composite carries
10
- `disabled: true`, so while the row is off not one byte of this package is
11
- imported and nothing is fetched. Turning the row on (plugin manager
12
- `setPluginEnabled` / `dsh plugin`) IS the switch — no env var, no config key.
13
- - **Why it exists**: the RPC shape is one `omp` child per Dash session
14
- (~240 MB private each). This shape hosts **N sessions in one bun sidecar**
15
- and shares `authStorage` / `modelRegistry` across them, so the marginal cost
16
- per extra session is far lower.
17
-
18
- ## No dependency is declared, and nothing is fetched at install time
19
-
20
- `package.json` declares an **empty `dependencies`** — no coding-agent package,
21
- no `bun`, no `optionalDependencies`, no `postinstall`. `dsh plugin add` only
22
- unpacks this package; `npm pack` contains no SDK bytes (only our own
23
- `sidecar/main.ts` source, which imports the package *inside the fetched
24
- runtime*).
25
-
26
- The durable runtime is fetched **lazily**, on the first real prompt of an
27
- `omp-sdk` session (draft / browse / passive queries stay at zero action, the
28
- same zero-spawn window the RPC line holds):
29
-
30
- ```
31
- <worldHome>/sdk-runtime/
32
- bin/bun bun release (linux-x64) unzipped into place
33
- package.json / node_modules/ the pinned coding-agent package, installed with that bun
34
- sidecar/main.ts this package's sidecar (bun resolves node_modules from here)
35
- dist/protocol.js the compiled protocol module the sidecar imports
36
- <worldHome>/sdk-runtime.json marker: {pluginVersion, packageVersion, bunVersion, bunPath, installedAt}
37
- <worldHome>/sdk-runtime.lock atomic (mkdir) bootstrap lock
38
- <worldHome>/sdk-runtime.error.log written only by a failed fetch
39
- ```
40
-
41
- The marker is written **last**; a marker whose identity (`pluginVersion`,
42
- `packageVersion`, `bunVersion`) does not match the running adapter is treated as
43
- absent and refetched. The install is deliberately **slim**: `bun add --exact
44
- --ignore-scripts --omit=optional @oh-my-pi/pi-coding-agent@<pin>
45
- @oh-my-pi/pi-natives-<platform>@<pin>` — `--ignore-scripts` blocks package build
46
- scripts, `--omit=optional` drops the ~234 MB `@huggingface/transformers` +
47
- `onnxruntime-*` weight whose native postinstall is blocked anyway, and the
48
- platform binding package is re-added explicitly because `@oh-my-pi/pi-natives`
49
- needs it to load (`OMP_SDK_KEEP_OPTIONAL=1` reinstates the full tree). After the
50
- install the fetcher copies the sidecar and the compiled protocol module in, then
51
- runs a **post-install smoke import** (`<bun> -e 'await import("@oh-my-pi/pi-coding-agent")'`,
52
- agent dir redirected inside the runtime tree) and only then writes the marker —
53
- a pin that cannot be imported (18.4.9 is such a pin) fails loud here instead of
54
- at the first prompt.
55
-
56
- A failed fetch writes the error log and throws a single actionable error naming
57
- `OMP_SDK_PACKAGE_VERSION`; it never degrades silently into a confusing sidecar
58
- crash, and it never falls back to the RPC line (that is another row the user did
59
- not enable).
60
-
61
- ## Wiring (where the fetch is triggered, and where it is not)
62
-
63
- - `world-plugin.ts` mounts the world and prints ONE report-only diagnostic when
64
- the runtime is not on disk yet. It never fetches, spawns or imports the
65
- runtime.
66
- - `index.ts` (`OmpProvider`) builds its transport in the constructor — that
67
- builds a pool object, nothing else.
68
- - `transport.ts` / `lazy-rpc.ts` (`LazyOmpRpc`) construct per-session wrappers
69
- with **zero** side effects; a new-chat draft leaves nothing server-side.
70
- - `sidecar-client.ts` (`OmpSdkSidecar#start`) is the ONE place `ensureSdkRuntime`
71
- is awaited. `start()` is reached only from `LazyOmpRpc#ensure()`, i.e. from the
72
- first `prompt` / `followUp` / `steer` / `ensureStarted`.
73
- - `sdk-client.ts` (`createOmpSdkSidecarPool`) holds the refcounted singleton:
74
- two sessions of one dsh process share one bun child, and the pool releases
75
- (and stops) it when the last client closes.
76
-
77
- ## Manual warm-up
78
-
79
- ```sh
80
- node scripts/fetch-sdk-runtime.mjs <dsh-home> # world home = <dsh-home>/agents/omp-sdk
81
- # or, with the home in the environment:
82
- DSH_HOME=<dsh-home> npm run fetch-sdk-runtime
83
- ```
84
-
85
- The script is a dev/test tool: it refuses any home outside this repository's
86
- `.tests` tree (the launcher red line) and has no `~/.dsh` default. It shares
87
- `createSdkRuntimeDeps` with the adapter's first-prompt fetch, so the two paths
88
- cannot drift.
89
-
90
- Pins: `OMP_SDK_PACKAGE_VERSION` (default `18.5.0` — do not use 18.4.9, whose
91
- source-level import is broken; `18.2.11` is the last known-good fallback) and
92
- `OMP_SDK_BUN_VERSION` (default `1.4.2`).
93
-
94
- ## Build & test
95
-
96
- ```sh
97
- npm run build # tsc -p tsconfig.json
98
- npm test # node --test test/*.test.mjs (imports dist/, zero network, zero real bun)
99
- ```
100
-
101
- The suite is fakes-only: the runtime bootstrap is driven through its injected
102
- `SdkRuntimeDeps`, and the sidecar spawn path through an injected `runtimeFetch`.
103
- No test downloads, spawns bun or touches a real home.
@@ -1,67 +0,0 @@
1
- # @pgmi-builds/agent-pi (Super D)
2
-
3
- pi coding agent provider for DeepSeek Harness — an `AgentFactory` dsh plugin that embeds the
4
- **pi coding agent** (`@earendil-works/pi-coding-agent@0.84.2`) **in-process via its SDK**
5
- (`createAgentSession` / `AgentSession` / `ModelRuntime`) and bridges pi's session surface into
6
- the Dash Agent/Session contracts. Structure follows `agent-omp` (same pi-agent-core lineage);
7
- lifecycle follows `agent-codex` (AW-E SDK line, DSH-native session persistence).
8
-
9
- ## Per-adapter rulings (2026-09-17 user; decisions recorded per dev-rules §4/§12)
10
-
11
- 1. **Native data home `~/.pi`.** Unlike every prior adapter (codex `<dshHome>/agents/codex`,
12
- omp `<dshHome>/agents/omp/.omp`), pi keeps its **native home**: the adapter passes no
13
- `agentDir` override, so the SDK's `getAgentDir()` default applies — auth, models, settings,
14
- skills, extensions and project trust are exactly what the user's pi CLI sees. No app-home
15
- seeding, no config one-way-valve. Dev-rules §5/§13's app-home ruling is superseded for pi's
16
- runtime data by this directive. Tests redirect via `PI_CODING_AGENT_DIR` /
17
- `PI_CODING_AGENT_SESSION_DIR` env only.
18
- 2. **`<dshHome>/agents/pi/` = adapter-owned DSH state only** — currently the mapping file
19
- `dsh-sessions.json`. pi never reads it; it is DSH-side bookkeeping in the same class as the
20
- DSH session log itself.
21
- 3. **Session storage duplication accepted**: pi writes its native session JSONL under
22
- `~/.pi/agent/sessions/<encoded-cwd>/`; the adapter writes the DSH log through upstream
23
- `session-persistence-jsonl` (factory holds the write channel). The WebUI reads the DSH copy;
24
- the native copy stays pi's authority; no back-read of pi transcripts for list/replay.
25
- 4. **Session identity = "mapping only"** (codex model): the DSH session id is the authority;
26
- the pi session file path is `null` in the map until the first prompt materializes it; resume
27
- resolves through the map and **fails closed** when unknown. Lazy iron law: zero pi objects
28
- before the first real prompt.
29
- 5. **In-process SDK** (user choice "sdk, refer to omp agent adapter"): no sidecar, no
30
- `--mode rpc` subprocess. Shared module-level `ModelRuntime`; one `AgentSession` per session.
31
- 6. **Model route**: single provider id `pi` on `ctx.llm`; model ids are composite
32
- `<provider>/<modelId>` (pi is multi-provider). Selection is live (`session.setModel`) — an
33
- upgrade over the codex SDK line's next-turn-only switch. `steer` is also real (pi supports it).
34
- 7. **Permission presets → launch-only toolsets** (pi has no per-action approval):
35
- `danger-full-access` / `workspace-write` → pi default tools (`read,bash,edit,write`);
36
- `read-only` → `read,grep,find,ls`. `/permission` is shadowed per-session with a clean
37
- refusal; `PI_APPROVAL_MODE=<preset-name>` overrides for headless runs.
38
- 8. **Compaction is wired** (unlike codex): `/compact` works via `session.compact()`;
39
- pi `compaction_start|end` → DSH `compaction/start|end` with a generated `compactionId`.
40
- 9. **Titles**: pi owns them — `session_info_changed` → DSH `session/title`
41
- (`source: {kind:"provider", provider:"pi"}`); the dsh `session-title-llm` row stays disabled.
42
-
43
- ## Layout
44
-
45
- `src/`: `index.ts` (PiProvider + `setupAndPublish` transaction), `agent.ts` (PiAgent shim),
46
- `pi-client.ts` (SDK client seam + lazy start), `pi-events.ts` (pi → wire vocabulary projection),
47
- `session-map.ts`, `models.ts` (ModelRuntime singleton + catalog memo), `adapter.ts` (LlmAdapter),
48
- `permission.ts`, `agent-preset-pi.ts` + `agent-preset-projection.ts` (roster/chip), `pi-home.ts`
49
- (state dir), `knobs.ts`, `inbox.ts`, `world-plugin.ts` (hub bridge).
50
-
51
- ## Testing
52
-
53
- `npm run build` then `node --test test/*.test.mjs` — tests import `dist/`, use temp homes, and
54
- inject fake pi sessions via `setPiSessionFactory`; the SDK seam is never hit by unit tests.
55
- Acceptance = standalone `dsh + adapter` real instance (form A) with a real pi turn, then the
56
- world form (form B) via the hub.
57
-
58
- ## Trap: `npm install` materializes the hub link
59
-
60
- `dependencies["file:../superd-hub"]` gets materialized by `npm install` as a
61
- **physical copy** under `node_modules/@pgmi-builds/superd-hub` — a second hub
62
- module instance whose rosters/mount-registry are dead. Symptom in world form:
63
- the world's virtual webServer never appears (`9 entries did not activate`,
64
- everything pending on webServer). After ANY `npm install` in this package,
65
- re-link: `rm -rf node_modules/@pgmi-builds/superd-hub && ln -sfn ../../../superd-hub
66
- node_modules/@pgmi-builds/superd-hub` (codex symlink discipline; same class as
67
- the `@deepseek-ai/*` heal).