@platless/axom-cli 0.5.9 → 0.6.52

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 (258) hide show
  1. package/README.md +25 -6
  2. package/dist/axom-patch/cli/README.md +129 -12
  3. package/dist/axom-patch/cli/account-limits/generate.py +15 -12
  4. package/dist/axom-patch/cli/account-limits/kimi-proxy.mjs +20 -3
  5. package/dist/axom-patch/cli/claude-account-limits.json +9 -9
  6. package/dist/axom-patch/cli/claude-replay-lifecycle.json +16 -0
  7. package/dist/axom-patch/cli/codex-account-limits.json +11 -11
  8. package/dist/axom-patch/cli/codex-terminal-output.json +16 -0
  9. package/dist/axom-patch/cli/commandcode-account-limits.json +9 -9
  10. package/dist/axom-patch/cli/kimi-quota.mjs +12 -0
  11. package/dist/axom-patch/cli/kimi-subagents.mjs +173 -0
  12. package/dist/axom-patch/cli/nightly-task.md +55 -13
  13. package/dist/axom-patch/cli/probes/claude-replay-lifecycle.mjs +31 -0
  14. package/dist/axom-patch/cli/probes/codex-terminal-output.mjs +33 -0
  15. package/dist/axom-patch/cli/probes/kimi-subagent-subwork.mjs +82 -0
  16. package/dist/axom-patch/cli/probes/zcode-env-account.mjs +81 -0
  17. package/dist/axom-patch/cli/probes/zcode-subagent-subwork.mjs +7 -0
  18. package/dist/axom-patch/cli/qoder/dist/axom-acp-compat.mjs +1687 -0
  19. package/dist/axom-patch/cli/qoder/releases/1.1.75.json +277 -0
  20. package/dist/axom-patch/cli/qoder-background-terminal.md +13 -6
  21. package/dist/axom-patch/cli/qoder-foreground-output.md +14 -8
  22. package/dist/axom-patch/cli/qoder-native-acp.json +227 -0
  23. package/dist/axom-patch/cli/qoder-steering.md +20 -25
  24. package/dist/axom-patch/cli/qoder-subagent-subwork.md +17 -68
  25. package/dist/axom-patch/cli/runtime.json +19 -19
  26. package/dist/axom-patch/cli/zcode/env-account.mjs +13 -0
  27. package/dist/axom-patch/cli/zcode/generate-env-account.py +52 -0
  28. package/dist/axom-patch/cli/zcode-account-limits.json +10 -11
  29. package/dist/axom-patch/cli/zcode-env-account.json +58 -0
  30. package/dist/axom-patch/cli/zcode-models.json +9 -10
  31. package/dist/axom-patch/cli/zcode-subagent-subwork.json +10 -11
  32. package/dist/cli.js +11 -45
  33. package/dist/commands/auth.js +4 -1
  34. package/dist/commands/knowledge.js +47 -0
  35. package/dist/commands/update.js +126 -3
  36. package/dist/commands/workstation.js +101 -164
  37. package/dist/commands/workstationRegistrations.js +116 -0
  38. package/dist/credentialBroker.js +13 -2
  39. package/dist/credentials.js +16 -0
  40. package/dist/install/claude/commands.js +15 -15
  41. package/dist/keepers/terminal/keeper.mjs +1089 -673
  42. package/dist/keepers/terminal/manifest.json +4 -4
  43. package/dist/mcp.js +1 -1
  44. package/dist/native/darwin-x64/axom-quic +0 -0
  45. package/dist/workstation/acp/acpAgents.js +113 -102
  46. package/dist/workstation/acp/acpClient.js +26 -0
  47. package/dist/workstation/acp/builds/install/npm.js +99 -10
  48. package/dist/workstation/acp/initializeResponse.js +6 -1
  49. package/dist/workstation/acp/managedPatches.js +189 -25
  50. package/dist/workstation/acp/managedRuntime.js +314 -0
  51. package/dist/workstation/acp/outbox.js +12 -5
  52. package/dist/workstation/acp/patchAssets.js +40 -0
  53. package/dist/workstation/acp/permission.js +2 -2
  54. package/dist/workstation/acp/processor/checkpoint.js +26 -34
  55. package/dist/workstation/acp/processor/control.js +7 -80
  56. package/dist/workstation/acp/processor/jsonrpc.js +8 -0
  57. package/dist/workstation/acp/processor/runtime.js +5 -81
  58. package/dist/workstation/acp/processor/session.js +54 -82
  59. package/dist/workstation/acp/processor/state.js +7 -13
  60. package/dist/workstation/acp/processor/step.js +3 -20
  61. package/dist/workstation/acp/processor/test/fixtureLog.js +9 -16
  62. package/dist/workstation/acp/processor/transport/local.js +19 -3
  63. package/dist/workstation/acp/processor/updates.js +156 -105
  64. package/dist/workstation/acp/processorSession.js +20 -173
  65. package/dist/workstation/acp/registry/catalog.js +65 -39
  66. package/dist/workstation/acp/registry/launch.js +16 -1
  67. package/dist/workstation/acp/switching.js +0 -3
  68. package/dist/workstation/acp/test/fakeAgent.js +13 -0
  69. package/dist/workstation/acp/test/keeperWorld.js +32 -3
  70. package/dist/workstation/acp/test/raw/sources.js +16 -130
  71. package/dist/workstation/acp/test/realAdapter.js +1 -47
  72. package/dist/workstation/acp/test/scriptAgent.js +11 -3
  73. package/dist/workstation/agentFlow.js +1 -1
  74. package/dist/workstation/agentSessions.js +114 -166
  75. package/dist/workstation/channels/agent.js +9 -1
  76. package/dist/workstation/channels/computer.js +27 -4
  77. package/dist/workstation/channels/management.js +130 -15
  78. package/dist/workstation/channels/url.js +1 -1
  79. package/dist/workstation/config.js +33 -9
  80. package/dist/workstation/connection/encryptedChannel.js +4 -1
  81. package/dist/workstation/control/bindingStore.js +204 -0
  82. package/dist/workstation/control/commands.js +125 -0
  83. package/dist/workstation/control/daemonIdentity.js +143 -0
  84. package/dist/workstation/control/deviceCommands.js +191 -0
  85. package/dist/workstation/control/deviceProtocol.js +68 -0
  86. package/dist/workstation/control/enrollment.js +106 -0
  87. package/dist/workstation/control/inspect.js +71 -0
  88. package/dist/workstation/control/locks.js +110 -0
  89. package/dist/workstation/control/protocol.js +40 -0
  90. package/dist/workstation/control/restartGuard.js +46 -0
  91. package/dist/workstation/control/rootFormat.js +16 -0
  92. package/dist/workstation/control/runtimeClient.js +152 -0
  93. package/dist/workstation/control/runtimeHost.js +235 -0
  94. package/dist/workstation/control/serverIdentity.js +35 -0
  95. package/dist/workstation/control/updateTransition.js +91 -0
  96. package/dist/workstation/daemon.js +266 -264
  97. package/dist/workstation/daemonctl.js +226 -25
  98. package/dist/workstation/desktopControl/audio.js +99 -0
  99. package/dist/workstation/desktopControl/automationDevice.js +219 -0
  100. package/dist/workstation/desktopControl/automationJson.js +74 -0
  101. package/dist/workstation/desktopControl/automationLocalState.js +23 -0
  102. package/dist/workstation/desktopControl/automationProtocol.js +253 -0
  103. package/dist/workstation/desktopControl/automationSchema.generated.js +1 -0
  104. package/dist/workstation/desktopControl/automationSession.js +81 -0
  105. package/dist/workstation/desktopControl/automationTransport.js +138 -0
  106. package/dist/workstation/desktopControl/capabilities.js +93 -0
  107. package/dist/workstation/desktopControl/captureModes.js +9 -0
  108. package/dist/workstation/desktopControl/captureTargetLabel.js +9 -0
  109. package/dist/workstation/desktopControl/deviceAdmission.js +229 -0
  110. package/dist/workstation/desktopControl/deviceOwnership.js +130 -0
  111. package/dist/workstation/desktopControl/deviceSockets.js +246 -0
  112. package/dist/workstation/desktopControl/helperProcess.js +602 -0
  113. package/dist/workstation/desktopControl/hostGrant.js +65 -0
  114. package/dist/workstation/desktopControl/lobby.js +131 -0
  115. package/dist/workstation/desktopControl/macProvider.js +156 -0
  116. package/dist/workstation/desktopControl/media.js +331 -0
  117. package/dist/workstation/desktopControl/nativeDeviceAdmission.js +207 -0
  118. package/dist/workstation/desktopControl/nativeProvider.js +1044 -0
  119. package/dist/workstation/desktopControl/networkEvidence.js +43 -0
  120. package/dist/workstation/desktopControl/overview.js +58 -0
  121. package/dist/workstation/desktopControl/ownershipProtocol.js +31 -0
  122. package/dist/workstation/desktopControl/protocol.js +311 -0
  123. package/dist/workstation/desktopControl/provider.js +1 -0
  124. package/dist/workstation/desktopControl/quicMedia.js +240 -0
  125. package/dist/workstation/desktopControl/rateController.js +226 -0
  126. package/dist/workstation/desktopControl/supervisor.js +1774 -0
  127. package/dist/workstation/desktopControl/transport.js +27 -0
  128. package/dist/workstation/desktopControl/wallpaper.js +98 -0
  129. package/dist/workstation/exec/policy.js +5 -0
  130. package/dist/workstation/files/client.js +10 -1
  131. package/dist/workstation/files/credentials.js +142 -0
  132. package/dist/workstation/files/host.js +9 -2
  133. package/dist/workstation/files/text.js +42 -8
  134. package/dist/workstation/journal.js +5 -2
  135. package/dist/workstation/keepers/acp/client.js +38 -2
  136. package/dist/workstation/keepers/kit/buildVersion.js +35 -11
  137. package/dist/workstation/keepers/kit/bundle.js +21 -17
  138. package/dist/workstation/keepers/kit/client.js +2 -2
  139. package/dist/workstation/keepers/kit/launcher.js +123 -7
  140. package/dist/workstation/keepers/kit/paths.js +2 -1
  141. package/dist/workstation/keepers/legacy.js +16 -2
  142. package/dist/workstation/keepers/policy.js +5 -34
  143. package/dist/workstation/keepers/terminal/client.js +115 -23
  144. package/dist/workstation/keepers/terminal/exec.js +6 -3
  145. package/dist/workstation/keepers/terminal/frames.js +73 -0
  146. package/dist/workstation/keepers/terminal/generations.js +5 -8
  147. package/dist/workstation/keepers/terminal/gridProtocol.js +16 -0
  148. package/dist/workstation/keepers/terminal/input.js +146 -0
  149. package/dist/workstation/keepers/terminal/keeper.js +22 -8
  150. package/dist/workstation/keepers/terminal/main.js +1 -1
  151. package/dist/workstation/keepers/terminal/metadata.js +138 -0
  152. package/dist/workstation/keepers/terminal/protocol.js +4 -28
  153. package/dist/workstation/keepers/terminal/pty.js +1 -330
  154. package/dist/workstation/keepers/terminal/screen.js +246 -0
  155. package/dist/workstation/keepers/terminal/sessions.js +526 -0
  156. package/dist/workstation/managedInstall.js +57 -0
  157. package/dist/workstation/oauth/deviceAuthorization.js +31 -17
  158. package/dist/workstation/protocol/agent.js +2 -15
  159. package/dist/workstation/protocol/management.js +113 -5
  160. package/dist/workstation/protocol/runtimeDiagnostics.js +15 -0
  161. package/dist/workstation/rd/artifact.js +120 -0
  162. package/dist/workstation/rd/control.js +117 -0
  163. package/dist/workstation/rd/display.js +29 -0
  164. package/dist/workstation/rd/host.js +213 -0
  165. package/dist/workstation/rd/migrationReadiness.js +46 -0
  166. package/dist/workstation/rd/provider.js +256 -0
  167. package/dist/workstation/rd/sessions.js +391 -0
  168. package/dist/workstation/rd/state.js +57 -0
  169. package/dist/workstation/rd/update.js +168 -0
  170. package/dist/workstation/rd/upkeep.js +80 -0
  171. package/dist/workstation/register.js +27 -37
  172. package/dist/workstation/registrations/enrollment.js +250 -0
  173. package/dist/workstation/registrations/enrollmentPending.js +361 -0
  174. package/dist/workstation/registrations/migration.js +356 -0
  175. package/dist/workstation/registrations/model.js +34 -0
  176. package/dist/workstation/registrations/removal.js +222 -0
  177. package/dist/workstation/registrations/store.js +737 -0
  178. package/dist/workstation/runtime/desktopBinding.js +20 -0
  179. package/dist/workstation/runtime/deviceDesktop.js +193 -0
  180. package/dist/workstation/runtime/deviceRuntime.js +568 -0
  181. package/dist/workstation/runtime/deviceServices.js +117 -0
  182. package/dist/workstation/runtime/events.js +20 -0
  183. package/dist/workstation/runtime/ownership.js +100 -0
  184. package/dist/workstation/runtime/registrationRuntime.js +575 -0
  185. package/dist/workstation/runtime/remoteDesktopAdapter.js +186 -0
  186. package/dist/workstation/runtime/removalActivity.js +184 -0
  187. package/dist/workstation/service/installer.js +197 -14
  188. package/dist/workstation/service/launchd.js +2 -0
  189. package/dist/workstation/service/systemd.js +1 -0
  190. package/dist/workstation/storageMetrics.js +118 -0
  191. package/dist/workstation/systemMetrics.js +47 -92
  192. package/dist/workstation/toolchain.js +94 -0
  193. package/dist/workstation/tools/browser.js +28 -4
  194. package/dist/workstation/tools/client.js +8 -27
  195. package/dist/workstation/tools/info.js +6 -13
  196. package/dist/workstation/tools/terminalRouter.js +17 -172
  197. package/dist/workstation/tools/validation.js +55 -1
  198. package/dist/workstation/update/archiveEvidence.js +206 -0
  199. package/dist/workstation/update/artifact.js +2 -1
  200. package/dist/workstation/update/coordinator.js +34 -13
  201. package/dist/workstation/update/deviceCompatibility.js +119 -0
  202. package/dist/workstation/update/deviceCoordinator.js +369 -0
  203. package/dist/workstation/update/deviceHealth.js +104 -0
  204. package/dist/workstation/update/deviceHealthProtocol.js +26 -0
  205. package/dist/workstation/update/deviceRecoveryLifecycle.js +46 -0
  206. package/dist/workstation/update/deviceRollback.js +78 -0
  207. package/dist/workstation/update/globalInstall.js +186 -0
  208. package/dist/workstation/update/legacyBridge.js +414 -0
  209. package/dist/workstation/update/legacyOwner.js +39 -0
  210. package/dist/workstation/update/npmInstaller.js +51 -25
  211. package/dist/workstation/update/privateDurability.js +61 -0
  212. package/dist/workstation/update/rdRollback.js +145 -0
  213. package/dist/workstation/update/recoveryPlan.js +124 -0
  214. package/dist/workstation/update/runUpdate.js +10 -3
  215. package/dist/workstation/update/taskRegistry.js +161 -3
  216. package/dist/workstation/update/watchdog.js +29806 -333
  217. package/dist/workstation/update/watchdogProcess.js +72 -0
  218. package/package.json +11 -7
  219. package/skills/axom/SKILL.md +11 -11
  220. package/skills/axom-definition/SKILL.md +3 -3
  221. package/skills/axom-platform/SKILL.md +3 -3
  222. package/dist/axom-patch/cli/probes/qoder-steering.mjs +0 -89
  223. package/dist/axom-patch/cli/probes/qoder-subagent-origin.mjs +0 -61
  224. package/dist/axom-patch/cli/qoder-steering.json +0 -52
  225. package/dist/axom-patch/cli/qoder-subagent-origin.json +0 -73
  226. package/dist/commands/guide.js +0 -38
  227. package/dist/runtime-deps/qoder-sdk/package-lock.json +0 -1189
  228. package/dist/runtime-deps/qoder-sdk/package.json +0 -8
  229. package/dist/workstation/acp/delegationMcp.js +0 -24
  230. package/dist/workstation/acp/processor/sideChannel.js +0 -80
  231. package/dist/workstation/acp/qoderStartup.js +0 -45
  232. package/dist/workstation/acp/test/raw/qoderCaptures.js +0 -125
  233. package/dist/workstation/qoderAdapter/backgroundProcess.js +0 -118
  234. package/dist/workstation/qoderAdapter/backgroundTerminal.js +0 -193
  235. package/dist/workstation/qoderAdapter/backgroundTerminalFold.js +0 -372
  236. package/dist/workstation/qoderAdapter/callbackContext.js +0 -76
  237. package/dist/workstation/qoderAdapter/completedContinuation.js +0 -139
  238. package/dist/workstation/qoderAdapter/contract.js +0 -78
  239. package/dist/workstation/qoderAdapter/foregroundOutput.js +0 -36
  240. package/dist/workstation/qoderAdapter/history.js +0 -85
  241. package/dist/workstation/qoderAdapter/identityIndex.js +0 -191
  242. package/dist/workstation/qoderAdapter/inputQueue.js +0 -42
  243. package/dist/workstation/qoderAdapter/main.js +0 -95
  244. package/dist/workstation/qoderAdapter/mapper.js +0 -117
  245. package/dist/workstation/qoderAdapter/observerPlugin.js +0 -245
  246. package/dist/workstation/qoderAdapter/observerReceiver.js +0 -187
  247. package/dist/workstation/qoderAdapter/permissions.js +0 -61
  248. package/dist/workstation/qoderAdapter/profile.js +0 -93
  249. package/dist/workstation/qoderAdapter/sdkDriver.js +0 -48
  250. package/dist/workstation/qoderAdapter/sdkRuntime.js +0 -93
  251. package/dist/workstation/qoderAdapter/sdkRuntimeInstall.js +0 -145
  252. package/dist/workstation/qoderAdapter/session.js +0 -319
  253. package/dist/workstation/qoderAdapter/subagentMeta.js +0 -28
  254. package/dist/workstation/qoderAdapter/subwork.js +0 -85
  255. package/dist/workstation/qoderAdapter/taskControl.js +0 -38
  256. package/dist/workstation/qoderAdapter/taskLedger.js +0 -163
  257. package/dist/workstation/qoderAdapter/usage.js +0 -37
  258. /package/dist/workstation/{qoderAdapter/types.js → desktopControl/automationPreparation.js} +0 -0
@@ -1,96 +1,6 @@
1
- /**
2
- * One live agent session driven by the deterministic ACP processor over a transport (Task 19, spec 2026-10-11 §5.3/§5.4/§5.7):
3
- * the daemon side of keeper-acp — or of the local fallback, which is the same session mechanism in this process.
4
- *
5
- * ## The record loop
6
- *
7
- * The transport's raw stream (`subscribeRaw`) is the only input. For each record, in order:
8
- * `step(record)` → every command it produced is executed through the transport (`executeDownCommandsVia`: idempotent by cause,
9
- * refused unless its spawn runs now, prompt blocks filled from this daemon's memory, `secretRef`s substituted from this daemon's
10
- * memory) → a prompt whose blocks are gone is failed with an `agent_prompt_failed` note → the record's frames go out.
11
- * Everything the server or this daemon decides reaches the processor as a note or a write first (`agent_prompt`, `agent_answer`,
12
- * `agent_interrupt`, …); nothing here changes processor state directly, and nothing here numbers a frame — the processor does —
13
- * with the one exception the poison contract names (below).
14
- *
15
- * ## What leaves
16
- *
17
- * Frames the manager sends (`onFrames`), unchanged, with `src`. The ones meant for the daemon itself stay here:
18
- * `processor.open_result` settles {@link openSession}; `processor.history_event`/`history_end` become the load's backfill
19
- * (never journaled: a daemon that dies inside the window loads again); an `agent_steered` / `agent_config_option_set` whose
20
- * request this object made settles that call (one with nobody waiting goes out as a frame).
21
- *
22
- * ## Secrets and blocks
23
- *
24
- * Prompt and steer blocks are held in memory under a `blocksRef` until their `down` is written; secrets (a delegation bearer)
25
- * under a `secretRef`, for the life of the session. Notes carry only the refs (spec §13).
26
- *
27
- * ## Poison (interface-contracts, "中毒恢复契约")
28
- *
29
- * A step that throws poisons the processor. The session is degraded: every turn still open ends with a failed `agent_turn_done`
30
- * this object numbers itself, after the processor's last seq; the adapter is terminated; `onDegraded` tells the manager, which
31
- * retires the session so the next `agent_open` starts a new spawn (`session/load`). Never retried from a checkpoint: replay is
32
- * deterministic and would poison again on the same record. A transport that fails under the loop (keeper gone, raw truncated) is
33
- * handled the same way: Task 19 has no re-attach (Task 21).
34
- *
35
- * ## Qoder side files (17c)
36
- *
37
- * When the repair is on, a 1 s timer asks the processor's **current** `sideDemand` — only once the processor has folded every
38
- * record this object appended — runs `BackgroundSideNotes.poll(demand)` and appends the notes it returns, in order. The reader
39
- * stops when the demand is `undefined` (no repair any more).
40
- *
41
- * ## Outbox, backpressure, checkpoints (Task 20, spec §5.5/§5.6)
42
- *
43
- * The manager records every journaled frame in {@link outbox} (the transport's outbox stream) before it sends it; the listener
44
- * {@link onFrames} registers returns that append, and the loop awaits it before folding the next record — so the outbox holding a
45
- * frame with `src.o = o` proves record `o`'s commands are in raw, and a checkpoint at `o` never precedes `o`'s frames. Before each
46
- * record the loop waits for {@link SessionOutbox.room}: a server that does not acknowledge stops the processor, and the backlog
47
- * stays in the raw log.
48
- *
49
- * Checkpoints (`acp.commit{checkpoint, rawThrough}`, raw truncated to the checkpoint): at the end of every turn; within a turn
50
- * every {@link CHECKPOINT_RAW_BYTES} of folded raw or {@link CHECKPOINT_INTERVAL_MS}; and on a `close('keep')` (graceful exit,
51
- * detach). Never while `boundaries.sideChunk` holds a half-read Qoder fact or a load's history window is open — deferred to the
52
- * next record where both are clear. Each carries `processorVersion` (`checkpointOf`).
53
- *
54
- * ## A session left under the same key
55
- *
56
- * An earlier life of this ref (a swept or degraded session, a previous daemon's, a local outbox) is reused, not released: the new
57
- * spawn continues the same raw log and outbox. Its unacknowledged frames are read back into {@link outbox} (resent when the server
58
- * reopens the ref) and the processor numbers after the highest seq the outbox ever held — `max(outbox.maxSeq, committedTail.seq,
59
- * resumeFromSeq)` (§5.5). An earlier life whose adapter still runs is never stopped here: the daemon adopts it at start
60
- * ({@link ProcessorSession.adopt}), and keeper-acp refuses a second spawn into a running session.
61
- *
62
- * ## Adoption (Task 21, spec §5.5)
63
- *
64
- * A keeper-acp session whose adapter outlived the daemon (restart, upgrade, crash) is adopted, not stopped:
65
- * `acp.attach` → the head checkpoint is restored → raw `(checkpoint.offset, replayEnd]` is replayed **updating state only** —
66
- * `replayEnd = max(outbox last.src.o, committedTail.src.o)`, everything whose frames were recorded — and the frames the replay
67
- * produces are compared byte for byte with the outbox entries that survive (daemon-numbered ones, `src.i ≥ DAEMON_FRAME_INDEX`,
68
- * skipped; differences are only counted when the checkpoint came from this very processor version) → the seq continues after
69
- * `max(replayed seq, outbox.maxSeq, committedTail.seq)` → the unacknowledged outbox entries are resent on the server's reopen →
70
- * the records after `replayEnd` are folded live (their commands are idempotent by cause). A session whose open never completed, or
71
- * that cannot be rebuilt (no readable checkpoint and no spawn record left), is refused ({@link AdoptionRefusedError}); the caller
72
- * stops its adapter and keeps its outbox. A checkpoint is cut right after the spawn and when the open completes, so every session
73
- * has one that says whether it is open.
74
- *
75
- * ## Detach (Task 21, spec §5.5.5)
76
- *
77
- * {@link detach} ends this daemon's hold on a keeper-hosted session without touching the adapter: the loop stops after the
78
- * record in hand, a head checkpoint is cut when the state is safe (never mid Qoder chunk or load history — then the next daemon
79
- * replays), the subscription is dropped. No `session/cancel`, no answer to a pending card, no `turn_done(failed)`: a detaching
80
- * session never degrades. The next daemon adopts it.
81
- *
82
- * ## Keeper connection loss (Task 21)
83
- *
84
- * keeper-acp unreachable under the loop (a request lost on a dropped connection, a stream that ended) is not a degradation: the
85
- * session re-attaches — `acp.attach` (which relaunches the current generation's keeper-acp if it died; an older generation is
86
- * only reconnected) and the same rebuild as an adoption, in place — with bounded retries. A note whose append failed is looked
87
- * for in raw before it is appended again. Only a keeper that is gone with the session (not found, or unreachable after the
88
- * retries) degrades it. When keeper-acp itself restarted, the session it recovered ends with `proc exit{reason:'keeper_lost'}`:
89
- * that tail is folded (a real `turn_done` in it is delivered) and the session reports its adapter dead.
90
- */
1
+ /** Daemon-side keeper session: records notes before commands, awaits outbox persistence before advancing, and checkpoints only complete history boundaries. A poisoned processor degrades the session and ends pending turns; it never retries half-updated state. */
91
2
  import { PROTOCOL_VERSION, RequestError } from '@agentclientprotocol/sdk';
92
3
  import { ACCOUNT_LIMITS_READ_TIMEOUT_MS } from '../protocol/accountLimits.js';
93
- import { BackgroundSideNotes, nativeTerminalHistoryPath } from '../qoderAdapter/backgroundTerminal.js';
94
4
  import { AgentInitializeTimeoutError, AgentSpawnError, UnsupportedProtocolVersionError } from './acpClient.js';
95
5
  import { executeDownCommandsVia } from './processor/transport/types.js';
96
6
  import { createProcessor, ProcessorPoisonedError, restoreProcessor } from './processor/step.js';
@@ -98,21 +8,18 @@ import { checkpointOf, decodeCheckpoint, encodeCheckpoint, PROCESSOR_VERSION } f
98
8
  import { DAEMON_FRAME_INDEX, isOutboxTail, SessionOutbox, transportOutboxStore } from './outbox.js';
99
9
  import { initialState } from './processor/state.js';
100
10
  import { activityRaw, runtimeDiagnostics } from './processor/runtime.js';
101
- import { sideDemand } from './processor/sideChannel.js';
102
- import { unfinishedAsyncTasks } from './processor/updates.js';
11
+ import { unfinishedAsyncTasks, unfinishedDraftSubagentCount } from './processor/updates.js';
103
12
  import { pendingRequestIds } from './processor/session.js';
104
13
  import { steeredIds } from './processor/control.js';
105
14
  import { RawTruncatedError } from './processor/transport/types.js';
106
- import { REPAIR_NOTE } from '../qoderAdapter/backgroundTerminalFold.js';
107
15
  import { AcpKeeperUnavailableError } from '../keepers/acp/client.js';
16
+ import { RegistrationOwnershipError } from '../runtime/ownership.js';
108
17
  import { AcpErrorCode } from '../keepers/acp/protocol.js';
109
18
  import { KeeperClosedError, KeeperConnectionLostError, KeeperNotConnectedError, KeeperRequestError, KeeperRequestTimeoutError, } from '../keepers/kit/client.js';
110
19
  /** What the executor reports when a prompt's blocks are no longer in this daemon's memory (interface-contracts). */
111
20
  export const PROMPT_LOST = 'The prompt was lost before it reached the agent';
112
21
  /** The error a turn ends with when the session degrades under it (poison, or a transport that failed under the loop). */
113
22
  export const SESSION_DEGRADED = 'The agent session failed and was stopped; reopen it to continue';
114
- /** How often the Qoder side-file reader polls (the live repair's timer). */
115
- const SIDE_POLL_MS = 1_000;
116
23
  /** stderr kept for a startup failure's message (the `err` records the processor ignores). */
117
24
  const STDERR_TAIL_BYTES = 8_192;
118
25
  /** Within a turn, a checkpoint every this many bytes of folded raw (spec §5.5, §14). */
@@ -210,7 +117,6 @@ export class ProcessorSession {
210
117
  openResult;
211
118
  historyEnd;
212
119
  history = [];
213
- side;
214
120
  /** The record loop's tail: notes it appends are serialised behind it. */
215
121
  chain = Promise.resolve();
216
122
  /** The loop is held at a record boundary for a switch ({@link suspend}); `release` lets it go on. */
@@ -252,7 +158,7 @@ export class ProcessorSession {
252
158
  }
253
159
  catch (error) {
254
160
  // keeper-acp unreachable is not a launch failure: the caller falls back to the local transport.
255
- if (error instanceof AcpKeeperUnavailableError)
161
+ if (error instanceof AcpKeeperUnavailableError || error instanceof RegistrationOwnershipError)
256
162
  throw error;
257
163
  throw spawnFailure(options.spawn.command, error);
258
164
  }
@@ -262,11 +168,12 @@ export class ProcessorSession {
262
168
  // resent when the server reopens the ref, and numbering continues after the highest seq the outbox ever held.
263
169
  const attached = await transport.attach(sessionKey);
264
170
  let leftovers = await readOutboxTail(transport, sessionKey, attached.outbox);
265
- if (seed && seed.imports.length > 0) {
171
+ const imports = (seed?.imports ?? options.imports ?? []).filter((entry) => entry.seq > (attached.outbox?.lastSeq ?? 0));
172
+ if (imports.length > 0) {
266
173
  // A switch's successor (Task 24): the predecessor's unacknowledged frames land here before anything this session numbers —
267
174
  // the predecessor is released only after this append returned (never the other way round: the frames would be nowhere).
268
175
  const at = Math.max(spawned.o - 1, 0);
269
- const entries = seed.imports.map((entry, k) => ({ seq: entry.seq, src: { o: at, i: DAEMON_FRAME_INDEX + k }, frame: { ...entry.frame } }));
176
+ const entries = imports.map((entry, index) => ({ seq: entry.seq, src: { o: at, i: DAEMON_FRAME_INDEX + index }, frame: { ...entry.frame } }));
270
177
  const { first } = await transport.appendOutbox(sessionKey, entries);
271
178
  leftovers = [...leftovers, ...entries.map((entry, k) => ({ o: first + k, t: Date.now(), ...entry }))];
272
179
  }
@@ -552,14 +459,9 @@ export class ProcessorSession {
552
459
  if (this.checkpointDue && this.checkpointSafe())
553
460
  this.cutCheckpoint();
554
461
  }
555
- /**
556
- * A checkpoint must let a replay continue from it alone: not while a chunked Qoder fact is half-read (`sideChunk`, its first
557
- * chunks would be truncated away) nor inside a load's history window (history is never journaled: a daemon that dies in the
558
- * window loads again — interface-contracts, T19).
559
- */
560
462
  checkpointSafe() {
561
463
  const state = this.processor.state;
562
- return state.offset >= 0 && state.offset <= this.recordedThrough && state.boundaries.sideChunk === null && state.history === null &&
464
+ return state.offset >= 0 && state.offset <= this.recordedThrough && state.history === null &&
563
465
  this.processor.poisoned === undefined;
564
466
  }
565
467
  /** Snapshot now (a record boundary: the loop is between records) and commit it with raw truncated through it (not a marker's). */
@@ -644,7 +546,7 @@ export class ProcessorSession {
644
546
  /** Async tasks / background work the adapter still runs for this session (processor state): a switch would kill them. */
645
547
  get liveBackgroundWork() {
646
548
  const state = this.processor.state;
647
- return unfinishedAsyncTasks(state).length + (sideDemand(state)?.active() ? 1 : 0);
549
+ return unfinishedAsyncTasks(state).length + unfinishedDraftSubagentCount(state);
648
550
  }
649
551
  /** The adapter's exit, once it has one: the spawn it ended and why (keeper-acp's `reason`, absent for an exit of its own). */
650
552
  get adapterExit() {
@@ -674,6 +576,9 @@ export class ProcessorSession {
674
576
  this.history.push(event);
675
577
  }
676
578
  continue;
579
+ case 'processor.closed_replay_level':
580
+ this.log(`[acp] session ${this.key}: ignored ${String(frame.sessionUpdate)} for ended replay scope ${JSON.stringify(frame.sessionId)}`);
581
+ continue;
677
582
  case 'processor.history_end': {
678
583
  const droppedCount = typeof frame.droppedCount === 'number' ? frame.droppedCount : 0;
679
584
  this.historyEnd = { ok: frame.ok === true, droppedCount };
@@ -945,7 +850,6 @@ export class ProcessorSession {
945
850
  for (const [, reply] of this.pendingReplies)
946
851
  reply({ ok: false, error: reason });
947
852
  this.pendingReplies.clear();
948
- this.stopSide();
949
853
  void this.transport.terminate(this.key).catch(() => null);
950
854
  try {
951
855
  this.options.onDegrade?.(this.headSeq);
@@ -1010,20 +914,8 @@ export class ProcessorSession {
1010
914
  ...(request.sessionId !== undefined ? { sessionId: request.sessionId } : {}),
1011
915
  mcpServers: request.mcpServers,
1012
916
  ...(request.redact && request.redact.length > 0 ? { redact: [...request.redact] } : {}),
1013
- ...(request.delegation ? { delegation: request.delegation } : {}),
1014
917
  };
1015
- const repair = request.mode === 'load' ? request.repair : undefined;
1016
- if (repair) {
1017
- // The repair note must follow the open note before the loop folds the open note (and so writes the `session/load` line
1018
- // the history answers): the loop is held while both are appended.
1019
- await this.holdingLoop(async () => {
1020
- await this.send(note);
1021
- await this.enableRepair(request.sessionId, request.cwd, repair.historyHome);
1022
- });
1023
- }
1024
- else {
1025
- await this.send(note);
1026
- }
918
+ await this.send(note);
1027
919
  return this.waitFor(() => this.openResult);
1028
920
  }
1029
921
  /** Runs `work` (appends only — never a wait on the loop) with the record loop held, so no record is folded meanwhile. */
@@ -1044,55 +936,6 @@ export class ProcessorSession {
1044
936
  await this.send({ type: 'historyEnd' });
1045
937
  return this.waitFor(() => this.historyEnd);
1046
938
  }
1047
- /**
1048
- * Turn the Qoder background terminal repair on (17c): the `qoder_terminal_repair` note, then the side-file reader. Nothing for a
1049
- * runtime the repair does not certify (no history path).
1050
- */
1051
- async enableRepair(nativeSessionId, cwd, historyHome, restoreCalls = false) {
1052
- const path = nativeTerminalHistoryPath(this.agentInfo, nativeSessionId, cwd, historyHome);
1053
- if (!path || this.side?.nativeSessionId === nativeSessionId)
1054
- return;
1055
- // A load that failed and fell back to `session/new`: the processor closed the load's repair (`settleOpen`); its reader goes
1056
- // too, and the new session gets its own (the old path closed the attached session and opened a fresh one).
1057
- this.stopSide();
1058
- const from = await this.appendNote({ type: REPAIR_NOTE, nativeSessionId, ...(restoreCalls ? { restoreCalls: true } : {}) });
1059
- const reader = new BackgroundSideNotes({ path, nativeSessionId, cwd, restoreCalls });
1060
- const timer = setInterval(() => { void this.pollSide(); }, SIDE_POLL_MS);
1061
- timer.unref();
1062
- this.side = { reader, timer, from, polling: false, nativeSessionId };
1063
- }
1064
- async pollSide() {
1065
- const side = this.side;
1066
- if (!side || side.polling || this.degraded !== undefined || this.closing)
1067
- return;
1068
- // The demand is the processor's *current* state, so only once it has folded everything this object appended.
1069
- if (this.processor.state.offset < Math.max(side.from, this.appended))
1070
- return;
1071
- const demand = sideDemand(this.processor.state);
1072
- if (!demand) {
1073
- this.stopSide();
1074
- return;
1075
- }
1076
- side.polling = true;
1077
- try {
1078
- const notes = await side.reader.poll(demand);
1079
- for (const note of notes)
1080
- await this.appendNote(note);
1081
- }
1082
- catch (error) {
1083
- this.log(`[acp] session ${this.key}: background terminal read failed: ${error instanceof Error ? error.message : String(error)}`);
1084
- }
1085
- finally {
1086
- side.polling = false;
1087
- }
1088
- }
1089
- stopSide() {
1090
- if (!this.side)
1091
- return;
1092
- clearInterval(this.side.timer);
1093
- this.side.reader.close();
1094
- this.side = undefined;
1095
- }
1096
939
  // ---- AcpAgentSession ----------------------------------------------------------------------------------------------------
1097
940
  get facts() {
1098
941
  const initialize = this.processor.state.initialize;
@@ -1108,7 +951,6 @@ export class ProcessorSession {
1108
951
  get configOptions() { return this.processor.state.configOptions ?? []; }
1109
952
  get runtimeDiagnostics() { return runtimeDiagnostics(this.processor.state); }
1110
953
  get activityRaw() { return activityRaw(this.processor.state); }
1111
- get delegation() { return this.processor.state.delegation ?? null; }
1112
954
  get nativeSessionId() {
1113
955
  const root = this.processor.state.rootSessionId;
1114
956
  return root !== null && root.length > 0 ? root : null;
@@ -1177,6 +1019,13 @@ export class ProcessorSession {
1177
1019
  async steer(blocks, priority, id) {
1178
1020
  if (this.pendingReplies.has(`agent_steered:${id}`))
1179
1021
  throw new Error(`A steer with id '${id}' is already in flight`);
1022
+ // A full producing window stops the raw loop, including control notes. Appending here
1023
+ // would leave a steer that can execute long after the server's RPC timed out. Refuse
1024
+ // before recording anything: promptRequired proves this attempt cannot inject later.
1025
+ if (!this.outbox.hasRoom()) {
1026
+ this.log(`[acp] session ${this.key}: steer ${id} not admitted while awaiting event acknowledgements`);
1027
+ return 'promptRequired';
1028
+ }
1180
1029
  const answered = this.reply('agent_steered', id);
1181
1030
  await this.send({ type: 'agent_steer', id, blocksRef: this.holdBlocks(blocks), ...(priority !== undefined ? { priority } : {}) })
1182
1031
  .catch((error) => { this.pendingReplies.delete(`agent_steered:${id}`); throw error; });
@@ -1283,7 +1132,6 @@ export class ProcessorSession {
1283
1132
  this.resume();
1284
1133
  this.detached = true;
1285
1134
  this.unlisten();
1286
- this.stopSide();
1287
1135
  for (const waiter of [...this.waiters])
1288
1136
  waiter.reject(new Error('The agent session was handed to the next daemon'));
1289
1137
  // A loop waiting for room stops (it sees `closing`); the head checkpoint is cut at the record boundary after it.
@@ -1307,7 +1155,6 @@ export class ProcessorSession {
1307
1155
  this.closing ??= (async () => {
1308
1156
  this.resume(); // a held loop drains (every fold sees `closing`)
1309
1157
  this.unlisten();
1310
- this.stopSide();
1311
1158
  for (const waiter of [...this.waiters])
1312
1159
  waiter.reject(new Error('The agent session is closed'));
1313
1160
  for (const [, reply] of this.pendingReplies)
@@ -44,10 +44,10 @@
44
44
  *
45
45
  * 这里写下的来源**整个替换** registry 的 `version` 与 `distribution`,id 与展示名仍是 registry 的,
46
46
  * 于是已有的配置条目、roster、安装、启动、更新都不用知道发生过替换(见 {@link withCatalogOverrides})。
47
- * 本文件的 distribution 用于长期策略;Qoder 等临时的钉版本放在
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
  *
@@ -86,13 +86,13 @@ export const AXOM_AGENT_CATALOG = [
86
86
  defaultName: 'claude-agent',
87
87
  defaultLabel: 'Claude Agent',
88
88
  detect: { commands: ['claude'] },
89
- // 钉版本的唯一理由是补丁:claude-account-limits 的配方只核验过 0.90.0(runtime.json 的
89
+ // 钉版本的唯一理由是补丁:账号配额与 replay lifecycle 配方只核验过 0.97.0(runtime.json 的
90
90
  // package_patches)。不钉的话 registry 一发新版,Install/Update 就装上一个配方不覆盖的包,
91
91
  // 账号配额扩展静默消失——2026-10-14 的 antigravity(registry 已到 1.4.0、native extension
92
92
  // 只认 1.3.0)就是这个缺口的实例。钉住后 scan 的 Update 比对(installedVersion vs 本清单的
93
93
  // version)只在落后于钉住版本时才成立,上游新版要等 nightly 核验移植配方后再 bump。
94
- // 周期核验步骤见 axom-patch/cli/nightly-task.md。
95
- distribution: { version: '0.90.0', npx: { package: '@agentclientprotocol/claude-agent-acp@0.90.0' } },
94
+ // 周期核验步骤见 axom-patch/DAILY_UPGRADE_CHECK.md。
95
+ distribution: { version: '0.97.0', npx: { package: '@agentclientprotocol/claude-agent-acp@0.97.0' } },
96
96
  launchEnv: {
97
97
  // Axom 拉起的 Claude Code——会话进程、配额读的 /usage、auth status 探针、terminalLogin 代跑的
98
98
  // `--cli auth login`——一律使用独立的 OAuth 凭据槽,与用户终端 `claude login` 写进默认槽
@@ -116,16 +116,18 @@ export const AXOM_AGENT_CATALOG = [
116
116
  defaultName: 'codex',
117
117
  defaultLabel: 'Codex',
118
118
  detect: { commands: ['codex'] },
119
- // 与 claude-acp 同一条规则:codex-account-limits 只核验过 2.2.2,钉住直到配方随新版本移植。
120
- distribution: { version: '2.2.2', npx: { package: '@agentclientprotocol/codex-acp@2.2.2' } },
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' } },
121
122
  },
122
123
  {
123
124
  registryAgent: 'qoder',
124
125
  defaultName: 'qoder',
125
126
  defaultLabel: 'Qoder',
126
127
  detect: { commands: ['qodercli'] },
127
- // The temporary registry catch-up pin lives in axom-patch/cli/runtime.json so a newer
128
- // upstream release can take over without another Axom release.
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'] } },
129
131
  },
130
132
  // `gemini` was here and is deliberately gone. `@google/gemini-cli --acp` now refuses `session/new`
131
133
  // outright ("This client is no longer supported for Gemini Code Assist for individuals … migrate
@@ -144,7 +146,7 @@ export const AXOM_AGENT_CATALOG = [
144
146
  // 其余字段照 registry#458 的条目写。
145
147
  supplement: {
146
148
  name: 'Kimi Code',
147
- version: '2.1.1',
149
+ version: '2.3.3',
148
150
  description: "Moonshot AI's next-gen coding agent",
149
151
  repository: 'https://github.com/MoonshotAI/kimi-code',
150
152
  website: 'https://moonshotai.github.io/kimi-code/',
@@ -152,13 +154,13 @@ export const AXOM_AGENT_CATALOG = [
152
154
  license: 'MIT',
153
155
  icon: 'https://cdn.agentclientprotocol.com/registry/v1/latest/kimi.svg',
154
156
  distribution: {
155
- binary: kimiCodeBinary('2.1.1', {
156
- 'darwin-aarch64': ['darwin-arm64', '8c3bad99571b16abd113ab5d511a98a36b852c0d5493991842a67b8c2bc4ecd0'],
157
- 'darwin-x86_64': ['darwin-x64', 'f6dc0289112c24119d070f9203d44bcd53580e380819db25b58be65643b75bd4'],
158
- 'linux-aarch64': ['linux-arm64', '5c68d74b139b47fb3457f3805a159cdfa942a6a98a159ab158a1baf93b024bbd'],
159
- 'linux-x86_64': ['linux-x64', 'b66cc3787bc9dfa6a06761305dc8878f98e7a24f79fa4494c00714229a1486e8'],
160
- 'windows-aarch64': ['win32-arm64', '72bb17fef0d165a5f61905ede7e57c552791905d605a778967d054fe702873d4'],
161
- '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'],
162
164
  }),
163
165
  },
164
166
  },
@@ -173,21 +175,20 @@ export const AXOM_AGENT_CATALOG = [
173
175
  registryAgent: 'command-code',
174
176
  defaultName: 'command-code',
175
177
  defaultLabel: 'Command Code',
176
- // registry 没有它。1.66.0 还没有 `acp` 子命令,1.74.3 起有、真机试跑通过;2026-10-14 nightly
177
- // 升到 1.82.1:`acp` 子命令仍在(四个 bin 不变),commandcode-account-limits 配方已随
178
- // generate.py 移植(handler map 换了名字 u/dn→m/hn,锚点已跟)。包里有 `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`、
179
180
  // `commandcode`、`command-code` 四个 bin,npx 挑与包名同名的那个。没有 ACP 登录方法,只有一句
180
181
  // 说明(终端里跑 `cmd login`);凭据在 `~/.commandcode`,与用户自己装的那份共用。npm 上的许可证
181
182
  // 写的是 UNLICENSED(专有)。
182
183
  supplement: {
183
184
  name: 'Command Code',
184
- version: '1.82.1',
185
+ version: '1.88.0',
185
186
  description: 'Command Code, coding agent that continuously learns your coding taste.',
186
187
  website: 'https://commandcode.ai',
187
188
  authors: ['Command Code'],
188
189
  license: 'UNLICENSED',
189
190
  icon: 'https://commandcode.ai/favicon.ico',
190
- distribution: { npx: { package: 'command-code@1.82.1', args: ['acp'] } },
191
+ distribution: { npx: { package: 'command-code@1.88.0', args: ['acp'] } },
191
192
  },
192
193
  detect: { commands: ['command-code', 'commandcode'] },
193
194
  },
@@ -203,19 +204,19 @@ export const AXOM_AGENT_CATALOG = [
203
204
  // 2026-10-13 真机验证(ZCode 桌面 3.14.5 + 0.69.3):initialize → session/new → 首轮 prompt 通过,
204
205
  // 日志 "serving the coding-plan API key (config.json or store)"。0.63/0.64 那轮不兼容(模型只剩
205
206
  // 无授权的 builtin:bigmodel-coding-plan\GLM-5.3,首轮 CONFIGURATION_ERROR "Model creation failed",
206
- // 2026-10-06 两台机器复现)自 0.68.1 起修复。2026-10-14 nightly 升到 0.69.4:三份配方的目标文件
207
- // 与 0.69.3 字节一致(配方 versions 同时覆盖两版),subagent 探针在 0.69.4 补丁副本上通过、
208
- // pristine 证实上游仍未原生发出 subagent/async 变体。
207
+ // 2026-10-06 两台机器复现)自 0.68.1 起修复。2026-10-29 升到 0.80.0:迁移配额、模型兜底、
208
+ // subagent/async 补丁;env 账号包装复用上游 bridge-accounts(不写桌面配置)。
209
+ // ZCODE_PROVIDER + ZCODE_API_KEY 支持独立个人 Coding Plan,无需复用桌面 OAuth。
209
210
  supplement: {
210
211
  name: 'ZCode',
211
- version: '0.69.4',
212
+ version: '0.80.0',
212
213
  description: 'Community bridge that drives the real ZCode app-server (GLM) over ACP.',
213
214
  repository: 'https://github.com/william0wang/zcode-acp',
214
215
  website: 'https://github.com/william0wang/zcode-acp',
215
216
  authors: ['William Wang'],
216
217
  license: 'Apache-2.0',
217
218
  icon: 'https://raw.githubusercontent.com/william0wang/zcode-acp/main/registry/zcode-acp/icon.svg',
218
- distribution: { npx: { package: 'zcode-acp-server@0.69.4' } },
219
+ distribution: { npx: { package: 'zcode-acp-server@0.80.0' } },
219
220
  },
220
221
  prerequisite: {
221
222
  label: 'ZCode',
@@ -238,7 +239,7 @@ export const AXOM_AGENT_CATALOG = [
238
239
  recommended: true,
239
240
  // pi-steering 与 pi-subagent-subwork 两份配方只核验过 0.0.34。registry 今天也在 0.0.34,
240
241
  // 但那是巧合而不是保护:上游一发 0.0.35,未钉版本的 Install 就会装上一个 steering/子代理
241
- // 归一都不生效的包。钉住后版本只随配方移植走(nightly-task.md)。
242
+ // 归一都不生效的包。钉住后版本只随配方移植走(DAILY_UPGRADE_CHECK.md)。
242
243
  distribution: { version: '0.0.34', npx: { package: 'pi-acp@0.0.34' } },
243
244
  prerequisite: {
244
245
  label: 'Pi',
@@ -287,27 +288,52 @@ export const AXOM_AGENT_CATALOG = [
287
288
  // registry 自己的条目(binary .par),我们只补名字与本机检测;`agy` 是 Antigravity 装好后放进 PATH 的命令。
288
289
  // distribution 钉住:antigravity 的账号配额靠 native extension(runtime.json
289
290
  // native_extensions,account-limits/antigravity-proxy.mjs),proxy 是 stdio sidecar,只在核验过的
290
- // 版本上声明能力。2026-10-14 nightly 升到 1.4.0:真实 1.4.0 .par 经 proxy 拉起,initialize 透传无损、
291
- // `axom/accountRateLimits` 能力注入成功(本地实测;配额 READ 属于用户凭据路径,留给真机冒烟)。
292
- // 归档 URL 抄自 registry 的 1.4.0 条目;registry 本身不给这个条目发 sha256,这里同样不发,校验语义与
293
- // registry 直装一致(binaryInstall:无 sha256 即不校验)。上游发新版时按 nightly-task.md 核验后同升。
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 核验后同升。
294
295
  {
295
296
  registryAgent: 'antigravity-acp',
296
297
  defaultName: 'google-antigravity',
297
298
  defaultLabel: 'Google Antigravity',
298
299
  detect: { commands: ['agy'] },
299
300
  distribution: {
300
- version: '1.4.0',
301
+ version: '1.4.3',
301
302
  binary: {
302
- 'darwin-aarch64': { archive: 'https://dl.google.com/agy-extensions/releases/macos/agy-acp-server-1.4.0-darwin-arm64.zip', cmd: './agy_acp_server.par' },
303
- 'darwin-x86_64': { archive: 'https://dl.google.com/agy-extensions/releases/macos/agy-acp-server-1.4.0-darwin-x86_64.zip', cmd: './agy_acp_server.par' },
304
- 'linux-x86_64': { archive: 'https://dl.google.com/agy-extensions/releases/linux/agy-acp-server-1.4.0-linux-x86_64.zip', cmd: './agy_acp_server.par', args: ['--uid='] },
305
- 'linux-aarch64': { archive: 'https://dl.google.com/agy-extensions/releases/linux/agy-acp-server-1.4.0-linux-arm64.zip', cmd: './agy_acp_server.par', args: ['--uid='] },
306
- 'windows-x86_64': { archive: 'https://dl.google.com/agy-extensions/releases/windows/agy-acp-server-1.4.0-windows-x86_64.zip', cmd: './agy_acp_server.exe' },
307
- 'windows-aarch64': { archive: 'https://dl.google.com/agy-extensions/releases/windows/agy-acp-server-1.4.0-windows-arm64.zip', cmd: './agy_acp_server.exe' },
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' },
308
309
  },
309
310
  },
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
+ },
311
337
  ];
312
338
  /**
313
339
  * Kimi Code 的六个平台归档:GitHub release `@moonshot-ai/kimi-code@<version>` 下的
@@ -1,7 +1,9 @@
1
1
  import { existsSync } from 'node:fs';
2
2
  import { homedir } from 'node:os';
3
3
  import path from 'node:path';
4
+ import semver from 'semver';
4
5
  import { fileURLToPath } from 'node:url';
6
+ import { managedRuntimeFor, verifyManagedRuntime, verifyRecordedManagedRuntime } from '../managedRuntime.js';
5
7
  import { nativeExtensionFor } from '../patchAssets.js';
6
8
  import { verifyPatchedFiles } from '../managedPatches.js';
7
9
  import { AdapterNotInstalledError, inside, labelFor } from '../builds/model.js';
@@ -45,10 +47,23 @@ function expandHomeInEnv(env) {
45
47
  return Object.fromEntries(Object.entries(env).map(([key, value]) => [key, value === '~' ? home : value.startsWith('~/') ? path.join(home, value.slice(2)) : value]));
46
48
  }
47
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.
48
60
  const dir = inside(root, build.dir);
49
61
  const entry = inside(dir, build.launch.entry);
50
62
  if (build.kind === 'npm-patched' && build.package && build.patchedFiles) {
51
- await verifyPatchedFiles(inside(path.join(dir, 'node_modules'), 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);
52
67
  }
53
68
  if (!existsSync(entry))
54
69
  throw new AdapterNotInstalledError(build.agentId, `build ${build.buildId} is missing its executable`);
@@ -62,7 +62,6 @@ const PLAIN_BLOCKERS = {
62
62
  'a permission or elicitation is unanswered': 'it is waiting for an answer',
63
63
  'the agent reports it is active': 'the agent says it is still working',
64
64
  'an async task or background terminal is still running': 'it has a background task or terminal still running',
65
- 'a delegation refresh is pending': 'its delegated access is being renewed',
66
65
  };
67
66
  /** Why a session may not be switched now (spec §6.3 step 2); empty = strictly idle. */
68
67
  export function switchBlockers(input) {
@@ -83,8 +82,6 @@ export function switchBlockers(input) {
83
82
  blockers.push('the agent reports it is active');
84
83
  if ((session.liveBackgroundWork ?? 0) > 0)
85
84
  blockers.push('an async task or background terminal is still running');
86
- if (session.delegation?.refreshPending)
87
- blockers.push('a delegation refresh is pending');
88
85
  const quiet = input.quietMs ?? SWITCH_QUIET_MS;
89
86
  const last = Math.max(input.lastActivityAt, session.lastFoldAt ?? 0);
90
87
  if (input.now - last < quiet)
@@ -113,6 +113,12 @@
113
113
  // // with this message instead of succeeding — lets a
114
114
  // // test prove a real agent-side rejection surfaces as
115
115
  // // a rejected promise
116
+ // authenticateNotifications?: Array<{method: string, params: unknown}>,
117
+ // // sent as client notifications at the top of the
118
+ // // `authenticate` handler, before anything else —
119
+ // // models an agent that pushes a login URL as an
120
+ // // extension notification (`_codebuddy.ai/authUrl`)
121
+ // // rather than eliciting or printing it
116
122
  // hangOnAuthenticate?: boolean, // if true, `authenticate` never resolves — the shape
117
123
  // // measured on a real agent that opens a browser and
118
124
  // // waits for its callback (spec §6.2: antigravity's
@@ -348,6 +354,13 @@ async function main() {
348
354
  writeFileSync(config.authenticateSink, JSON.stringify(ctx.params));
349
355
  if (config.authenticateRejectsWith)
350
356
  throw new Error(config.authenticateRejectsWith);
357
+ // Extension notifications an agent pushes while answering `authenticate` (measured on the real
358
+ // CodeBuddy adapter: `_codebuddy.ai/authUrl` with `{authUrl, provider}` — a URL channel that
359
+ // is neither `elicitation/create` nor stderr). Sent before the reply, so a client that only
360
+ // listens from the reply onward still misses them, exactly like the real one.
361
+ for (const { method, params } of config.authenticateNotifications ?? []) {
362
+ await ctx.client.notify(method, params);
363
+ }
351
364
  if (config.createElicitationDuringAuthenticate) {
352
365
  // `requestId` is filled in here rather than in the config: a login elicitation is
353
366
  // request-scoped (ACP's `ElicitationRequestScope` — "tied to a specific JSON-RPC request