@platless/axom-cli 0.3.13 → 0.6.36

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 (320) hide show
  1. package/README.md +18 -5
  2. package/dist/axom-patch/cli/README.md +119 -9
  3. package/dist/axom-patch/cli/account-limits/README.md +27 -0
  4. package/dist/axom-patch/cli/account-limits/antigravity-proxy.mjs +47 -0
  5. package/dist/axom-patch/cli/account-limits/antigravity-read.mjs +90 -0
  6. package/dist/axom-patch/cli/account-limits/antigravity.mjs +46 -0
  7. package/dist/axom-patch/cli/account-limits/generate.py +123 -0
  8. package/dist/axom-patch/cli/account-limits/kimi-proxy.mjs +81 -0
  9. package/dist/axom-patch/cli/account-limits/normalize.mjs +151 -0
  10. package/dist/axom-patch/cli/claude-account-limits.json +37 -0
  11. package/dist/axom-patch/cli/codex-account-limits.json +37 -0
  12. package/dist/axom-patch/cli/codex-terminal-output.json +16 -0
  13. package/dist/axom-patch/cli/commandcode-account-limits.json +30 -0
  14. package/dist/axom-patch/cli/kimi-quota.mjs +12 -0
  15. package/dist/axom-patch/cli/kimi-subagents.mjs +173 -0
  16. package/dist/axom-patch/cli/nightly-task.md +194 -0
  17. package/dist/axom-patch/cli/pi-subagent-subwork.json +23 -0
  18. package/dist/axom-patch/cli/probes/claude-late-async-terminal.mjs +5 -1
  19. package/dist/axom-patch/cli/probes/codex-terminal-output.mjs +33 -0
  20. package/dist/axom-patch/cli/probes/kimi-subagent-subwork.mjs +82 -0
  21. package/dist/axom-patch/cli/probes/pi-subagent-subwork.mjs +211 -0
  22. package/dist/axom-patch/cli/probes/zcode-subagent-subwork.mjs +257 -0
  23. package/dist/axom-patch/cli/qoder/dist/axom-acp-compat.mjs +1591 -0
  24. package/dist/axom-patch/cli/qoder/releases/1.1.75.json +360 -0
  25. package/dist/axom-patch/cli/qoder-background-terminal.md +13 -5
  26. package/dist/axom-patch/cli/qoder-foreground-output.md +14 -7
  27. package/dist/axom-patch/cli/qoder-native-acp.json +227 -0
  28. package/dist/axom-patch/cli/qoder-steering.md +20 -25
  29. package/dist/axom-patch/cli/qoder-subagent-subwork.md +17 -68
  30. package/dist/axom-patch/cli/runtime.json +39 -15
  31. package/dist/axom-patch/cli/zcode-account-limits.json +30 -0
  32. package/dist/axom-patch/cli/zcode-models.json +37 -0
  33. package/dist/axom-patch/cli/zcode-subagent-subwork.json +72 -0
  34. package/dist/cli.js +4 -9
  35. package/dist/commands/knowledge.js +47 -0
  36. package/dist/commands/update.js +65 -3
  37. package/dist/commands/workstation.js +73 -7
  38. package/dist/install/claude/commands.js +13 -13
  39. package/dist/keepers/acp/keeper.mjs +3083 -0
  40. package/dist/keepers/acp/manifest.json +9 -0
  41. package/dist/keepers/terminal/keeper.mjs +8469 -0
  42. package/dist/keepers/terminal/manifest.json +9 -0
  43. package/dist/keepers/terminal/node_modules/node-pty/lib/conpty_console_list_agent.js +25 -0
  44. package/dist/keepers/terminal/node_modules/node-pty/lib/eventEmitter2.js +47 -0
  45. package/dist/keepers/terminal/node_modules/node-pty/lib/index.js +52 -0
  46. package/dist/keepers/terminal/node_modules/node-pty/lib/interfaces.js +7 -0
  47. package/dist/keepers/terminal/node_modules/node-pty/lib/shared/conout.js +10 -0
  48. package/dist/keepers/terminal/node_modules/node-pty/lib/terminal.js +190 -0
  49. package/dist/keepers/terminal/node_modules/node-pty/lib/types.js +7 -0
  50. package/dist/keepers/terminal/node_modules/node-pty/lib/unixTerminal.js +351 -0
  51. package/dist/keepers/terminal/node_modules/node-pty/lib/utils.js +38 -0
  52. package/dist/keepers/terminal/node_modules/node-pty/lib/windowsConoutConnection.js +131 -0
  53. package/dist/keepers/terminal/node_modules/node-pty/lib/windowsPtyAgent.js +344 -0
  54. package/dist/keepers/terminal/node_modules/node-pty/lib/windowsTerminal.js +209 -0
  55. package/dist/keepers/terminal/node_modules/node-pty/lib/worker/conoutSocketWorker.js +22 -0
  56. package/dist/keepers/terminal/node_modules/node-pty/package.json +66 -0
  57. package/dist/keepers/terminal/node_modules/node-pty/prebuilds/darwin-arm64/pty.node +0 -0
  58. package/dist/keepers/terminal/node_modules/node-pty/prebuilds/darwin-arm64/spawn-helper +0 -0
  59. package/dist/keepers/terminal/node_modules/node-pty/prebuilds/darwin-x64/pty.node +0 -0
  60. package/dist/keepers/terminal/node_modules/node-pty/prebuilds/darwin-x64/spawn-helper +0 -0
  61. package/dist/keepers/terminal/node_modules/node-pty/prebuilds/linux-arm64/pty.node +0 -0
  62. package/dist/keepers/terminal/node_modules/node-pty/prebuilds/linux-x64/pty.node +0 -0
  63. package/dist/mcp.js +1 -1
  64. package/dist/native/darwin-arm64/axom-quic +0 -0
  65. package/dist/test/keeperKit.js +67 -0
  66. package/dist/workstation/acp/acpAgents.js +2192 -636
  67. package/dist/workstation/acp/acpClient.js +84 -495
  68. package/dist/workstation/acp/adoption.js +10 -396
  69. package/dist/workstation/acp/binaryInstall.js +100 -27
  70. package/dist/workstation/acp/builds/gc.js +245 -0
  71. package/dist/workstation/acp/builds/install/binary.js +28 -0
  72. package/dist/workstation/acp/builds/install/npm.js +324 -0
  73. package/dist/workstation/acp/builds/install/uv.js +254 -0
  74. package/dist/workstation/acp/builds/migrate.js +195 -0
  75. package/dist/workstation/acp/builds/model.js +128 -0
  76. package/dist/workstation/acp/builds/nodeGate.js +100 -0
  77. package/dist/workstation/acp/builds/store.js +352 -0
  78. package/dist/workstation/acp/commandTableProbe.js +68 -0
  79. package/dist/workstation/acp/configOptions.js +103 -1
  80. package/dist/workstation/acp/envSecrets.js +27 -0
  81. package/dist/workstation/acp/initializeResponse.js +290 -0
  82. package/dist/workstation/acp/installErrors.js +12 -2
  83. package/dist/workstation/acp/installProbe.js +1 -1
  84. package/dist/workstation/acp/managedPatches.js +239 -159
  85. package/dist/workstation/acp/managedRuntime.js +314 -0
  86. package/dist/workstation/acp/outbox.js +330 -0
  87. package/dist/workstation/acp/patchAssets.js +60 -3
  88. package/dist/workstation/acp/permission.js +42 -10
  89. package/dist/workstation/acp/processor/checkpoint.js +78 -0
  90. package/dist/workstation/acp/processor/commands.js +35 -0
  91. package/dist/workstation/acp/processor/control.js +282 -0
  92. package/dist/workstation/acp/processor/emit.js +26 -0
  93. package/dist/workstation/acp/processor/jsonrpc.js +172 -0
  94. package/dist/workstation/acp/processor/memoryLog.js +49 -0
  95. package/dist/workstation/acp/processor/origins.js +48 -0
  96. package/dist/workstation/acp/processor/output.js +67 -0
  97. package/dist/workstation/acp/processor/projection.js +42 -0
  98. package/dist/workstation/acp/processor/record.js +128 -0
  99. package/dist/workstation/acp/processor/runtime.js +105 -0
  100. package/dist/workstation/acp/processor/sdkSchemas.js +61 -0
  101. package/dist/workstation/acp/processor/session.js +496 -0
  102. package/dist/workstation/acp/processor/state.js +67 -0
  103. package/dist/workstation/acp/processor/step.js +442 -0
  104. package/dist/workstation/acp/processor/test/fixtureLog.js +58 -0
  105. package/dist/workstation/acp/processor/test/harness.js +120 -0
  106. package/dist/workstation/acp/processor/test/largeIdEcho.js +50 -0
  107. package/dist/workstation/acp/processor/test/rawAgent.js +70 -0
  108. package/dist/workstation/acp/processor/transport/generations.js +76 -0
  109. package/dist/workstation/acp/processor/transport/keeper.js +130 -0
  110. package/dist/workstation/acp/processor/transport/local.js +269 -0
  111. package/dist/workstation/acp/processor/transport/types.js +78 -0
  112. package/dist/workstation/acp/processor/updates.js +390 -0
  113. package/dist/workstation/acp/processorSession.js +1348 -0
  114. package/dist/workstation/acp/registry/catalog.js +189 -41
  115. package/dist/workstation/acp/registry/launch.js +76 -119
  116. package/dist/workstation/acp/sessionUpdateMapper.js +18 -7
  117. package/dist/workstation/acp/steering.js +58 -0
  118. package/dist/workstation/acp/switching.js +111 -0
  119. package/dist/workstation/acp/terminalLogin.js +16 -42
  120. package/dist/workstation/acp/terminalLoginSpec.js +41 -0
  121. package/dist/workstation/acp/test/adapterFixtures.js +256 -0
  122. package/dist/workstation/acp/test/daemonLife.js +106 -0
  123. package/dist/workstation/acp/test/fakeAgent.js +13 -0
  124. package/dist/workstation/acp/test/keeperWorld.js +295 -0
  125. package/dist/workstation/acp/test/memoryOutbox.js +55 -0
  126. package/dist/workstation/acp/test/raw/fixtures.js +196 -0
  127. package/dist/workstation/acp/test/raw/sanitize.js +344 -0
  128. package/dist/workstation/acp/test/raw/sources.js +135 -0
  129. package/dist/workstation/acp/test/realAdapter.js +331 -0
  130. package/dist/workstation/acp/test/scriptAgent.js +214 -0
  131. package/dist/workstation/acp/test/sessionFrames.js +42 -0
  132. package/dist/workstation/acp/timedCommand.js +4 -2
  133. package/dist/workstation/acp/uvxInstall.js +72 -122
  134. package/dist/workstation/agentFlow.js +103 -0
  135. package/dist/workstation/agentSessions.js +1289 -544
  136. package/dist/workstation/channels/agent.js +7 -5
  137. package/dist/workstation/channels/computer.js +69 -21
  138. package/dist/workstation/channels/computerExecs.js +200 -0
  139. package/dist/workstation/channels/management.js +172 -8
  140. package/dist/workstation/channels/url.js +1 -1
  141. package/dist/workstation/config.js +16 -4
  142. package/dist/workstation/connection/encryptedChannel.js +4 -1
  143. package/dist/workstation/control/bindingStore.js +200 -0
  144. package/dist/workstation/control/commands.js +124 -0
  145. package/dist/workstation/control/daemonIdentity.js +53 -0
  146. package/dist/workstation/control/enrollment.js +106 -0
  147. package/dist/workstation/control/inspect.js +71 -0
  148. package/dist/workstation/control/locks.js +63 -0
  149. package/dist/workstation/control/protocol.js +40 -0
  150. package/dist/workstation/control/restartGuard.js +46 -0
  151. package/dist/workstation/control/runtimeClient.js +97 -0
  152. package/dist/workstation/control/runtimeHost.js +148 -0
  153. package/dist/workstation/control/serverIdentity.js +35 -0
  154. package/dist/workstation/daemon.js +393 -12
  155. package/dist/workstation/daemonctl.js +103 -14
  156. package/dist/workstation/desktopControl/audio.js +99 -0
  157. package/dist/workstation/desktopControl/capabilities.js +92 -0
  158. package/dist/workstation/desktopControl/captureModes.js +9 -0
  159. package/dist/workstation/desktopControl/captureTargetLabel.js +9 -0
  160. package/dist/workstation/desktopControl/deviceSockets.js +246 -0
  161. package/dist/workstation/desktopControl/helperProcess.js +353 -0
  162. package/dist/workstation/desktopControl/lobby.js +129 -0
  163. package/dist/workstation/desktopControl/macProvider.js +155 -0
  164. package/dist/workstation/desktopControl/media.js +331 -0
  165. package/dist/workstation/desktopControl/nativeProvider.js +1018 -0
  166. package/dist/workstation/desktopControl/networkEvidence.js +43 -0
  167. package/dist/workstation/desktopControl/overview.js +58 -0
  168. package/dist/workstation/desktopControl/protocol.js +302 -0
  169. package/dist/workstation/desktopControl/quicMedia.js +240 -0
  170. package/dist/workstation/desktopControl/rateController.js +226 -0
  171. package/dist/workstation/desktopControl/supervisor.js +1681 -0
  172. package/dist/workstation/desktopControl/transport.js +27 -0
  173. package/dist/workstation/desktopControl/wallpaper.js +78 -0
  174. package/dist/workstation/exec/attach.js +126 -0
  175. package/dist/workstation/exec/command.js +40 -0
  176. package/dist/workstation/exec/durable.js +517 -0
  177. package/dist/workstation/exec/fallback.js +106 -0
  178. package/dist/workstation/exec/policy.js +837 -0
  179. package/dist/workstation/exec/shaping.js +211 -0
  180. package/dist/workstation/exec.js +3 -112
  181. package/dist/workstation/files/adapters/computerFileFrames.js +51 -0
  182. package/dist/workstation/files/adapters/toolRequests.js +121 -0
  183. package/dist/workstation/files/client.js +455 -0
  184. package/dist/workstation/files/credentials.js +142 -0
  185. package/dist/workstation/files/errors.js +28 -0
  186. package/dist/workstation/files/fence.js +350 -0
  187. package/dist/workstation/files/find/fileIndex.js +153 -0
  188. package/dist/workstation/files/find/fuzzy.js +155 -0
  189. package/dist/workstation/files/host.js +122 -0
  190. package/dist/workstation/files/hostProtocol.js +2 -0
  191. package/dist/workstation/files/media/cache.js +620 -0
  192. package/dist/workstation/files/media/encoding.js +308 -0
  193. package/dist/workstation/files/media/estimator.js +100 -0
  194. package/dist/workstation/files/media/media.js +325 -0
  195. package/dist/workstation/files/media/packedAudio.js +23 -0
  196. package/dist/workstation/files/media/scheduler.js +551 -0
  197. package/dist/workstation/files/media/types.js +5 -0
  198. package/dist/workstation/files/scope.js +45 -0
  199. package/dist/workstation/files/structured.js +284 -0
  200. package/dist/workstation/{fileOps.js → files/text.js} +152 -39
  201. package/dist/workstation/files/uploads.js +351 -0
  202. package/dist/workstation/journal.js +65 -236
  203. package/dist/workstation/keepers/acp/client.js +101 -0
  204. package/dist/workstation/keepers/acp/envelope.js +62 -0
  205. package/dist/workstation/keepers/acp/host.js +419 -0
  206. package/dist/workstation/keepers/acp/main.js +18 -0
  207. package/dist/workstation/keepers/acp/memoryStream.js +121 -0
  208. package/dist/workstation/keepers/acp/params.js +137 -0
  209. package/dist/workstation/keepers/acp/protocol.js +66 -0
  210. package/dist/workstation/keepers/acp/recover.js +120 -0
  211. package/dist/workstation/keepers/acp/session.js +584 -0
  212. package/dist/workstation/keepers/acp/stderr.js +154 -0
  213. package/dist/workstation/keepers/kit/activity.js +103 -0
  214. package/dist/workstation/keepers/kit/bootstrap.js +164 -0
  215. package/dist/workstation/keepers/kit/buildVersion.js +51 -0
  216. package/dist/workstation/keepers/kit/bundle.js +124 -0
  217. package/dist/workstation/keepers/kit/client.js +432 -0
  218. package/dist/workstation/keepers/kit/identity.js +21 -0
  219. package/dist/workstation/keepers/kit/ipc.js +112 -0
  220. package/dist/workstation/keepers/kit/launchConfig.js +8 -0
  221. package/dist/workstation/keepers/kit/launcher.js +289 -0
  222. package/dist/workstation/keepers/kit/lock.js +123 -0
  223. package/dist/workstation/keepers/kit/orphanSweep.js +86 -0
  224. package/dist/workstation/keepers/kit/paths.js +76 -0
  225. package/dist/workstation/keepers/kit/protocol.js +43 -0
  226. package/dist/workstation/keepers/kit/server.js +518 -0
  227. package/dist/workstation/keepers/kit/streamLog.js +697 -0
  228. package/dist/workstation/keepers/legacy.js +296 -0
  229. package/dist/workstation/keepers/policy.js +576 -0
  230. package/dist/workstation/keepers/stop.js +34 -0
  231. package/dist/workstation/keepers/terminal/client.js +213 -0
  232. package/dist/workstation/keepers/terminal/exec.js +981 -0
  233. package/dist/workstation/keepers/terminal/generations.js +129 -0
  234. package/dist/workstation/keepers/terminal/keeper.js +62 -0
  235. package/dist/workstation/keepers/terminal/main.js +43 -0
  236. package/dist/workstation/keepers/terminal/orphanSweep.js +3 -0
  237. package/dist/workstation/keepers/terminal/params.js +27 -0
  238. package/dist/workstation/keepers/terminal/protocol.js +56 -0
  239. package/dist/workstation/keepers/terminal/pty.js +330 -0
  240. package/dist/workstation/managedInstall.js +57 -0
  241. package/dist/workstation/protocol/accountLimits.js +47 -0
  242. package/dist/workstation/protocol/agent.js +50 -19
  243. package/dist/workstation/protocol/common.js +30 -0
  244. package/dist/workstation/protocol/computer.js +15 -4
  245. package/dist/workstation/protocol/management.js +141 -4
  246. package/dist/workstation/protocol/runtimeDiagnostics.js +15 -0
  247. package/dist/workstation/rd/artifact.js +119 -0
  248. package/dist/workstation/rd/control.js +119 -0
  249. package/dist/workstation/rd/display.js +29 -0
  250. package/dist/workstation/rd/provider.js +222 -0
  251. package/dist/workstation/rd/sessions.js +391 -0
  252. package/dist/workstation/rd/state.js +45 -0
  253. package/dist/workstation/rd/update.js +171 -0
  254. package/dist/workstation/rd/upkeep.js +38 -0
  255. package/dist/workstation/register.js +27 -37
  256. package/dist/workstation/service/installer.js +104 -13
  257. package/dist/workstation/service/launchd.js +1 -0
  258. package/dist/workstation/storageMetrics.js +118 -0
  259. package/dist/workstation/systemMetrics.js +154 -93
  260. package/dist/workstation/toolchain.js +94 -0
  261. package/dist/workstation/tools/browser.js +28 -4
  262. package/dist/workstation/tools/client.js +9 -1
  263. package/dist/workstation/tools/info.js +50 -0
  264. package/dist/workstation/tools/keeperProcess.js +15 -5
  265. package/dist/workstation/tools/router.js +55 -0
  266. package/dist/workstation/tools/terminalRouter.js +222 -0
  267. package/dist/workstation/tools/validation.js +37 -1
  268. package/dist/workstation/update/artifact.js +2 -1
  269. package/dist/workstation/update/coordinator.js +3 -0
  270. package/dist/workstation/update/globalInstall.js +116 -0
  271. package/dist/workstation/update/npmInstaller.js +49 -23
  272. package/dist/workstation/update/ptyPreflight.js +21 -0
  273. package/dist/workstation/update/rdRollback.js +145 -0
  274. package/dist/workstation/update/runUpdate.js +3 -2
  275. package/dist/workstation/update/taskRegistry.js +105 -11
  276. package/dist/workstation/update/watchdog.js +16790 -334
  277. package/package.json +11 -8
  278. package/skills/axom/SKILL.md +11 -11
  279. package/skills/axom-definition/SKILL.md +3 -3
  280. package/skills/axom-platform/SKILL.md +3 -3
  281. package/dist/axom-patch/cli/probes/qoder-steering.mjs +0 -89
  282. package/dist/axom-patch/cli/probes/qoder-subagent-origin.mjs +0 -49
  283. package/dist/axom-patch/cli/qoder-steering.json +0 -52
  284. package/dist/axom-patch/cli/qoder-subagent-origin.json +0 -73
  285. package/dist/commands/guide.js +0 -38
  286. package/dist/workstation/acp/acpSession.js +0 -1475
  287. package/dist/workstation/acp/contract.js +0 -499
  288. package/dist/workstation/acp/delegationMcp.js +0 -24
  289. package/dist/workstation/acp/draftInterceptor.js +0 -163
  290. package/dist/workstation/acp/qoderStartup.js +0 -45
  291. package/dist/workstation/acp/sessionScope.js +0 -19
  292. package/dist/workstation/filePaths.js +0 -174
  293. package/dist/workstation/fileWorker.js +0 -81
  294. package/dist/workstation/fileWorkerClient.js +0 -121
  295. package/dist/workstation/qoderAdapter/backgroundProcess.js +0 -106
  296. package/dist/workstation/qoderAdapter/backgroundTerminal.js +0 -262
  297. package/dist/workstation/qoderAdapter/completedContinuation.js +0 -139
  298. package/dist/workstation/qoderAdapter/contract.js +0 -78
  299. package/dist/workstation/qoderAdapter/foregroundOutput.js +0 -30
  300. package/dist/workstation/qoderAdapter/history.js +0 -87
  301. package/dist/workstation/qoderAdapter/identityIndex.js +0 -191
  302. package/dist/workstation/qoderAdapter/inputQueue.js +0 -42
  303. package/dist/workstation/qoderAdapter/main.js +0 -93
  304. package/dist/workstation/qoderAdapter/mapper.js +0 -117
  305. package/dist/workstation/qoderAdapter/observerPlugin.js +0 -245
  306. package/dist/workstation/qoderAdapter/observerReceiver.js +0 -187
  307. package/dist/workstation/qoderAdapter/permissions.js +0 -61
  308. package/dist/workstation/qoderAdapter/profile.js +0 -93
  309. package/dist/workstation/qoderAdapter/sdkDriver.js +0 -49
  310. package/dist/workstation/qoderAdapter/session.js +0 -319
  311. package/dist/workstation/qoderAdapter/subagentMeta.js +0 -28
  312. package/dist/workstation/qoderAdapter/subwork.js +0 -77
  313. package/dist/workstation/qoderAdapter/taskControl.js +0 -38
  314. package/dist/workstation/qoderAdapter/taskEvent.js +0 -26
  315. package/dist/workstation/qoderAdapter/taskLedger.js +0 -163
  316. package/dist/workstation/qoderAdapter/usage.js +0 -37
  317. package/dist/workstation/tools/core.js +0 -50
  318. package/dist/workstation/tools/files.js +0 -525
  319. package/dist/workstation/tools/terminal.js +0 -214
  320. /package/dist/workstation/{qoderAdapter/types.js → desktopControl/provider.js} +0 -0
@@ -6,7 +6,7 @@
6
6
  * 一个 agent 在本清单里,就是我们真机验证过(roster 的 `curated`),设置页把它放进展开区;其余官方
7
7
  * 条目进折叠的 "Unverified Agents"。本清单能做的事,各有一节在下面:
8
8
  *
9
- * - **推荐**:`recommended` 是静态的,只给愿意向任何一台新机器推荐的(claude、codex、pi)。
9
+ * - **推荐**:`recommended` 是静态的,只给愿意向任何一台新机器推荐的(pi)。
10
10
  * - **本地检测**(`detect`,见 `detect.ts`):PATH 上的命令或固定文件位置,只看文件在不在、不起进程。
11
11
  * 检测到 = 这台机器的用户自己在用它,于是它也进推荐位,原因写"本机在用"。
12
12
  * - **前置依赖**(`prerequisite`):适配器之外、它起得来所必需的本体(Pi 的 CLI、ZCode 桌面应用),
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * ## 托管与检测是两件事
17
17
  *
18
- * Axom 启动的**一律是 Axom 托管的那份**——npx 缓存、`uv tool dir`、`<config dir>/acp-adapters` 里我们
18
+ * Axom 启动的**一律是 Axom 托管的那份**——`<config dir>/acp-adapters` 里我们(npm、uv、binary 各按版本)
19
19
  * 自己装的、钉了版本的副本,与用户自己的安装隔离、独立升级。`adapterInstalled` 只回答这一份在不在。
20
20
  * 用户 PATH 上的 `kimi`、`command-code` **不算** Axom 已安装,也从不被拿来启动:它只是 `detect` 的
21
21
  * 推荐信号。两份共用数据目录(`~/.kimi-code`、`~/.commandcode`),所以登录是共享的。
@@ -44,10 +44,10 @@
44
44
  *
45
45
  * 这里写下的来源**整个替换** registry 的 `version` 与 `distribution`,id 与展示名仍是 registry 的,
46
46
  * 于是已有的配置条目、roster、安装、启动、更新都不用知道发生过替换(见 {@link withCatalogOverrides})。
47
- * 本文件里的是长期的(Qoder:registry 落后于验证过的原生版本);临时的钉版本放在
47
+ * 本文件的 distribution 用于长期策略;临时的版本覆盖才放在
48
48
  * axom-patch/cli/runtime.json,按 registry 版本挑选(`when_registry_version` / `until_registry_version`,
49
49
  * 见 `patchAssets.ts`),registry 一到就自己让位。两者与上面的 `install` 是同一条安全边界:只能是
50
- * 随 CLI 发布、钉死版本、由真机验证过的可信配置。
50
+ * 随 CLI 发布、钉死版本、由补丁哈希和回归验证过的可信配置。
51
51
  *
52
52
  * ## `supplement` 与 `supersedes`:registry 缺的条目、registry 不肯撤的条目
53
53
  *
@@ -85,19 +85,49 @@ export const AXOM_AGENT_CATALOG = [
85
85
  registryAgent: 'claude-acp',
86
86
  defaultName: 'claude-agent',
87
87
  defaultLabel: 'Claude Agent',
88
- recommended: true,
89
88
  detect: { commands: ['claude'] },
89
+ // 钉版本的唯一理由是补丁:claude-account-limits 的配方只核验过 0.97.0(runtime.json 的
90
+ // package_patches)。不钉的话 registry 一发新版,Install/Update 就装上一个配方不覆盖的包,
91
+ // 账号配额扩展静默消失——2026-10-14 的 antigravity(registry 已到 1.4.0、native extension
92
+ // 只认 1.3.0)就是这个缺口的实例。钉住后 scan 的 Update 比对(installedVersion vs 本清单的
93
+ // version)只在落后于钉住版本时才成立,上游新版要等 nightly 核验移植配方后再 bump。
94
+ // 周期核验步骤见 axom-patch/DAILY_UPGRADE_CHECK.md。
95
+ distribution: { version: '0.97.0', npx: { package: '@agentclientprotocol/claude-agent-acp@0.97.0' } },
96
+ launchEnv: {
97
+ // Axom 拉起的 Claude Code——会话进程、配额读的 /usage、auth status 探针、terminalLogin 代跑的
98
+ // `--cli auth login`——一律使用独立的 OAuth 凭据槽,与用户终端 `claude login` 写进默认槽
99
+ // (macOS keychain `Claude Code-credentials`)的那份互不轮换。Claude 的 refresh token 单次
100
+ // 轮换,多进程共享一份凭据时并发刷新会互相作废、进而被 Claude Code 清除(全员登出;
101
+ // anthropics/claude-code#54443,2026-10 本机实测每日复现)。
102
+ //
103
+ // CLAUDE_SECURESTORAGE_CONFIG_DIR 只改槽位命名,不把存储切到目录:macOS 上 keychain 条目变为
104
+ // `Claude Code-credentials-<sha256(路径)前8位>`,明文回退文件在 <路径>/.credentials.json(仅当
105
+ // keychain 写入失败时才落)。前导 `~` 由 `registry/launch.ts` 在 launch env 边界展开为绝对路径——
106
+ // Claude 把这个值按字面路径使用,不展开 `~`。
107
+ //
108
+ // **共享/独立凭据的开关收敛在这一个键上**:删除它(或将来的用户开关通过 workstation 配置的
109
+ // 同名变量覆盖)即回到与终端 CLI 共享默认槽的旧行为,判定点只此一处。路径一旦发布永不改名——
110
+ // 换字符串等于强制所有人重新登录。
111
+ CLAUDE_SECURESTORAGE_CONFIG_DIR: '~/.axom/auth/secures/claude',
112
+ },
113
+ },
114
+ {
115
+ registryAgent: 'codex-acp',
116
+ defaultName: 'codex',
117
+ defaultLabel: 'Codex',
118
+ detect: { commands: ['codex'] },
119
+ // 与 claude-acp 同一条规则:codex-account-limits 只核验过 2.3.0(2026-10-27 nightly;2.3.0 的
120
+ // authStatus 锚点在两处 capabilities 里重复,已加长到 initialize 独有后缀消歧),钉住直到配方随新版本移植。
121
+ distribution: { version: '2.3.0', npx: { package: '@agentclientprotocol/codex-acp@2.3.0' } },
90
122
  },
91
- { registryAgent: 'codex-acp', defaultName: 'codex', defaultLabel: 'Codex', recommended: true, detect: { commands: ['codex'] } },
92
123
  {
93
124
  registryAgent: 'qoder',
94
125
  defaultName: 'qoder',
95
126
  defaultLabel: 'Qoder',
96
127
  detect: { commands: ['qodercli'] },
97
- // The registry still launches 0.2.14, which only reports legacy `models`. The tested native
98
- // release reports ACP configOptions for model/mode and accepts session/set_config_option.
99
- // Keep registry installs on the same verified runtime as the native production baseline.
100
- distribution: { version: '1.1.61', npx: { package: '@qoder-ai/qodercli@1.1.61', args: ['--acp'] } },
128
+ // Native ACP is the sole Qoder entry. The exact --acp argv is pinned here; the package
129
+ // patch layer verifies the 1.1.75 package and its qoder-native-acp recipe hashes.
130
+ distribution: { version: '1.1.75', npx: { package: '@qoder-ai/qodercli@1.1.75', args: ['--acp'] } },
101
131
  },
102
132
  // `gemini` was here and is deliberately gone. `@google/gemini-cli --acp` now refuses `session/new`
103
133
  // outright ("This client is no longer supported for Gemini Code Assist for individuals … migrate
@@ -116,7 +146,7 @@ export const AXOM_AGENT_CATALOG = [
116
146
  // 其余字段照 registry#458 的条目写。
117
147
  supplement: {
118
148
  name: 'Kimi Code',
119
- version: '2.1.1',
149
+ version: '2.3.3',
120
150
  description: "Moonshot AI's next-gen coding agent",
121
151
  repository: 'https://github.com/MoonshotAI/kimi-code',
122
152
  website: 'https://moonshotai.github.io/kimi-code/',
@@ -124,13 +154,13 @@ export const AXOM_AGENT_CATALOG = [
124
154
  license: 'MIT',
125
155
  icon: 'https://cdn.agentclientprotocol.com/registry/v1/latest/kimi.svg',
126
156
  distribution: {
127
- binary: kimiCodeBinary('2.1.1', {
128
- 'darwin-aarch64': ['darwin-arm64', '8c3bad99571b16abd113ab5d511a98a36b852c0d5493991842a67b8c2bc4ecd0'],
129
- 'darwin-x86_64': ['darwin-x64', 'f6dc0289112c24119d070f9203d44bcd53580e380819db25b58be65643b75bd4'],
130
- 'linux-aarch64': ['linux-arm64', '5c68d74b139b47fb3457f3805a159cdfa942a6a98a159ab158a1baf93b024bbd'],
131
- 'linux-x86_64': ['linux-x64', 'b66cc3787bc9dfa6a06761305dc8878f98e7a24f79fa4494c00714229a1486e8'],
132
- 'windows-aarch64': ['win32-arm64', '72bb17fef0d165a5f61905ede7e57c552791905d605a778967d054fe702873d4'],
133
- 'windows-x86_64': ['win32-x64', '87756a53a9bb0915842d884eaf43f69a06b2e404bcbb05d41c519c12d4b410cb'],
157
+ binary: kimiCodeBinary('2.3.3', {
158
+ 'darwin-aarch64': ['darwin-arm64', 'd097b397db785e9bde07e9d169870e315dd9a0d9d6542727ea4a50e4a630a280'],
159
+ 'darwin-x86_64': ['darwin-x64', '9c42127a60488add5cfb8ca60d35f4df9d881552eb3b05268c3a691f7b3c5406'],
160
+ 'linux-aarch64': ['linux-arm64', '4b12a13d64dbf9cde631e4c74965ccd1b72bfd93892b30d8272b4bc6448fe45f'],
161
+ 'linux-x86_64': ['linux-x64', '0e4a766d38e5202a2413b8517bd4b3a2c00486327a6e231c98f99a0bbf7422e1'],
162
+ 'windows-aarch64': ['win32-arm64', '655a4b0e57090fa414aec6c69e4801c12a28e7ca75dd627bfc64340b600079fd'],
163
+ 'windows-x86_64': ['win32-x64', '08bd5fcb7b0d6b3bcd70ef42e58b73c884149905b0044544a941ad795f587c4a'],
134
164
  }),
135
165
  },
136
166
  },
@@ -145,19 +175,20 @@ export const AXOM_AGENT_CATALOG = [
145
175
  registryAgent: 'command-code',
146
176
  defaultName: 'command-code',
147
177
  defaultLabel: 'Command Code',
148
- // registry 没有它。1.66.0 还没有 `acp` 子命令,1.74.3 起有、真机试跑通过。包里有 `cmd`、`cmdc`、
178
+ // registry 没有它。1.66.0 还没有 `acp` 子命令,1.74.3 起有、真机试跑通过;2026-10-27 已到 1.88.0(10-25):`acp` 子命令仍在(四个 bin 不变),commandcode-account-limits 配方已随
179
+ // generate.py 移植(handler map 枚举每版改名 u/dn→m/hn→m/vn→m/bn,锚点已跟)。包里有 `cmd`、`cmdc`、
149
180
  // `commandcode`、`command-code` 四个 bin,npx 挑与包名同名的那个。没有 ACP 登录方法,只有一句
150
181
  // 说明(终端里跑 `cmd login`);凭据在 `~/.commandcode`,与用户自己装的那份共用。npm 上的许可证
151
182
  // 写的是 UNLICENSED(专有)。
152
183
  supplement: {
153
184
  name: 'Command Code',
154
- version: '1.74.3',
185
+ version: '1.88.0',
155
186
  description: 'Command Code, coding agent that continuously learns your coding taste.',
156
187
  website: 'https://commandcode.ai',
157
188
  authors: ['Command Code'],
158
189
  license: 'UNLICENSED',
159
190
  icon: 'https://commandcode.ai/favicon.ico',
160
- distribution: { npx: { package: 'command-code@1.74.3', args: ['acp'] } },
191
+ distribution: { npx: { package: 'command-code@1.88.0', args: ['acp'] } },
161
192
  },
162
193
  detect: { commands: ['command-code', 'commandcode'] },
163
194
  },
@@ -165,21 +196,27 @@ export const AXOM_AGENT_CATALOG = [
165
196
  registryAgent: 'zcode-acp',
166
197
  defaultName: 'zcode',
167
198
  defaultLabel: 'ZCode',
168
- unverified: 'zcode-acp 0.63/0.64 与 ZCode 桌面 3.14.x 不兼容:3.14 不写 ~/.zcode/v2/config.json,模型只剩无授权的 ' +
169
- 'builtin:bigmodel-coding-plan\\GLM-5.3,首轮 CONFIGURATION_ERROR "Model creation failed"(2026-10-06 两台机器复现)。',
170
- // 社区适配器(registry#566、#650 都还没合),驱动的是 ZCode 桌面应用自带的 `zcode app-server`,
199
+ // 社区适配器(registry#566、#650 都还没合),驱动的是 ZCode 桌面应用自带的 `zcode app-server`,
171
200
  // 所以 ZCode 本体是前置依赖,而且没有一条我们能替用户跑的安装命令 —— 只能告诉他去装。
172
- // 凭据在 `~/.zcode/v2/config.json`,由 ZCode 自己登录写下。Linux 上本体没有固定路径,只认 PATH。
201
+ // 凭据:legacy `~/.zcode/v2/config.json`,但 ZCode 桌面 3.14.x 起不再写它;适配器 0.68.1+(上游
202
+ // #320)在 config.json 缺席时改读加密凭据库 `~/.zcode/v2/credentials.json`(桌面登录时写下)取
203
+ // individual coding-plan 的 api-key。Linux 上本体没有固定路径,只认 PATH。
204
+ // 2026-10-13 真机验证(ZCode 桌面 3.14.5 + 0.69.3):initialize → session/new → 首轮 prompt 通过,
205
+ // 日志 "serving the coding-plan API key (config.json or store)"。0.63/0.64 那轮不兼容(模型只剩
206
+ // 无授权的 builtin:bigmodel-coding-plan\GLM-5.3,首轮 CONFIGURATION_ERROR "Model creation failed",
207
+ // 2026-10-06 两台机器复现)自 0.68.1 起修复。2026-10-27 nightly 升到 0.76.3:subagent 探针在
208
+ // 0.76.3 补丁副本上通过、pristine 复现缺失(上游仍无 subagent/async 变体、无配额能力、无模型
209
+ // 兜底);全部锚点存活,配方纯重哈希。
173
210
  supplement: {
174
211
  name: 'ZCode',
175
- version: '0.63.0',
212
+ version: '0.76.3',
176
213
  description: 'Community bridge that drives the real ZCode app-server (GLM) over ACP.',
177
214
  repository: 'https://github.com/william0wang/zcode-acp',
178
215
  website: 'https://github.com/william0wang/zcode-acp',
179
216
  authors: ['William Wang'],
180
217
  license: 'Apache-2.0',
181
218
  icon: 'https://raw.githubusercontent.com/william0wang/zcode-acp/main/registry/zcode-acp/icon.svg',
182
- distribution: { npx: { package: 'zcode-acp-server@0.63.0' } },
219
+ distribution: { npx: { package: 'zcode-acp-server@0.76.3' } },
183
220
  },
184
221
  prerequisite: {
185
222
  label: 'ZCode',
@@ -200,6 +237,10 @@ export const AXOM_AGENT_CATALOG = [
200
237
  defaultName: 'pi',
201
238
  defaultLabel: 'Pi',
202
239
  recommended: true,
240
+ // pi-steering 与 pi-subagent-subwork 两份配方只核验过 0.0.34。registry 今天也在 0.0.34,
241
+ // 但那是巧合而不是保护:上游一发 0.0.35,未钉版本的 Install 就会装上一个 steering/子代理
242
+ // 归一都不生效的包。钉住后版本只随配方移植走(DAILY_UPGRADE_CHECK.md)。
243
+ distribution: { version: '0.0.34', npx: { package: 'pi-acp@0.0.34' } },
203
244
  prerequisite: {
204
245
  label: 'Pi',
205
246
  detect: { commands: ['pi'] },
@@ -212,8 +253,87 @@ export const AXOM_AGENT_CATALOG = [
212
253
  requiresNode: '>=22.19.0',
213
254
  },
214
255
  },
256
+ {
257
+ // 推荐位第二名(pi 之后的第一个):真机验证记录见 2026-10-13 genius 站验证(scan/verify/会话/审批
258
+ // 全链路)。hermes 不在公开 ACP registry(41 个 agent 里没有),本条同时是 supplement —— registry
259
+ // 一旦收录这个 id 就整体让位。PyPI 上的 `hermes-agent`(0.19.0,requires_python <3.14)是过时的
260
+ // 次要通道,官方分发是 `curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash`(git
261
+ // clone + pm bootstrap,写 ~/.local/bin/{hermes,hermes-acp}),所以走 pathLaunch 而不是 uvx:
262
+ // 启动用户自己装的那份,本机只有一份,与 pi 的本体同款哲学。`hermes-acp` 是官方 wheel/git 都
263
+ // 声明的 ACP console script;不要用 `hermes-agent`(那是 demo runner)或裸 `hermes`(CLI 主入口,
264
+ // acp 只是它的子命令 —— 两者都不带 ACP 语义的入口保障)。
265
+ registryAgent: 'hermes-acp',
266
+ defaultName: 'hermes',
267
+ defaultLabel: 'Hermes',
268
+ recommended: true,
269
+ detect: {
270
+ commands: ['hermes'],
271
+ locations: everyPlatform(['~/.local/bin/hermes-acp'], ['~/.local/bin/hermes-acp.exe']),
272
+ },
273
+ pathLaunch: { command: 'hermes-acp', hint: 'Install Hermes Agent with the official installer (curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash), then scan again.' },
274
+ supplement: {
275
+ name: 'Hermes',
276
+ version: '0.21.7',
277
+ description: "Nous Research's self-improving coding agent — native ACP server (hermes acp).",
278
+ repository: 'https://github.com/NousResearch/hermes-agent',
279
+ website: 'https://hermes-agent.nousresearch.com',
280
+ authors: ['Nous Research'],
281
+ license: 'Apache-2.0',
282
+ icon: 'https://hermes-agent.nousresearch.com/favicon.ico',
283
+ // supplement 必须给一条 distribution 才能在 registry 类型里站得住;hermes 没有任何可安装产物,
284
+ // 留空 distribution 由 pathLaunch 接管 available(见 acpAgents.ts 的 roster)。
285
+ distribution: {},
286
+ },
287
+ },
215
288
  // registry 自己的条目(binary .par),我们只补名字与本机检测;`agy` 是 Antigravity 装好后放进 PATH 的命令。
216
- { registryAgent: 'antigravity-acp', defaultName: 'google-antigravity', defaultLabel: 'Google Antigravity', detect: { commands: ['agy'] } },
289
+ // distribution 钉住:antigravity 的账号配额靠 native extension(runtime.json
290
+ // native_extensions,account-limits/antigravity-proxy.mjs),proxy 是 stdio sidecar,只在核验过的
291
+ // 版本上声明能力。2026-10-25 nightly 升到 1.4.3:真实 1.4.3 .par 经 proxy 拉起,initialize 透传无损、
292
+ // `axom/accountRateLimits`(v5)能力注入成功(本地实测;配额 READ 属于用户凭据路径,留给真机冒烟)。
293
+ // 归档 URL 抄自 registry 的 1.4.3 条目(六平台 HEAD 200);registry 本身不给这个条目发 sha256,这里同样不发,校验语义与
294
+ // registry 直装一致(binaryInstall:无 sha256 即不校验)。上游发新版时按 axom-patch/DAILY_UPGRADE_CHECK.md 核验后同升。
295
+ {
296
+ registryAgent: 'antigravity-acp',
297
+ defaultName: 'google-antigravity',
298
+ defaultLabel: 'Google Antigravity',
299
+ detect: { commands: ['agy'] },
300
+ distribution: {
301
+ version: '1.4.3',
302
+ binary: {
303
+ 'darwin-aarch64': { archive: 'https://dl.google.com/agy-extensions/releases/macos/agy-acp-server-1.4.3-darwin-arm64.zip', cmd: './agy_acp_server.par' },
304
+ 'darwin-x86_64': { archive: 'https://dl.google.com/agy-extensions/releases/macos/agy-acp-server-1.4.3-darwin-x86_64.zip', cmd: './agy_acp_server.par' },
305
+ 'linux-x86_64': { archive: 'https://dl.google.com/agy-extensions/releases/linux/agy-acp-server-1.4.3-linux-x86_64.zip', cmd: './agy_acp_server.par', args: ['--uid='] },
306
+ 'linux-aarch64': { archive: 'https://dl.google.com/agy-extensions/releases/linux/agy-acp-server-1.4.3-linux-arm64.zip', cmd: './agy_acp_server.par', args: ['--uid='] },
307
+ 'windows-x86_64': { archive: 'https://dl.google.com/agy-extensions/releases/windows/agy-acp-server-1.4.3-windows-x86_64.zip', cmd: './agy_acp_server.exe' },
308
+ 'windows-aarch64': { archive: 'https://dl.google.com/agy-extensions/releases/windows/agy-acp-server-1.4.3-windows-arm64.zip', cmd: './agy_acp_server.exe' },
309
+ },
310
+ },
311
+ },
312
+ // CodeBuddy(腾讯的编码 agent,npm 是它唯一的官方 CLI 分发)。registry 已收录 `codebuddy-code`
313
+ // (npx @tencent-ai/codebuddy-code --acp,包自带 @agentclientprotocol/sdk 依赖),于是这是最普通
314
+ // 的「registry 条目 + 本清单认证」形态:不 supplement(registry 有这个 id)、不 pathLaunch(有可装
315
+ // 产物,Axom 装自己托管的那份)、不钉版本(没有依赖版本的配方)、不配 launchEnv——本条就是
316
+ // CodeBuddy 本身,登录落在它的 copilot.tencent.com。
317
+ //
318
+ // 2026-10-19/21 真机实测(npm 2.169.0/2.171.0,ACP capture):`--acp` 起 initialize 通过,能力
319
+ // image/embeddedContext/mcp http+sse/loadSession/delegateTools/multitask;authMethods 声明
320
+ // iOA、external(Google/Github)、internal(WeChat)、selfhosted;登录链接经 `_codebuddy.ai/authUrl`
321
+ // 扩展通知推送(acpClient 的处理器)。凭据在 CODEBUDDY_CONFIG_DIR(默认 ~/.codebuddy)的
322
+ // credentials.json,登录走 ACP 认证流(一次性,与终端 CLI 共用)。
323
+ //
324
+ // 同一引擎另有 App 产品形态(App 内 product.json 声明 productName/endpoint/计费,经其自设的
325
+ // ACC_PRODUCT_CONFIG_PATH 环境变量切换)——那是**另一个产品、另一套账号**,npm 包名、registry
326
+ // id、CLI bin 都不带它的名字;Axom 只策展 npm 的 CodeBuddy,不策展那个 App 形态,也不替用户
327
+ // 预设产品开关(真需要的用户可经 agentEnv 自行覆盖)。
328
+ //
329
+ // detect 认 npm 包的两个主 bin(codebuddy 与 cbc;codebuddy-code/codebuddy-lowmem 是同名
330
+ // 变体,不另列)。
331
+ {
332
+ registryAgent: 'codebuddy-code',
333
+ defaultName: 'codebuddy',
334
+ defaultLabel: 'CodeBuddy',
335
+ detect: { commands: ['codebuddy', 'cbc'] },
336
+ },
217
337
  ];
218
338
  /**
219
339
  * Kimi Code 的六个平台归档:GitHub release `@moonshot-ai/kimi-code@<version>` 下的
@@ -236,30 +356,58 @@ function everyPlatform(unix, windows) {
236
356
  };
237
357
  }
238
358
  const BY_ID = new Map(AXOM_AGENT_CATALOG.map((entry) => [entry.registryAgent, entry]));
359
+ /**
360
+ * 静态推荐条目的展示序(目录数组序):推荐层的排序依据,用户可指定(2026-10-13:pi 第一、hermes
361
+ * 第二)。名册序做不到这件事 —— supplement 追加在 registry 之后,字母序又与本意相反(H < P),
362
+ * 所以显式带一个序号,roster 经 `recommendedRank` 下发、推荐层按它排。非静态推荐的 detected 卡
363
+ * ("本机在用")没有序号,排在静态推荐之后、按 label 字母序。
364
+ */
365
+ export const RECOMMENDED_RANK = new Map(AXOM_AGENT_CATALOG
366
+ .map((entry, index) => [entry.registryAgent, index])
367
+ .filter(([id]) => catalogEntryFor(id)?.recommended === true)
368
+ .map(([id], rank) => [id, rank]));
239
369
  export function catalogEntryFor(registryAgent) {
240
370
  return BY_ID.get(registryAgent);
241
371
  }
242
- /**
243
- * The registry entry as Axom will actually install and launch it: unchanged unless something
244
- * overrides it. A distribution replaces the registry's `version` and `distribution` — a runtime.json
245
- * override that applies at this registry version first, else this catalog's own. Launch env is merged
246
- * under every distribution's own `env` (the registry's declared variables win over ours). Identity
247
- * and the registry's own words never move (see the file header).
248
- */
249
- export function applyCatalogOverrides(agent) {
372
+ /** The CLI-owned launch environment for one agent at one registry version: catalog `launchEnv`, then runtime.json `env`. */
373
+ export function catalogLaunchEnv(agentId, registryVersion) {
374
+ return { ...catalogEntryFor(agentId)?.launchEnv, ...patchOverridesFor(agentId, registryVersion).env };
375
+ }
376
+ export function effectiveEntry(agent, supplemented = false) {
250
377
  const entry = catalogEntryFor(agent.id);
251
378
  const patch = patchOverridesFor(agent.id, agent.version);
252
379
  const pinned = patch.distribution ?? entry?.distribution;
253
- const launchEnv = { ...entry?.launchEnv, ...patch.env };
380
+ const pinnedBy = patch.distribution ? 'runtime-override'
381
+ : entry?.distribution || supplemented ? 'catalog' : undefined;
254
382
  let effective = agent;
255
383
  if (pinned) {
256
384
  const { version, ...distribution } = pinned;
257
385
  effective = { ...effective, version, distribution };
258
386
  }
259
- if (Object.keys(launchEnv).length) {
260
- effective = { ...effective, distribution: withLaunchEnv(effective.distribution, launchEnv) };
261
- }
262
- return effective;
387
+ return {
388
+ agent: effective,
389
+ registryVersion: agent.version,
390
+ launchEnv: { ...entry?.launchEnv, ...patch.env },
391
+ ...(pinnedBy ? { pinnedBy } : {}),
392
+ };
393
+ }
394
+ /** {@link withCatalogEntries} then {@link effectiveEntry} over a whole registry document, supplements marked as catalog pins. */
395
+ export function effectiveEntries(agents) {
396
+ const published = new Set(agents.map((agent) => agent.id));
397
+ return withCatalogEntries(agents).map((agent) => effectiveEntry(agent, !published.has(agent.id)));
398
+ }
399
+ /**
400
+ * The registry entry as Axom will actually install and launch it: unchanged unless something
401
+ * overrides it. A distribution replaces the registry's `version` and `distribution` — a runtime.json
402
+ * override that applies at this registry version first, else this catalog's own. Launch env is merged
403
+ * under every distribution's own `env` (the registry's declared variables win over ours). Identity
404
+ * and the registry's own words never move (see the file header).
405
+ */
406
+ export function applyCatalogOverrides(agent) {
407
+ const { agent: effective, launchEnv } = effectiveEntry(agent);
408
+ if (!Object.keys(launchEnv).length)
409
+ return effective;
410
+ return { ...effective, distribution: withLaunchEnv(effective.distribution, launchEnv) };
263
411
  }
264
412
  /** The registry's list with this catalog's supplements added where the registry lacks them and superseded ids removed. */
265
413
  export function withCatalogEntries(agents) {
@@ -1,128 +1,85 @@
1
+ import { existsSync } from 'node:fs';
2
+ import { homedir } from 'node:os';
1
3
  import path from 'node:path';
2
- import { binaryTargetFor, installedBinaryVersion, platformTriple } from '../binaryInstall.js';
3
- import { npmPackageName } from '../installProbe.js';
4
- import { uvPackageName, uvToolEntrypoint, uvToolEntrypointFrom } from '../uvxInstall.js';
5
- export class UnsupportedDistributionError extends Error {
6
- }
7
- /** `npx --yes <specifier> [dist args]`,两个调用方共用的一处构造:钉版本的和不钉版本的。 */
8
- function npxLaunch(specifier, npx, platform) {
9
- return {
10
- command: platform === 'win32' ? 'npx.cmd' : 'npx',
11
- // `--yes` 让首次拉包不停在交互确认上。
12
- args: ['--yes', specifier, ...(npx.args ?? [])],
13
- env: { ...(npx.env ?? {}) },
14
- };
15
- }
4
+ import semver from 'semver';
5
+ import { fileURLToPath } from 'node:url';
6
+ import { managedRuntimeFor, verifyManagedRuntime, verifyRecordedManagedRuntime } from '../managedRuntime.js';
7
+ import { nativeExtensionFor } from '../patchAssets.js';
8
+ import { verifyPatchedFiles } from '../managedPatches.js';
9
+ import { AdapterNotInstalledError, inside, labelFor } from '../builds/model.js';
10
+ import { assertBuildRunsOn } from '../builds/nodeGate.js';
16
11
  /**
17
- * registry 只给原料,不给命令行 —— 没有 `command` 字段,启动方式要从 `distribution` 推导。
18
- *
19
- * 三种分发方式现在都支持:`npx`/`uvx` 走各自安装侧维护的缓存/工具目录(见 `installProbe.ts`、
20
- * `uvxInstall.ts`),`binary` 走 `binaryInstall.ts`(Task 8)—— 按六个平台三元组挑一个目标、
21
- * 从 `adapterRoot` 找已经装好的版本。三条路径共同的规则是:**从不猜**,找不到就抛
22
- * `UnsupportedDistributionError`,理由写清楚是"这个平台没有发行版"还是"这台机器还没装",而不是
23
- * 笼统的一句"不支持"。
12
+ * `env` with `prefix` first on its `PATH` — unless `PATH` already starts with exactly that prefix (the
13
+ * spec's own env survived the merge), so applying it twice is harmless.
24
14
  */
25
- export async function resolveLaunch(agent, platform,
26
- // 六个平台三元组里的一半;只有 binary 分支用到。
27
- arch,
28
- // `<workstation config dir>/acp-adapters` —— `binaryInstall.ts` 解包落地的根目录,只有 binary
29
- // 分支用到。npx 走 npm 自己的 `_npx` 缓存,uvx 走 `uv tool dir`,都不需要这个根目录。
30
- adapterRoot,
31
- // 仅测试注入:真实调用永远走 `uvxInstall.ts` 的默认 `uv` 实现。签名上留成可选,两个真实调用点
32
- // (`acpAgents.ts`)不用跟着改。下面的 `uvTools` 给出时,这个参数被忽略 —— 见它的说明。
33
- run,
34
- // 已经读好的 `uv tool list` 快照(`listUvTools`)。给了就直接查表,不再自己起 `uv` 子进程 ——
35
- // `AcpAgents.roster` 为整份 39 条 registry 只读一次,把结果传进这里,而不是让每个 uvx agent
36
- // 在这条路径上各自再起一次 `uv`。真正的启动路径(`resolveLaunchFor`)不传这个参数,继续用
37
- // `run`/默认实现现读一次,这里的现读对它而言正是期望行为。
38
- //
39
- // 这个函数整体是 async 的唯一原因:`uv` 现在是非阻塞调用(`RunUv` 返回 `Promise`,见
40
- // `uvxInstall.ts`),没有预取快照时这里必须 `await` 它。给了 `uvTools` 的那条路径
41
- // (`AcpAgents.resolvable`)完全同步、不等待任何东西,包成 `async` 只是让两条路径共用同一个
42
- // 签名——`Promise.resolve` 包一层同步返回值的开销,跟每次 roster 扫描本来就要付的成本比可以
43
- // 忽略不计。
44
- uvTools) {
45
- const { npx, uvx, binary } = agent.distribution;
46
- // specifier 里已内联精确版本,不会追 latest —— 除非 registry 钉的那个版本 npm 根本没有,
47
- // 见 {@link unpinnedFallbackFor}。
48
- if (npx)
49
- return npxLaunch(npx.package, npx, platform);
50
- if (uvx) {
51
- // 不走 `uvx <pkg>`:那条路用 uv 自己的临时环境缓存,目录名带哈希,"装没装"读不可靠。
52
- // 改成我们自己 `uv tool install`、启动时直接跑装出来的入口点 —— 与 binary 一样,
53
- // 落到"我们装的、我们知道装在哪"这一条统一规则上。
54
- const outcome = uvTools
55
- ? uvToolEntrypointFrom(uvPackageName(uvx.package), uvTools)
56
- : await uvToolEntrypoint(uvPackageName(uvx.package), run);
57
- if (outcome.ok) {
58
- return { command: outcome.path, args: [...(uvx.args ?? [])], env: { ...(uvx.env ?? {}) } };
59
- }
60
- if (outcome.reason === 'ambiguous') {
61
- // 装了,但不敢猜:多个可执行文件里没有一个跟包名同名,uv 的列出顺序又不是文档化契约——
62
- // 静默启动错的那个,换来的是一次没人能追回这里的 ACP 握手挂死或失败,比拒绝启动更糟。
63
- throw new UnsupportedDistributionError(`Agent '${agent.id}' is distributed through uvx and its tool is installed, but this build ` +
64
- `cannot tell which of its executables is the ACP adapter: ${outcome.candidates.join(', ')}.`);
65
- }
66
- throw new UnsupportedDistributionError(`Agent '${agent.id}' is distributed through uvx but its tool is not installed on this machine.`);
67
- }
68
- if (binary) {
69
- // 六个平台三元组里挑一个;`windows-aarch64` 在实测的 registry 快照上只有 9/18 的覆盖,
70
- // "这个平台没有发行版"是常态,不是异常——`installBinary`(`binaryInstall.ts`)在下载前就
71
- // 用同一个函数做同一个判断,这里只是启动路径上再问一次同一件事,答案必须一致。
72
- const triple = platformTriple(platform, arch);
73
- const target = triple ? binaryTargetFor(agent, triple) : undefined;
74
- if (!target) {
75
- throw new UnsupportedDistributionError(`Agent '${agent.id}' publishes no archive for ${triple ?? `${platform}-${arch}`}.`);
76
- }
77
- // 装没装是这台机器磁盘上的事实,不是 registry 条目的属性 —— 跟 npx/uvx 分支一样,没装就说
78
- // "没装",不是"不支持"。
79
- //
80
- // `agent.version` 必须传:同一个 agent 的多个版本可以并存(`<root>/<agent>/<version>/`,
81
- // 就是为此设计的),`pickInstalledVersion` 的规则是"钉的版本在就取它,否则取最大"。
82
- // `AcpAgents.roster` 报告 `adapterVersion` 时传了它,这里不传就会在两个版本并存时报告一个、
83
- // 启动另一个 —— 名册说 0.75.0、跑起来是 0.74.0,而且没有任何一处会说出这件事。
84
- const version = installedBinaryVersion(agent.id, adapterRoot, agent.version);
85
- if (!version) {
86
- throw new UnsupportedDistributionError(`Agent '${agent.id}' has no installed adapter on this machine.`);
87
- }
88
- return {
89
- command: path.join(adapterRoot, agent.id, version, target.cmd),
90
- args: [...(target.args ?? [])],
91
- env: { ...(target.env ?? {}) },
92
- };
93
- }
94
- throw new UnsupportedDistributionError(`Agent '${agent.id}' declares no launchable distribution.`);
15
+ export function withPathPrefix(env, prefix) {
16
+ if (!prefix?.length)
17
+ return env;
18
+ const head = prefix.join(path.delimiter);
19
+ const current = env.PATH ?? '';
20
+ if (current === head || current.startsWith(head + path.delimiter))
21
+ return env;
22
+ return { ...env, PATH: current ? head + path.delimiter + current : head };
95
23
  }
96
24
  /**
97
- * 同一个 agent,但把 registry 钉的版本从 specifier 上剥掉 —— 上游钉了一个 npm 上并不存在的版本时,
98
- * 唯一还能把这个 agent 救回来的启动方式。
99
- *
100
- * ## 为什么需要它
101
- *
102
- * 2026-09-04 实测:registry 的 `codex-acp` 条目声明
103
- * `@agentclientprotocol/codex-acp@1.10.0`,而 npm 上这个包的版本停在 `1.9.0`
104
- * (`dist-tags.latest` 也是 `1.9.0`)。于是每一次 codex 启动都是 `npm error code ETARGET`,npx 退出,
105
- * 子进程死掉 —— 两台真实工作站同时失去了 codex。这是上游的缺陷;这里能做的是不让它把 agent 砖掉。
106
- *
107
- * ## 代价,以及为什么仍然值得
25
+ * The spawn spec for an installed build — **no npx, no registry read, no network**: the build's own
26
+ * entry, run with a fixed absolute Node (`nodePath`, the daemon's `process.execPath`) when it is
27
+ * JavaScript, or executed directly when it is native.
108
28
  *
109
- * 不钉版本装回来的,是 npm 此刻叫 `latest` 的那一个 —— **registry 从来没有指定过它**。它可能比钉的
110
- * 版本新(常见,上游多半正是发版发歪了),也可能是一个协议行为不同、甚至跟这个客户端谈不拢
111
- * `initialize` 的版本。所以这条路只在 ETARGET 上走(见 `acpClient.ts` 的 `isMissingPackageVersion`),
112
- * 只走一次,而且两条 warn 日志会把「跑的不是 registry 要的那个版本」说穿。
113
- *
114
- * ## 三种「没有回退可言」的情况,都返回 undefined
29
+ * `launchEnv` is the running CLI's catalog/runtime.json launch environment for this agent, evaluated
30
+ * at the registry version the build was installed from. It goes underneath the build's own
31
+ * (distribution-declared) env, the same order `registry/catalog.ts`'s `withLaunchEnv` always used.
32
+ * A patched build's files are re-hashed first (the tamper check that used to run on every launch), and
33
+ * a JavaScript build must pass the Node gate (`builds/nodeGate.ts`) against `nodePath`.
34
+ */
35
+ /**
36
+ * Expand a leading `~` / `~/` in every env value against the user's home directory.
115
37
  *
116
- * 没有 npx 分发(`uvx` 走的是 uv 自己的缓存,`binary` 这个版本压根不支持)、specifier 本来就不带版本
117
- * (剥无可剥,npm 已经在追 latest 了)。剥版本用 `npmPackageName`,它按最后一个 `@` 切,所以
118
- * `@scope/name@1.10.0` → `@scope/name`,而前导的 `@` 不会被当成版本分隔符。
38
+ * Why here and nowhere else: the CLI-owned `launchEnv` (catalog / runtime.json) ships as a static
39
+ * file, so it cannot spell the per-machine absolute path some consumers need — Claude's
40
+ * `CLAUDE_SECURESTORAGE_CONFIG_DIR` is used as a literal path and never expands `~` itself. And the
41
+ * final merged env is the only point that covers both sources: a build's own distribution env
42
+ * overwrites same-key `launchEnv` values, so expanding the `launchEnv` alone would let an unexpanded
43
+ * build value win. Only a leading `~` is touched; a `~` elsewhere in a value is data, not a path.
119
44
  */
120
- export function unpinnedFallbackFor(agent, platform) {
121
- const npx = agent.distribution.npx;
122
- if (!npx)
123
- return undefined;
124
- const unpinned = npmPackageName(npx.package);
125
- if (unpinned === npx.package)
126
- return undefined;
127
- return { pinned: npx.package, unpinned, launch: npxLaunch(unpinned, npx, platform) };
45
+ function expandHomeInEnv(env) {
46
+ const home = homedir();
47
+ return Object.fromEntries(Object.entries(env).map(([key, value]) => [key, value === '~' ? home : value.startsWith('~/') ? path.join(home, value.slice(2)) : value]));
48
+ }
49
+ export async function launchForBuild(build, root, options) {
50
+ const policy = options.policy ?? managedRuntimeFor(build.agentId);
51
+ // Only a caller resolving an explicit recorded old binding/rollback may use legacy launch rules.
52
+ // Removing runtimeReleaseId from the strict target never changes its policy classification.
53
+ const legacy = options.allowLegacy && !build.runtimeReleaseId && policy && (build.package !== policy.package || (semver.valid(build.version) !== null && semver.lt(build.version, policy.version)));
54
+ if (policy && !legacy) {
55
+ const verify = options.allowLegacy && build.runtimeReleaseId ? verifyRecordedManagedRuntime : verifyManagedRuntime;
56
+ await verify({ ...options, policy, build, storeRoot: root, initialize: false });
57
+ }
58
+ // A build recorded under a strict policy this CLI no longer ships launches like any other build:
59
+ // its runtimeReleaseId is history, and the patched-file check below still applies.
60
+ const dir = inside(root, build.dir);
61
+ const entry = inside(dir, build.launch.entry);
62
+ if (build.kind === 'npm-patched' && build.package && build.patchedFiles) {
63
+ if (build.patchedFilesBase !== undefined && build.patchedFilesBase !== 'node_modules')
64
+ throw new Error('Invalid Axom patched file base');
65
+ const modules = path.join(dir, 'node_modules');
66
+ await verifyPatchedFiles(build.patchedFilesBase === 'node_modules' ? modules : inside(modules, build.package), build.patchedFiles);
67
+ }
68
+ if (!existsSync(entry))
69
+ throw new AdapterNotInstalledError(build.agentId, `build ${build.buildId} is missing its executable`);
70
+ // Every build launch passes the Node gate — patched and pristine alike, whatever the args look like.
71
+ await assertBuildRunsOn(build, root, options.nodePath);
72
+ const env = expandHomeInEnv({ ...options.launchEnv, ...build.launch.env });
73
+ const pathPrefix = build.launch.pathDirs?.map((relative) => inside(dir, relative));
74
+ if (pathPrefix?.length) {
75
+ env.PATH = pathPrefix.join(path.delimiter) + path.delimiter + (env.PATH ?? options.basePath ?? process.env.PATH ?? '');
76
+ }
77
+ const extra = pathPrefix?.length ? { pathPrefix } : {};
78
+ const extension = build.launch.runtime !== 'node' ? nativeExtensionFor(build.agentId, build.version) : undefined;
79
+ if (extension) {
80
+ return { command: options.nodePath, args: [fileURLToPath(extension), entry, ...build.launch.args], env, label: labelFor(build), ...extra };
81
+ }
82
+ return build.launch.runtime === 'node'
83
+ ? { command: options.nodePath, args: [entry, ...build.launch.args], env, label: labelFor(build), ...extra }
84
+ : { command: entry, args: [...build.launch.args], env, label: labelFor(build), ...extra };
128
85
  }
@@ -1,4 +1,7 @@
1
1
  import { codexActivityRaw } from './activityReporting.js';
2
+ export function newMapperScopeData() {
3
+ return { byId: {}, lastReportedQueueDepth: 0 };
4
+ }
2
5
  /**
3
6
  * One session's memory, and the reason this file is no longer stateless: **what this session has
4
7
  * already been told**, for the two branches that cannot answer a frame from the frame alone.
@@ -32,7 +35,7 @@ import { codexActivityRaw } from './activityReporting.js';
32
35
  */
33
36
  export class SessionMapperState {
34
37
  onActivityReported;
35
- byId = new Map();
38
+ data;
36
39
  /**
37
40
  * Where an agent-reported activity-state push (today, only `codexActivityRaw`'s extraction of
38
41
  * `session_info_update._meta.codex.threadStatus`) actually goes once {@link reportActivity} is
@@ -44,8 +47,11 @@ export class SessionMapperState {
44
47
  * replay path, which has no live connection to report anything on — keeps compiling and keeps
45
48
  * doing nothing, exactly as it always has.
46
49
  */
47
- constructor(onActivityReported = () => { }) {
50
+ constructor(onActivityReported = () => { },
51
+ /** The memory itself, mutated in place — the processor passes the checkpointed copy it owns. */
52
+ data = newMapperScopeData()) {
48
53
  this.onActivityReported = onActivityReported;
54
+ this.data = data;
49
55
  }
50
56
  /**
51
57
  * The agent queue depth this session has already reported to the server.
@@ -55,7 +61,9 @@ export class SessionMapperState {
55
61
  * reader already assumes. Seeding it to `-1` (or `null`) would let the very first frame through,
56
62
  * which on `pi-acp` is `startTurn`'s, i.e. the defect this field exists to prevent.
57
63
  */
58
- lastReportedQueueDepth = 0;
64
+ get lastReportedQueueDepth() {
65
+ return this.data.lastReportedQueueDepth;
66
+ }
59
67
  /**
60
68
  * Is `depth` news? Records it if so. **This is the whole fix for a defect that shipped in the
61
69
  * previous commit**, so the reasoning is written out rather than summarised.
@@ -110,7 +118,7 @@ export class SessionMapperState {
110
118
  reportsQueueDepth(depth) {
111
119
  if (depth === this.lastReportedQueueDepth)
112
120
  return false;
113
- this.lastReportedQueueDepth = depth;
121
+ this.data.lastReportedQueueDepth = depth;
114
122
  return true;
115
123
  }
116
124
  /**
@@ -126,7 +134,10 @@ export class SessionMapperState {
126
134
  /** Remember what this call is called. Later updates that carry no `name` fall back to it. */
127
135
  record(toolCallId, name) {
128
136
  if (name)
129
- this.byId.set(toolCallId, name);
137
+ this.remember(toolCallId, name);
138
+ }
139
+ remember(toolCallId, name) {
140
+ Object.defineProperty(this.data.byId, toolCallId, { value: name, enumerable: true, writable: true, configurable: true });
130
141
  }
131
142
  /**
132
143
  * The name to report for one update, in ACP's own order of authority: an explicit `name` on the
@@ -138,10 +149,10 @@ export class SessionMapperState {
138
149
  */
139
150
  resolve(toolCallId, name, title) {
140
151
  if (name) {
141
- this.byId.set(toolCallId, name);
152
+ this.remember(toolCallId, name);
142
153
  return name;
143
154
  }
144
- return this.byId.get(toolCallId) ?? title ?? 'unknown';
155
+ return (Object.hasOwn(this.data.byId, toolCallId) ? this.data.byId[toolCallId] : undefined) ?? title ?? 'unknown';
145
156
  }
146
157
  }
147
158
  /**