super-dsh 0.1.9 → 0.1.10-e

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (178) hide show
  1. package/README.md +25 -3
  2. package/agent-agy/cordis.patch.yml +7 -4
  3. package/agent-agy/dist/agent.d.ts +12 -11
  4. package/agent-agy/dist/agy-auth-gateway.d.ts +124 -0
  5. package/agent-agy/dist/agy-auth-gateway.js +233 -0
  6. package/agent-agy/dist/agy-auth.d.ts +153 -0
  7. package/agent-agy/dist/agy-auth.js +179 -0
  8. package/agent-agy/dist/agy-cli-client.d.ts +39 -9
  9. package/agent-agy/dist/agy-cli-client.js +82 -18
  10. package/agent-agy/dist/agy-store.d.ts +8 -0
  11. package/agent-agy/dist/index.d.ts +46 -16
  12. package/agent-agy/dist/index.js +82 -56
  13. package/agent-agy/dist/models.d.ts +70 -0
  14. package/agent-agy/dist/models.js +102 -3
  15. package/agent-agy/package.json +7 -5
  16. package/agent-agy-sdk/cordis.patch.yml +58 -0
  17. package/agent-agy-sdk/dist/adapter.d.ts +15 -0
  18. package/agent-agy-sdk/dist/adapter.js +42 -0
  19. package/agent-agy-sdk/dist/agent-preset-agy.d.ts +27 -0
  20. package/agent-agy-sdk/dist/agent-preset-agy.js +32 -0
  21. package/agent-agy-sdk/dist/agent.d.ts +138 -0
  22. package/agent-agy-sdk/dist/agent.js +494 -0
  23. package/{agent-agy → agent-agy-sdk}/dist/agy-client.d.ts +26 -6
  24. package/{agent-agy → agent-agy-sdk}/dist/agy-client.js +43 -25
  25. package/agent-agy-sdk/dist/agy-sessions.d.ts +25 -0
  26. package/agent-agy-sdk/dist/agy-sessions.js +107 -0
  27. package/agent-agy-sdk/dist/agy-store.d.ts +39 -0
  28. package/agent-agy-sdk/dist/agy-store.js +83 -0
  29. package/agent-agy-sdk/dist/inbox.d.ts +26 -0
  30. package/agent-agy-sdk/dist/inbox.js +53 -0
  31. package/agent-agy-sdk/dist/index.d.ts +93 -0
  32. package/agent-agy-sdk/dist/index.js +476 -0
  33. package/agent-agy-sdk/dist/models.d.ts +41 -0
  34. package/agent-agy-sdk/dist/models.js +74 -0
  35. package/agent-agy-sdk/dist/sdk-venv.d.ts +76 -0
  36. package/agent-agy-sdk/dist/sdk-venv.js +173 -0
  37. package/agent-agy-sdk/dist/world-plugin.d.ts +10 -0
  38. package/agent-agy-sdk/dist/world-plugin.js +82 -0
  39. package/agent-agy-sdk/package.json +64 -0
  40. package/agent-claude/dist/adapter.js +106 -31
  41. package/agent-claude/dist/agent.js +154 -17
  42. package/agent-claude/dist/claude-client.js +84 -43
  43. package/agent-claude/dist/claude-launch.js +101 -0
  44. package/agent-claude/dist/claude-native-config.js +169 -0
  45. package/agent-claude/dist/claude-provider-gateway.js +340 -0
  46. package/agent-claude/dist/claude-providers.js +391 -0
  47. package/agent-claude/dist/claude-route.js +152 -0
  48. package/agent-claude/dist/index.js +214 -37
  49. package/agent-claude/dist/models.js +14 -0
  50. package/agent-claude/dist/sdk-runtime.js +320 -0
  51. package/agent-claude/package.json +6 -4
  52. package/agent-codex/README.md +141 -36
  53. package/agent-codex/cordis.patch.yml +14 -10
  54. package/agent-codex/dist/adapter.js +64 -28
  55. package/agent-codex/dist/agent.js +255 -81
  56. package/agent-codex/dist/app-server-approvals.js +165 -0
  57. package/agent-codex/dist/app-server-client.js +723 -0
  58. package/agent-codex/dist/app-server-events.js +432 -0
  59. package/agent-codex/dist/app-server-protocol.js +95 -0
  60. package/agent-codex/dist/app-server-wire.js +299 -0
  61. package/agent-codex/dist/codex-launch.js +78 -0
  62. package/agent-codex/dist/codex-native-config.js +392 -0
  63. package/agent-codex/dist/codex-provider-gateway.js +402 -0
  64. package/agent-codex/dist/codex-providers.js +376 -0
  65. package/agent-codex/dist/codex-route.js +86 -0
  66. package/agent-codex/dist/index.js +256 -115
  67. package/agent-codex/dist/permission.js +75 -1
  68. package/agent-codex/package.json +1 -2
  69. package/agent-codex-sdk/README.md +79 -0
  70. package/agent-codex-sdk/cordis.patch.yml +81 -0
  71. package/agent-codex-sdk/dist/adapter.js +91 -0
  72. package/agent-codex-sdk/dist/agent-preset-codex.js +32 -0
  73. package/agent-codex-sdk/dist/agent.js +1085 -0
  74. package/agent-codex-sdk/dist/codex-native-config.js +392 -0
  75. package/agent-codex-sdk/dist/codex-provider-gateway.js +402 -0
  76. package/agent-codex-sdk/dist/codex-providers.js +376 -0
  77. package/agent-codex-sdk/dist/codex-route.js +86 -0
  78. package/{agent-codex/dist/codex-client.js → agent-codex-sdk/dist/codex-sdk-client.js} +253 -32
  79. package/agent-codex-sdk/dist/codex-sdk-launch.js +92 -0
  80. package/agent-codex-sdk/dist/codex-store.js +180 -0
  81. package/agent-codex-sdk/dist/inbox.js +53 -0
  82. package/agent-codex-sdk/dist/index.js +739 -0
  83. package/agent-codex-sdk/dist/permission.js +71 -0
  84. package/agent-codex-sdk/dist/sdk-runtime.js +307 -0
  85. package/agent-codex-sdk/dist/session-map.js +167 -0
  86. package/agent-codex-sdk/dist/world-plugin.js +93 -0
  87. package/agent-codex-sdk/package.json +79 -0
  88. package/agent-codex-sdk/scripts/fetch-sdk-runtime.mjs +57 -0
  89. package/agent-omp/README.md +72 -55
  90. package/agent-omp/dist/agent.js +36 -11
  91. package/agent-omp/dist/index.js +92 -52
  92. package/agent-omp/dist/lazy-rpc.js +11 -4
  93. package/agent-omp/dist/omp-cli.js +114 -97
  94. package/agent-omp/dist/omp-store.js +12 -4
  95. package/agent-omp/dist/permission.js +70 -5
  96. package/agent-omp/dist/rpc-client.js +409 -0
  97. package/agent-omp/dist/world-plugin.js +36 -3
  98. package/agent-omp/package.json +2 -6
  99. package/agent-omp-sdk/README.md +103 -0
  100. package/agent-omp-sdk/cordis.patch.yml +108 -0
  101. package/agent-omp-sdk/dist/adapter.d.ts +21 -0
  102. package/agent-omp-sdk/dist/adapter.js +36 -0
  103. package/agent-omp-sdk/dist/agent-preset-omp.d.ts +31 -0
  104. package/agent-omp-sdk/dist/agent-preset-omp.js +32 -0
  105. package/agent-omp-sdk/dist/agent.d.ts +64 -0
  106. package/agent-omp-sdk/dist/agent.js +1178 -0
  107. package/agent-omp-sdk/dist/discovery.d.ts +57 -0
  108. package/agent-omp-sdk/dist/discovery.js +116 -0
  109. package/agent-omp-sdk/dist/inbox.d.ts +28 -0
  110. package/agent-omp-sdk/dist/inbox.js +53 -0
  111. package/agent-omp-sdk/dist/index.d.ts +60 -0
  112. package/agent-omp-sdk/dist/index.js +632 -0
  113. package/agent-omp-sdk/dist/knobs.d.ts +34 -0
  114. package/agent-omp-sdk/dist/knobs.js +50 -0
  115. package/agent-omp-sdk/dist/lazy-rpc.d.ts +98 -0
  116. package/agent-omp-sdk/dist/lazy-rpc.js +178 -0
  117. package/agent-omp-sdk/dist/mobile/zoom-guard.d.ts +187 -0
  118. package/agent-omp-sdk/dist/mobile/zoom-guard.js +294 -0
  119. package/agent-omp-sdk/dist/mobile-boot.d.ts +49 -0
  120. package/agent-omp-sdk/dist/mobile-boot.js +38 -0
  121. package/agent-omp-sdk/dist/models.d.ts +39 -0
  122. package/agent-omp-sdk/dist/models.js +299 -0
  123. package/agent-omp-sdk/dist/omp-cli.d.ts +67 -0
  124. package/agent-omp-sdk/dist/omp-cli.js +164 -0
  125. package/agent-omp-sdk/dist/omp-disk-discovery.d.ts +27 -0
  126. package/agent-omp-sdk/dist/omp-disk-discovery.js +178 -0
  127. package/agent-omp-sdk/dist/omp-executable.d.ts +2 -0
  128. package/agent-omp-sdk/dist/omp-executable.js +30 -0
  129. package/agent-omp-sdk/dist/omp-store.d.ts +134 -0
  130. package/agent-omp-sdk/dist/omp-store.js +526 -0
  131. package/agent-omp-sdk/dist/pairing.d.ts +7 -0
  132. package/agent-omp-sdk/dist/pairing.js +45 -0
  133. package/agent-omp-sdk/dist/permission.d.ts +138 -0
  134. package/agent-omp-sdk/dist/permission.js +161 -0
  135. package/agent-omp-sdk/dist/protocol.d.ts +189 -0
  136. package/agent-omp-sdk/dist/rpc-types.d.ts +77 -0
  137. package/agent-omp-sdk/dist/rpc-types.js +1 -0
  138. package/agent-omp-sdk/dist/sdk-client.d.ts +160 -0
  139. package/{agent-omp → agent-omp-sdk}/dist/sdk-client.js +108 -56
  140. package/agent-omp-sdk/dist/sdk-runtime.d.ts +211 -0
  141. package/agent-omp-sdk/dist/sdk-runtime.js +418 -0
  142. package/agent-omp-sdk/dist/sidecar-client.d.ts +87 -0
  143. package/agent-omp-sdk/dist/sidecar-client.js +197 -0
  144. package/agent-omp-sdk/dist/store/adapter.d.ts +17 -0
  145. package/agent-omp-sdk/dist/store/adapter.js +47 -0
  146. package/agent-omp-sdk/dist/store/db.d.ts +70 -0
  147. package/agent-omp-sdk/dist/store/db.js +210 -0
  148. package/agent-omp-sdk/dist/store/index.d.ts +23 -0
  149. package/agent-omp-sdk/dist/store/index.js +59 -0
  150. package/agent-omp-sdk/dist/store/reconcile.d.ts +15 -0
  151. package/agent-omp-sdk/dist/store/reconcile.js +51 -0
  152. package/agent-omp-sdk/dist/store/schema.d.ts +8 -0
  153. package/agent-omp-sdk/dist/store/schema.js +40 -0
  154. package/agent-omp-sdk/dist/transport.d.ts +49 -0
  155. package/agent-omp-sdk/dist/transport.js +35 -0
  156. package/agent-omp-sdk/dist/world-home.d.ts +4 -0
  157. package/agent-omp-sdk/dist/world-home.js +23 -0
  158. package/agent-omp-sdk/dist/world-plugin.d.ts +10 -0
  159. package/agent-omp-sdk/dist/world-plugin.js +137 -0
  160. package/agent-omp-sdk/package.json +87 -0
  161. package/client/index.js +1204 -93
  162. package/cordis.patch.yml +64 -0
  163. package/package.json +17 -8
  164. package/superd-hub/dist/client/agent-settings.d.ts +210 -0
  165. package/superd-hub/dist/client/agent-settings.js +300 -0
  166. package/superd-hub/dist/client/roster.js +6 -0
  167. package/superd-hub/dist/client/runtime-settings-api.d.ts +76 -0
  168. package/superd-hub/dist/client/runtime-settings-api.js +137 -0
  169. package/superd-hub/dist/client/switch.d.ts +165 -0
  170. package/superd-hub/dist/client/switch.js +295 -0
  171. package/superd-hub/lib/client/index.js +1204 -93
  172. package/agent-codex/dist/models.js +0 -152
  173. package/agent-omp/dist/sidecar-client.js +0 -195
  174. /package/{agent-agy → agent-agy-sdk}/bridge/agy_bridge.py +0 -0
  175. /package/{agent-agy → agent-agy-sdk}/bridge/gemini_openai_server.mjs +0 -0
  176. /package/{agent-codex/dist/codex-events.js → agent-codex-sdk/dist/codex-sdk-events.js} +0 -0
  177. /package/{agent-omp → agent-omp-sdk}/dist/protocol.js +0 -0
  178. /package/{agent-omp → agent-omp-sdk}/sidecar/main.ts +0 -0
@@ -10,6 +10,10 @@ const PRESETS = {
10
10
  export function isPresetName(raw) {
11
11
  return typeof raw === "string" && Object.hasOwn(PRESETS, raw);
12
12
  }
13
+ /** Narrow an untrusted value to a known sandbox mode. */
14
+ export function isSandboxMode(raw) {
15
+ return raw === "read-only" || raw === "workspace-write" || raw === "danger-full-access";
16
+ }
13
17
  /**
14
18
  * `CODEX_APPROVAL_MODE` when it names an approval policy Codex implements,
15
19
  * else undefined. An invalid value is IGNORED (the preset mapping applies).
@@ -19,16 +23,44 @@ export function envApprovalMode() {
19
23
  return raw !== undefined && APPROVAL_POLICIES.includes(raw) ? raw : undefined;
20
24
  }
21
25
  /**
22
- * Map a preset onto Codex's `--approval-mode` value; no preset → never.
26
+ * Map a preset onto Codex's launch approval policy; no preset → never.
23
27
  * A value that is ALREADY a codex approval policy (the env override rides
24
28
  * through the same folded call) passes through untouched; unknown preset
25
29
  * names degrade to never.
30
+ *
31
+ * Still used at create/resume for `thread/start|resume.approvalPolicy` — the
32
+ * thread's initial posture before the first per-turn fold lands.
26
33
  */
27
34
  export function codexApprovalMode(preset) {
28
35
  if (preset !== undefined && APPROVAL_POLICIES.includes(preset))
29
36
  return preset;
30
37
  return isPresetName(preset) ? PRESETS[preset].codexPolicy : "never";
31
38
  }
39
+ /** The codex approval policy a Dash `approval/policy` value maps onto. */
40
+ export function approvalPolicyForDashPolicy(policy) {
41
+ return policy === "ask" ? "on-request" : "never";
42
+ }
43
+ /** The structured codex sandbox policy for one Dash sandbox mode. */
44
+ export function sandboxPolicyFor(mode, cwd) {
45
+ switch (mode) {
46
+ case "danger-full-access":
47
+ return { type: "dangerFullAccess" };
48
+ case "read-only":
49
+ return { type: "readOnly", networkAccess: false };
50
+ case "workspace-write":
51
+ return {
52
+ type: "workspaceWrite",
53
+ writableRoots: [cwd],
54
+ networkAccess: false,
55
+ excludeTmpdirEnvVar: false,
56
+ excludeSlashTmp: false,
57
+ };
58
+ }
59
+ }
60
+ /** The Dash sandbox mode a preset pins (unknown/absent → danger-full-access, matching the profile pin). */
61
+ export function sandboxModeForPreset(preset) {
62
+ return isPresetName(preset) ? PRESETS[preset].sandbox : "danger-full-access";
63
+ }
32
64
  /**
33
65
  * The default preset for FUTURE sessions, as the permission service
34
66
  * resolves it (settings-backed; the profile patch pins the base default).
@@ -56,6 +88,48 @@ export function presetFromEvents(events) {
56
88
  }
57
89
  return undefined;
58
90
  }
91
+ /** The session's effective sandbox mode: the last `sandbox/mode` event. */
92
+ export function sandboxModeFromEvents(events) {
93
+ for (let index = events.length - 1; index >= 0; index -= 1) {
94
+ const event = events[index];
95
+ if (event.type === "sandbox/mode" && isSandboxMode(event.data?.mode))
96
+ return event.data.mode;
97
+ }
98
+ return undefined;
99
+ }
100
+ /** The session's effective approval policy: the last `approval/policy` event. */
101
+ export function approvalPolicyFromEvents(events) {
102
+ for (let index = events.length - 1; index >= 0; index -= 1) {
103
+ const event = events[index];
104
+ if (event.type === "approval/policy") {
105
+ const policy = event.data?.policy;
106
+ if (policy === "ask" || policy === "never")
107
+ return approvalPolicyForDashPolicy(policy);
108
+ }
109
+ }
110
+ return undefined;
111
+ }
112
+ /**
113
+ * Fold the session's live permission state into the codex overrides for the
114
+ * NEXT `turn/start`. Never throws; every unknown value degrades to the
115
+ * fallback preset, and the env override wins for the approval half.
116
+ *
117
+ * @param events - the session log (or any suffix ending at the current state).
118
+ * @param fallbackPreset - the preset to use when the log carries no event
119
+ * (the recorded preset from the identity map, else the service default).
120
+ * @param cwd - the session workspace, used for `workspaceWrite.writableRoots`.
121
+ */
122
+ export function turnPolicyFromEvents(events, fallbackPreset, cwd) {
123
+ const preset = isPresetName(fallbackPreset) ? fallbackPreset : undefined;
124
+ const presetSpec = preset === undefined ? undefined : PRESETS[preset];
125
+ const sandboxMode = sandboxModeFromEvents(events) ?? presetSpec?.sandbox ?? "danger-full-access";
126
+ const fromEvents = approvalPolicyFromEvents(events);
127
+ const envMode = envApprovalMode();
128
+ const approvalPolicy = envMode === "never" || envMode === "on-request" || envMode === "untrusted"
129
+ ? envMode
130
+ : fromEvents ?? codexApprovalMode(preset);
131
+ return { approvalPolicy, sandbox: sandboxPolicyFor(sandboxMode, cwd) };
132
+ }
59
133
  /**
60
134
  * The three Dash events `pinInitialPermission` stamps for a fresh session,
61
135
  * in its append order (preset, sandbox, approval). Cold replay prepends
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@pgmi-builds/agent-codex",
3
3
  "version": "0.1.0",
4
- "description": "Codex provider for DeepSeek Harness (dsh) — an AgentFactory that embeds Codex CLI via the @openai/codex-sdk and bridges Codex's session surface into Dash Agent/Session contracts .",
4
+ "description": "Codex provider for DeepSeek Harness (dsh) — an AgentFactory that drives a `codex app-server` child process (stdio JSONL JSON-RPC) per session and bridges its thread/turn surface, approvals and permission policy into Dash Agent/Session contracts.",
5
5
  "type": "module",
6
6
  "exports": {
7
7
  ".": "./dist/index.js",
@@ -23,7 +23,6 @@
23
23
  },
24
24
  "dependencies": {
25
25
  "@openai/codex": "0.154.0",
26
- "@openai/codex-sdk": "0.154.0",
27
26
  "zod": "4.4.3"
28
27
  },
29
28
  "peerDependencies": {
@@ -0,0 +1,79 @@
1
+ # @pgmi-builds/agent-codex-sdk
2
+
3
+ superd 外壳下的 **Codex adapter**(super-dsh 线,AW-E):把 Codex CLI 经由
4
+ `@openai/codex-sdk` 接进 DSH —— 会话、事件、模型目录、持久化全部按 DSH 语义呈现,
5
+ WebUI 消费的是 DSH 服务提供的数据面。
6
+
7
+ > 通用规则(定位 / 两形态 / 测试准则 / 接线域 / per-agent 定制权 / home 与 profile 布局)
8
+ > 见上级目录的 `agent-adapter-dev-rules.md` —— 改本包前先读它。
9
+
10
+ ## 它是什么
11
+
12
+ - 一个**普通 dsh plugin bundle**:`package.json` 的 `dsh.bundle.patch` 指向本目录的
13
+ `cordis.patch.yml`(挂 codex provider、关掉它替代的原生行、重写权限三档表、pin 应用内目录选择器)。
14
+ - 一个 **AgentFactory**:`src/index.ts` 里的 `CodexProvider` 在 `ctx.agents` 注册工厂,
15
+ 每个会话一个 `CodexSdkClient`(真 `@openai/codex-sdk` 线程);`src/agent.ts` 把 Codex 线程事件
16
+ 投影成 DSH 会话事件。
17
+ - **带自己的 world 入口**:`src/world-plugin.ts`(`./world`,world key `codex-sdk`)把它作为
18
+ superd 世界挂载(`spawnWorld` + `worldMountPatches`),需要 hub 的 `@pgmi-builds/superd-hub`;
19
+ 同一份 adapter 代码也可作为普通 bundle 点亮一个完整 web app(两形态一条代码路径)。
20
+
21
+ ## 零声明依赖与运行时自取(2026-10-04 user 裁决)
22
+
23
+ 本包 **不声明任何运行时依赖** —— `@openai/codex-sdk` / `@openai/codex` / `zod` 既不在
24
+ `dependencies`、也不在 `optionalDependencies`、也不在 `peerDependencies`(`dependencies` 恒为
25
+ `{}`),安装期零下载、零 postinstall。SDK 树在**首个真 prompt** 时才被 fetch 进
26
+ `<worldHome>/sdk-runtime/`(`src/sdk-runtime.ts`):
27
+
28
+ - marker `<worldHome>/sdk-runtime.json`(**最后写**:写不到就不算成功)、锁 `.lock`(mkdir 原子,
29
+ 30 min 判陈旧可夺)、失败留 `.error.log`;
30
+ - marker 身份 = 本包版本 + 两个 pin,任一变化即重取;命中且 entry 存在则零网络短路;
31
+ - 装完立刻 smoke `import()` entry 并要求 `Codex` 构造器存在 —— 坏树在 fetch 时报错,不留到首 prompt;
32
+ - 预热(dev/运维):`npm run fetch-sdk-runtime [<home>]`(只接受仓内 `.tests` 下的 home)。
33
+
34
+ ## 跑起来
35
+
36
+ 本包默认 **disabled**(composite 行 `agent-codex-sdk`,打开该行即启用):行为级验证只走整包
37
+ pack 线(`super-dsh/test/start-4999.sh` + dev3 实装),不另起 per-agent 场景 rig(2026-09-24
38
+ 场景退役,见 `agent-adapter-dev-rules.md` §2)。`CODEX_TRACE=1` 开 provider/agent 追踪。
39
+ ## Home 与 profile 布局(user 裁定)
40
+
41
+ | 位置 | 内容 |
42
+ |---|---|
43
+ | `$DSH_HOME`(测试 = `<repo>/.tests`) | 测试 DSH home |
44
+ | `<DSH_HOME>/agents/codex-sdk` | 该世界的 **world DSH home**(`dsh-sessions.json` 映射等 adapter 态)+ **自取 SDK 运行时** `<worldHome>/sdk-runtime/`;codex app home 仍是原生 `~/.codex`(绝不重定向) |
45
+ | `$DSH_HOME/profiles/codex-sdk` | 该世界的 dsh profile(bundles + `cordis.patch.yml`) |
46
+ | `$DSH_HOME/sessions/...` | **DSH 会话日志**(上游 `session-persistence-jsonl`,zstd)——list/replay 都由此提供 |
47
+
48
+ **禁止**自造 per-app home(如 `.tests/codex-app`)。
49
+
50
+ ## 关键实现点
51
+
52
+ - **session 身份 = 一对一映射**:DSH session id 是权威;Codex thread id 在其物化后写入
53
+ `<worldHome>/dsh-sessions.json`(`src/session-map.ts`)。resume 只经该映射重挂线程,查不到即
54
+ fail-closed。**不自建 rollout 扫描做 list,也不自解析 JSONL 做 replay。**
55
+ - **DSH-native 持久化**:工厂按上游 agent-loop 的方式持有写通道(create `persistence.create` /
56
+ resume `persistence.open(id,'write')` → `read` → `interruptedTurnClosers` → `prepare`),
57
+ 发布点刷未存后缀,dispose 时 `handle.close()` 排空。
58
+ - **每会话路由钉住**:工厂在 create/resume 时同步钉住本会话路由(追加 `model/selection` +
59
+ `installModelSelection`),**不依赖全局默认模型的落盘时序**(共享 test home 里 settings 默认可能属别线)。
60
+ - **事件映射**:`system/message`(Codex 系统提示,rollout HEAD `base_instructions`)、
61
+ `request/context`(provider/model/contextWindow)、`assistant/message`(reasoning 用
62
+ `{type:'reasoning',text}`)、`tool/call`(原始 JSON 串)/`tool/result`、`step/start|end`、`turn/start|end`。
63
+
64
+ ## 测试
65
+
66
+ ```bash
67
+ npm run build # tsc strict
68
+ DSH_HOME=<repo>/.tests \
69
+ SUPERD_DSH_ANCHOR=<repo>/upstream/deepseek-harness/package.json \
70
+ node --test test/*.test.mjs
71
+ ```
72
+
73
+ ## 已知边界(V1)
74
+
75
+ - 审批仅 launch-only 预设(SDK 无运行时审批;app-server 线才有 `*/requestApproval`);
76
+ - 无 steer / 无运行时换模型(下一轮生效)/ usage 滞后一轮 / 无 fork;
77
+ - `compaction/*`、`todo/write`、`subagent/*` 未接(见规则文档 §9.4 backlog);
78
+ - **world 入口**:`src/world-plugin.ts`(world key `codex-sdk`)已接线 `spawnWorld`;roster 条目
79
+ fiber-scoped、行关闭时 dispose 世界(2026-10-03 omp-sdk 验收踩到的两条卸载契约)。
@@ -0,0 +1,81 @@
1
+ # @pgmi-builds/agent-codex-sdk bundle patch (SDK line, standalone form).
2
+ # This file is the `dsh.bundle.patch` layer of the adapter package: when the
3
+ # codex world profile mounts the bundle, the boot merges THIS patch — mount
4
+ # the Codex provider plus disable the native components it replaces.
5
+ #
6
+ # Profile-specific values are deliberately NOT here: `webserver.port` (port
7
+ # choice) belongs to the world/profile patch layer (the superd-codex-world
8
+ # fixture carries the 127.0.0.1:0 listener posture).
9
+
10
+ # Mount the Codex provider: a Cordis Service that registers an AgentFactory
11
+ # on ctx.agents. The provider drives @openai/codex-sdk threads (one
12
+ # CodexSdkClient per session) plus resume (--resume-thread); the model
13
+ # selector is served by a Codex-backed LlmAdapter reading the codex home's
14
+ # config.toml + model_catalog_json.
15
+ - insert:
16
+ - id: codex-sdk-provider
17
+ name: '@pgmi-builds/agent-codex-sdk'
18
+
19
+ # Codex owns the live agent transcript (the rollout JSONL); disable the
20
+ # built-in loop so it does not double-run alongside the SDK thread.
21
+ - id: agent-loop
22
+ disabled: true
23
+
24
+ # The native routes register deepseek-official / pi-ai providers; the Codex
25
+ # provider registers its own adapter (the single `codex` route) on ctx.llm.
26
+ # Leaving them mounted would advertise native models alongside Codex's.
27
+ - id: llm-deepseek
28
+ disabled: true
29
+ - id: llm-pi-ai
30
+ disabled: true
31
+
32
+ # Codex is single-mode: the SDK thread drives tools itself, so no Dash preset
33
+ # composition is needed (the provider ships the fixed single-preset roster).
34
+ # 0.1.7: the host AgentPresetRegistry row (renamed `agent-presets` ->
35
+ # `agent-preset-registry`) stays MOUNTED — the adapter registers its one
36
+ # fixed preset into it (src/agent-preset-codex.ts); pin only the default.
37
+ - id: agent-preset-registry
38
+ config:
39
+ default: codex
40
+
41
+ # The upstream jsonl persistence row STAYS MOUNTED (2026-09-16): the provider
42
+ # writes the DSH session log through it (create/open/append/close), so
43
+ # list/read/replay/workspace grouping are ordinary DSH services over that log.
44
+ # The adapter no longer provides its own persistence.
45
+
46
+ # Codex has no runtime approval control — the adapter maps the preset onto
47
+ # the launch-only --approval-mode flag (3:3 table in src/permission.ts).
48
+ # Default to danger-full-access. Restate the full 3-preset table: a patch
49
+ # with only defaultPreset silently drops the bundle's 3-preset table to the
50
+ # plugin's built-in 2, breaking the 3:3 Dash<->Codex pairing.
51
+ - id: permission
52
+ config:
53
+ presets:
54
+ read-only:
55
+ sandbox: read-only
56
+ approval: ask
57
+ workspace-write:
58
+ sandbox: workspace-write
59
+ approval: ask
60
+ danger-full-access:
61
+ sandbox: danger-full-access
62
+ approval: never
63
+ defaultPreset: danger-full-access
64
+
65
+ # Directory picker: the stock `directory-picker-auto` is never a simple alias —
66
+ # it RESOLVES the interaction once per boot and mounts BOTH faces through the
67
+ # loader: the host backend package AND the matching CLIENT SURFACE package
68
+ # (`dsh-client-ui-directory-picker-<kind>`). The client surface is what
69
+ # occupies the workspace picker's directory-flow hole; with the hole empty the
70
+ # client hides the "add workspace" entry entirely (WorkspacePicker: `flowAvailable
71
+ # ? [ADD_WORKSPACE] : []`). NEVER just `disabled: true` this row — that removed
72
+ # the button. Pin the in-app browser by mounting both faces of `browse`
73
+ # ourselves (backend first: the surface's browser half drives the capability the
74
+ # backend registers) and unmounting the auto row.
75
+ - insert:
76
+ - id: directory-picker-browse
77
+ name: '@deepseek-ai/dsh-host-directory-picker-browse'
78
+ - id: directory-picker-browse-surface
79
+ name: '@deepseek-ai/dsh-client-ui-directory-picker-browse'
80
+ - id: directory-picker
81
+ disabled: true
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Codex-backed `LlmAdapter` registered on `ctx.llm` by the Codex provider.
3
+ *
4
+ * The browser model selector never touches the Codex agent directly: it is an
5
+ * RPC round-trip through the apiproxy, which reads `ctx.llm.listProviders /
6
+ * listModels / resolveModelInfo` to build the catalog. This adapter answers
7
+ * those queries from the ADAPTER's canonical provider store
8
+ * (`codex-providers.ts`), registering ONE ROUTE PER CONFIGURED PROVIDER.
9
+ *
10
+ * That one-route-per-provider shape is the 2026-10-04 rework, and it is what
11
+ * makes the whole feature DSH-native: the harness's own model selector already
12
+ * renders a provider-grouped catalog, already keeps the choice per session
13
+ * (`session/selectModel` → the durable `model/selection` event + the
14
+ * `modelSelection` projection), and already reports which route a session last
15
+ * used. Registering the Codex providers as real routes means Super D gets all
16
+ * of that by construction instead of re-implementing it — there is no "active
17
+ * provider" left for the UI to hold.
18
+ *
19
+ * `stream` is never dispatched: Codex owns generation through its app-server
20
+ * thread (`CodexAgent`), so the adapter only serves catalog/metadata queries.
21
+ * It throws rather than fabricating a wire route the harness would misuse.
22
+ *
23
+ * @module agent-codex/adapter
24
+ */
25
+ import { LlmAdapter, LlmError, } from "@deepseek-ai/dsh-llm";
26
+ import { readProviderStore } from "./codex-providers.js";
27
+ /**
28
+ * The single route every Codex model was served under before the multi-provider
29
+ * rework. No longer registered (a session pinned to it falls back to whatever
30
+ * the native `config.toml` runs), but kept as the one named constant so the
31
+ * legacy value is greppable in session logs.
32
+ */
33
+ export const CODEX_PROVIDER_ID = "codex";
34
+ /** Whether a provider may be registered as a model route. */
35
+ export function routableProvider(entry) {
36
+ return entry.models.length > 0;
37
+ }
38
+ /** The route ids a store currently contributes to `ctx.llm`. */
39
+ export function routeIds(store) {
40
+ return store.providers.filter(routableProvider).map((entry) => entry.id);
41
+ }
42
+ /** The provider entry a route id names, or `undefined`. */
43
+ export function providerFor(worldHome, providerId) {
44
+ return readProviderStore(worldHome).providers.find((entry) => entry.id === providerId);
45
+ }
46
+ export class CodexLlmAdapter extends LlmAdapter {
47
+ worldHome;
48
+ /**
49
+ * @param worldHome - the world's DSH home, holding the canonical provider
50
+ * store in `<worldHome>/codex-providers.json`. Read on every call, so a
51
+ * panel edit is visible to the next catalog query without re-registration.
52
+ */
53
+ constructor(worldHome) {
54
+ super();
55
+ this.worldHome = worldHome;
56
+ }
57
+ providerInfo(provider) {
58
+ // The display name is the entry's label — for a provider folded in from the
59
+ // user's own config that is its endpoint URL, which is the only name a
60
+ // hand-written codex config supplies.
61
+ return { id: provider, name: providerFor(this.worldHome, provider)?.label ?? provider };
62
+ }
63
+ async listModels(provider) {
64
+ const entry = providerFor(this.worldHome, provider);
65
+ if (entry === undefined)
66
+ return [];
67
+ return entry.models.map((model) => ({
68
+ provider,
69
+ id: model.id,
70
+ name: model.displayName ?? model.id,
71
+ }));
72
+ }
73
+ async resolveModel(provider, model, _signal) {
74
+ const entry = providerFor(this.worldHome, provider);
75
+ const found = entry?.models.find((candidate) => candidate.id === model);
76
+ if (found === undefined) {
77
+ throw new LlmError(`Codex provider "${provider}" does not serve model "${model}"`, "MODEL_NOT_FOUND");
78
+ }
79
+ return {
80
+ provider,
81
+ id: found.id,
82
+ name: found.displayName ?? found.id,
83
+ ...(found.contextWindow !== undefined && found.contextWindow > 0
84
+ ? { context: { contextWindow: found.contextWindow } }
85
+ : {}),
86
+ };
87
+ }
88
+ stream(_options) {
89
+ throw new LlmError("the Codex adapter does not stream: Codex owns generation through its app-server thread", "UNSUPPORTED_STREAM");
90
+ }
91
+ }
@@ -0,0 +1,32 @@
1
+ export const CODEX_PRESET_ID = "codex";
2
+ /** The single fixed Codex preset: mounting it composes nothing. */
3
+ export const CODEX_PRESET = Object.freeze({
4
+ id: CODEX_PRESET_ID,
5
+ name: "Codex",
6
+ description: "Codex agent via the agent-codex adapter",
7
+ plugins: Object.freeze([]),
8
+ });
9
+ /**
10
+ * Register the fixed preset into the host `AgentPresetRegistry` once the
11
+ * service is up. Registration failure keeps the roster row visible as
12
+ * `broken` inside the registry (upstream owns that lifecycle) — the adapter
13
+ * only owns the disposer.
14
+ */
15
+ export function registerCodexPreset(ctx) {
16
+ ctx.inject(["agentPresets"], (scoped) => {
17
+ let dispose;
18
+ let settled = false;
19
+ void scoped.agentPresets.register(CODEX_PRESET).then((unregister) => {
20
+ if (settled) {
21
+ void unregister();
22
+ }
23
+ else {
24
+ dispose = unregister;
25
+ }
26
+ });
27
+ ctx.effect(() => async () => {
28
+ settled = true;
29
+ await dispose?.();
30
+ }, "codexAdapter.preset");
31
+ });
32
+ }