@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
@@ -0,0 +1,390 @@
1
+ /** Session updates map in log order. Root chunks track streaming message boundaries; diverted and child updates retain their session address. Both feed the permission-origin graph and unfinished async-task state. Load history uses separate mapper scopes and emits unnumbered backfill events. */
2
+ import { DRAFT_SESSION_UPDATE_NAMES } from '../draftSubagents.js';
3
+ import { mapSessionUpdate, newMapperScopeData, SessionMapperState } from '../sessionUpdateMapper.js';
4
+ import { validateWireEvent } from '../validate.js';
5
+ import { emitEvent, isRecord } from './emit.js';
6
+ import { observeSubagentSpawned } from './origins.js';
7
+ import { reportActivity } from './runtime.js';
8
+ import { INBOUND_NOTIFICATION_SCHEMAS } from './sdkSchemas.js';
9
+ import { ASYNC_TASK_LIMIT, getOwn, putOwn } from './state.js';
10
+ const DRAFT_NAMES = new Set(DRAFT_SESSION_UPDATE_NAMES);
11
+ /**
12
+ * Updates that state what the session **is now** (its command table, mode, config, usage, info), not what happened in it (Task 21).
13
+ * One the loaded session sends after the load's response — the root is bound — but before the daemon's `historyEnd` is not history:
14
+ * it is folded live (numbered), or a reopened session would never show its command table (Claude sends `available_commands_update`
15
+ * from a timer right after answering `session/load`). Before the response such an update is part of the replay and stays history.
16
+ */
17
+ const LEVEL_UPDATES = new Set([
18
+ 'available_commands_update', 'current_mode_update', 'config_option_update', 'usage_update', 'session_info_update',
19
+ ]);
20
+ const SESSION_NOTIFICATION = INBOUND_NOTIFICATION_SCHEMAS['session/update'];
21
+ function stringField(payload, key) {
22
+ const value = payload[key];
23
+ return typeof value === 'string' ? value : null;
24
+ }
25
+ /** The mapper for `nativeSessionId`, over the checkpointed scope data (created on first use). */
26
+ function liveMapper(state, out, nativeSessionId, t) {
27
+ let data = getOwn(state.mapperScopes, nativeSessionId);
28
+ if (!data)
29
+ putOwn(state.mapperScopes, nativeSessionId, data = newMapperScopeData());
30
+ // Codex's activity rides the root's own `session_info_update` (`AcpSession.scopes`' callback).
31
+ return new SessionMapperState((raw) => {
32
+ if (nativeSessionId === state.rootSessionId)
33
+ reportActivity(state, out, raw, t);
34
+ }, data);
35
+ }
36
+ /** An inbound `session/update` notification (params not yet validated). */
37
+ export function onSessionUpdate(state, params, out, t) {
38
+ if (!isRecord(params) || typeof params.sessionId !== 'string' || params.sessionId.length === 0 || !isRecord(params.update)) {
39
+ state.diagnostics.droppedUpdates += 1;
40
+ return;
41
+ }
42
+ const { sessionId, update } = params;
43
+ if (state.history && !(LEVEL_UPDATES.has(String(update.sessionUpdate)) && state.rootSessionId !== null && sessionId === state.rootSessionId)) {
44
+ onHistoryUpdate(state, state.history, sessionId, update, out);
45
+ return;
46
+ }
47
+ const root = state.rootSessionId;
48
+ if (root === null) {
49
+ state.diagnostics.droppedUpdates += 1;
50
+ return;
51
+ }
52
+ const variant = update.sessionUpdate;
53
+ const draft = typeof variant === 'string' && DRAFT_NAMES.has(variant);
54
+ if (!draft && sessionId === root) {
55
+ const parsed = SESSION_NOTIFICATION.safeParse(params);
56
+ if (!parsed.success) {
57
+ state.diagnostics.droppedUpdates += 1;
58
+ return;
59
+ }
60
+ const stripped = parsed.data.update;
61
+ for (const event of mapSessionUpdate(stripped, liveMapper(state, out, root, t)))
62
+ routeOwnEvent(state, out, event);
63
+ return;
64
+ }
65
+ let events;
66
+ try {
67
+ events = mapSessionUpdate(update, liveMapper(state, out, sessionId, t));
68
+ }
69
+ catch {
70
+ // `applyDivertedUpdate`: an unmapped variant on a diverted update is dropped, the session lives on.
71
+ state.diagnostics.droppedUpdates += 1;
72
+ return;
73
+ }
74
+ for (const event of events)
75
+ emitSessionEvent(state, out, sessionId === root ? event : { ...event, acpSessionId: sessionId });
76
+ }
77
+ const CHUNK_CHURN = new WeakMap();
78
+ const CHUNK_TICKS = new WeakMap();
79
+ const canonical = (value) => { try {
80
+ return JSON.stringify(value) ?? 'undefined';
81
+ }
82
+ catch {
83
+ return 'unserializable';
84
+ } };
85
+ const isVolatileMetaKey = (key) => key === 'timestamp' || key.endsWith('.timestamp') || key.endsWith('_timestamp');
86
+ /** Every event through the live/history entry points ticks once; a tracker whose last chunk is not the immediately
87
+ * preceding event starts fresh. A tool call or any other update between two chunks therefore keeps their ids
88
+ * meaningful — which also matches the server, where an unrelated event already flushes the pending text. */
89
+ function tickEvent(state) {
90
+ const ticks = CHUNK_TICKS.get(state) ?? { tick: 0 };
91
+ ticks.tick += 1;
92
+ CHUNK_TICKS.set(state, ticks);
93
+ return ticks.tick;
94
+ }
95
+ function churnStateOf(state, key, tick) {
96
+ let perState = CHUNK_CHURN.get(state);
97
+ if (!perState)
98
+ CHUNK_CHURN.set(state, perState = new Map());
99
+ const fresh = state.turns.length;
100
+ let churn = perState.get(key);
101
+ if (!churn || churn.seenTurns !== fresh || churn.lastTick !== tick - 1)
102
+ perState.set(key, churn = { prevId: null, anchorId: null, trusted: false, prevMeta: null, anchorMeta: {}, churnyMetaKeys: new Set(), trustedMetaKeys: new Set(), seenTurns: fresh, lastTick: tick });
103
+ churn.lastTick = tick;
104
+ return churn;
105
+ }
106
+ /** Absorb per-delta id/meta churn on one assistant chunk (see the block comment above); other events pass through. */
107
+ function absorbAssistantChunkChurn(state, tick, event) {
108
+ if (event.eventName !== 'agent_message_chunk' && event.eventName !== 'agent_thought_chunk')
109
+ return event;
110
+ const payload = event.payload;
111
+ const churn = churnStateOf(state, `${event.acpSessionId ?? 'root'}:${event.eventName}`, tick);
112
+ let changed = false;
113
+ const rawId = typeof payload.messageId === 'string' ? payload.messageId : null;
114
+ if (rawId !== null) {
115
+ if (churn.prevId !== null && rawId === churn.prevId)
116
+ churn.trusted = true;
117
+ if (churn.trusted) {
118
+ churn.anchorId = rawId;
119
+ }
120
+ else if (churn.prevId !== null) {
121
+ // A change with no stable pair ever seen: churn — keep the anchor.
122
+ if (churn.anchorId !== null && churn.anchorId !== rawId) {
123
+ payload.messageId = churn.anchorId;
124
+ changed = true;
125
+ }
126
+ }
127
+ else {
128
+ churn.anchorId = rawId;
129
+ }
130
+ churn.prevId = rawId;
131
+ }
132
+ const rawMeta = payload._meta;
133
+ if (rawMeta !== null && typeof rawMeta === 'object') {
134
+ const meta = rawMeta;
135
+ const emitted = {};
136
+ let anchored = false;
137
+ for (const [key, value] of Object.entries(meta)) {
138
+ if (!isVolatileMetaKey(key)) {
139
+ emitted[key] = value;
140
+ continue;
141
+ }
142
+ const previous = churn.prevMeta;
143
+ if (previous !== null && key in previous) {
144
+ if (canonical(value) === canonical(previous[key]))
145
+ churn.trustedMetaKeys.add(key);
146
+ else if (!churn.trustedMetaKeys.has(key)) {
147
+ // First sighting of a change on a never-stable key: anchor it to what the previous chunk
148
+ // already emitted, so every chunk of this stream carries the identical map.
149
+ if (!(key in churn.anchorMeta))
150
+ churn.anchorMeta[key] = previous[key];
151
+ churn.churnyMetaKeys.add(key);
152
+ }
153
+ }
154
+ emitted[key] = churn.churnyMetaKeys.has(key) && key in churn.anchorMeta ? churn.anchorMeta[key] : value;
155
+ if (emitted[key] !== value)
156
+ anchored = true;
157
+ }
158
+ churn.prevMeta = meta;
159
+ if (anchored) {
160
+ payload._meta = emitted;
161
+ changed = true;
162
+ }
163
+ }
164
+ return changed ? { ...event, payload } : event;
165
+ }
166
+ function routeOwnEvent(state, out, event) {
167
+ const tick = tickEvent(state);
168
+ event = absorbAssistantChunkChurn(state, tick, event);
169
+ observe(state, event);
170
+ observeBackgroundWriter(state, event);
171
+ if ((!event.acpSessionId || event.acpSessionId === state.rootSessionId) &&
172
+ (event.eventName === 'agent_message_chunk' || event.eventName === 'agent_thought_chunk'))
173
+ trackMessageBoundary(state, out, event);
174
+ emitEvent(state, out, event);
175
+ }
176
+ /** Normalize the root session address, observe the event, then emit. */
177
+ export function emitSessionEvent(state, out, event) {
178
+ const tick = tickEvent(state);
179
+ event = absorbAssistantChunkChurn(state, tick, event);
180
+ // Inside a load's history window the session being loaded is the root (an attached `AcpSession` knows it).
181
+ const normalized = event.acpSessionId === (state.rootSessionId ?? state.history?.rootSessionId)
182
+ ? { eventName: event.eventName, payload: event.payload }
183
+ : event;
184
+ observe(state, normalized);
185
+ emitEvent(state, out, normalized);
186
+ }
187
+ /** What every live event feeds besides the outbox: the origin graph and the async-task set. */
188
+ function observe(state, event) {
189
+ if (event.eventName === 'subagent_spawned') {
190
+ observeSubagentSpawned(state, event.acpSessionId ?? state.rootSessionId, event.payload.subagentSessionId);
191
+ }
192
+ trackAsyncTask(state, event);
193
+ trackDraftSubagent(state, event);
194
+ }
195
+ /** `AcpSession.observeBackgroundWriter`: an explicitly detached writer blocks `executionEnded` for good. */
196
+ function observeBackgroundWriter(state, event) {
197
+ const input = event.payload.rawInput;
198
+ if (isRecord(input) && input.run_in_background === true)
199
+ state.backgroundWriterUnconfirmed = true;
200
+ const output = event.payload.rawOutput;
201
+ if (isRecord(output) && output.backgrounded === true && (typeof output.taskId === 'string' || typeof output.pid === 'number')) {
202
+ state.backgroundWriterUnconfirmed = true;
203
+ }
204
+ }
205
+ const DRAFT_CHILD_LIMIT = 4096;
206
+ const DRAFT_TERMINALS = new Set(['completed', 'failed', 'cancelled']);
207
+ /** Keep terminal tombstones: duplicated/reordered spawns cannot resurrect completed children.
208
+ * At capacity retain a conservative blocker rather than forget potentially running work. */
209
+ function trackDraftSubagent(state, event) {
210
+ if (event.eventName !== 'subagent_spawned' && event.eventName !== 'subagent_state_update')
211
+ return;
212
+ const id = event.payload.subagentSessionId;
213
+ if (typeof id !== 'string' || !id.length)
214
+ return;
215
+ const data = state.draftSubagents;
216
+ if (id.length > 256) {
217
+ data.overflow = true;
218
+ return;
219
+ }
220
+ const terminal = event.eventName === 'subagent_state_update' && DRAFT_TERMINALS.has(String(event.payload.state));
221
+ if (getOwn(data.children, id) === false)
222
+ return;
223
+ if (!Object.hasOwn(data.children, id) && Object.keys(data.children).length >= DRAFT_CHILD_LIMIT) {
224
+ data.overflow = true;
225
+ return;
226
+ }
227
+ putOwn(data.children, id, !terminal);
228
+ }
229
+ export function unfinishedDraftSubagentCount(state) {
230
+ return Object.values(state.draftSubagents.children).filter(Boolean).length + Number(state.draftSubagents.overflow);
231
+ }
232
+ const TERMINAL_ASYNC_STATES = new Set(['completed', 'failed', 'stopped']);
233
+ /**
234
+ * The unfinished async tasks (AIR `async_task_*`), per native session: spawned → running; a state
235
+ * update sets the last non-terminal state or removes the task on a terminal one. Settles on the
236
+ * **last** state — a finished shell sends `stopped` then `completed` (`draftSubagents.ts`), and the
237
+ * second finds nothing left to remove.
238
+ */
239
+ function trackAsyncTask(state, event) {
240
+ if (event.eventName !== 'async_task_spawned' && event.eventName !== 'async_task_state_update')
241
+ return;
242
+ const taskId = event.payload.asyncTaskId;
243
+ if (typeof taskId !== 'string' || taskId.length === 0)
244
+ return;
245
+ const owner = event.acpSessionId ?? state.rootSessionId;
246
+ if (owner === null)
247
+ return;
248
+ const next = event.eventName === 'async_task_spawned' ? 'running' : event.payload.state;
249
+ let tasks = getOwn(state.asyncTasks, owner);
250
+ if (typeof next === 'string' && TERMINAL_ASYNC_STATES.has(next)) {
251
+ if (tasks && Object.hasOwn(tasks, taskId)) {
252
+ delete tasks[taskId];
253
+ if (Object.keys(tasks).length === 0)
254
+ delete state.asyncTasks[owner];
255
+ }
256
+ return;
257
+ }
258
+ if (next !== 'running' && next !== 'paused')
259
+ return;
260
+ if (!(tasks && Object.hasOwn(tasks, taskId)) && unfinishedAsyncTaskCount(state) >= ASYNC_TASK_LIMIT) {
261
+ state.diagnostics.untrackedAsyncTasks += 1;
262
+ return;
263
+ }
264
+ if (!tasks)
265
+ putOwn(state.asyncTasks, owner, tasks = {});
266
+ putOwn(tasks, taskId, next);
267
+ }
268
+ function unfinishedAsyncTaskCount(state) {
269
+ let count = 0;
270
+ for (const tasks of Object.values(state.asyncTasks))
271
+ count += Object.keys(tasks).length;
272
+ return count;
273
+ }
274
+ /** Every unfinished async task, as `{nativeSessionId, asyncTaskId, state}`, in insertion order. */
275
+ export function unfinishedAsyncTasks(state) {
276
+ return Object.entries(state.asyncTasks).flatMap(([nativeSessionId, tasks]) => Object.entries(tasks).map(([asyncTaskId, status]) => ({ nativeSessionId, asyncTaskId, state: status })));
277
+ }
278
+ // ---- agent_message synthesis --------------------------------------------------------------------
279
+ /** `AcpSession.trackMessageBoundary`, plus remembering whether the message began outside any turn. */
280
+ function trackMessageBoundary(state, out, event) {
281
+ const message = state.message;
282
+ const messageId = stringField(event.payload, 'messageId');
283
+ if (message.open && messageId !== null && message.messageId !== null && messageId !== message.messageId)
284
+ flushMessage(state, out);
285
+ if (!message.open)
286
+ message.outOfTurn = state.turns.length === 0;
287
+ message.open = true;
288
+ if (messageId !== null)
289
+ message.messageId = messageId;
290
+ }
291
+ /** `AcpSession.flushMessageCompleted`: close the streaming message with `agent_message` (no-op if none). */
292
+ export function flushMessage(state, out) {
293
+ const message = state.message;
294
+ if (!message.open)
295
+ return;
296
+ emitEvent(state, out, { eventName: 'agent_message', payload: { messageId: message.messageId ?? 'turn' } });
297
+ message.open = false;
298
+ message.messageId = null;
299
+ message.outOfTurn = false;
300
+ }
301
+ /** A turn is about to start: a message that began outside any turn is closed now, never merged into it. */
302
+ export function flushOutOfTurnMessage(state, out) {
303
+ if (state.message.open && state.message.outOfTurn)
304
+ flushMessage(state, out);
305
+ }
306
+ // ---- load history -----------------------------------------------------------------------------
307
+ /** `foldScopedReplayEvents`, one update at a time. */
308
+ function onHistoryUpdate(state, history, sessionId, update, out) {
309
+ let data = getOwn(history.scopes, sessionId);
310
+ if (!data)
311
+ putOwn(history.scopes, sessionId, data = newMapperScopeData());
312
+ let events;
313
+ try {
314
+ events = mapSessionUpdate(update, new SessionMapperState(() => { }, data));
315
+ }
316
+ catch {
317
+ // Today an unmappable update throws out of the whole load (`replayNativeSession`); here one
318
+ // update is lost and the history goes on — counted, and reported on `processor.history_end`.
319
+ state.diagnostics.droppedUpdates += 1;
320
+ history.droppedCount += 1;
321
+ return;
322
+ }
323
+ for (const rawEvent of events) {
324
+ // Same churn absorption as the live path: a replayed CodeBuddy history fragments identically.
325
+ const event = absorbAssistantChunkChurn(state, tickEvent(state), rawEvent);
326
+ if (event.eventName === 'user_message_chunk')
327
+ flushHistoryMessage(state, history, sessionId, out);
328
+ if (event.eventName === 'agent_message_chunk' || event.eventName === 'agent_thought_chunk') {
329
+ const messageId = stringField(event.payload, 'messageId');
330
+ const index = history.messages.findIndex((entry) => entry.nativeSessionId === sessionId);
331
+ const previous = index >= 0 ? history.messages[index] : undefined;
332
+ if (previous && messageId !== null && previous.messageId !== null && messageId !== previous.messageId) {
333
+ flushHistoryMessage(state, history, sessionId, out);
334
+ history.messages.push({ nativeSessionId: sessionId, messageId });
335
+ }
336
+ else if (previous) {
337
+ previous.messageId = messageId ?? previous.messageId;
338
+ }
339
+ else {
340
+ history.messages.push({ nativeSessionId: sessionId, messageId });
341
+ }
342
+ }
343
+ emitHistory(state, history, out, event, sessionId);
344
+ }
345
+ }
346
+ function flushHistoryMessage(state, history, sessionId, out) {
347
+ const index = history.messages.findIndex((entry) => entry.nativeSessionId === sessionId);
348
+ if (index < 0)
349
+ return;
350
+ const [message] = history.messages.splice(index, 1);
351
+ emitHistory(state, history, out, { eventName: 'agent_message', payload: { messageId: message.messageId ?? 'replay' } }, sessionId);
352
+ }
353
+ function emitHistory(state, history, out, event, sessionId) {
354
+ const scoped = sessionId === history.rootSessionId ? event : { ...event, acpSessionId: sessionId };
355
+ if (validateWireEvent(scoped)) {
356
+ state.diagnostics.invalidEvents += 1;
357
+ return;
358
+ }
359
+ // `AcpSession.observeReplayEvent`: history restores the repair's calls, addresses and background-writer evidence.
360
+ if (scoped.eventName === 'subagent_spawned') {
361
+ observeSubagentSpawned(state, scoped.acpSessionId ?? history.rootSessionId, scoped.payload.subagentSessionId, history.rootSessionId);
362
+ }
363
+ trackDraftSubagent(state, scoped);
364
+ observeBackgroundWriter(state, scoped);
365
+ out.unjournaled({
366
+ t: 'processor.history_event',
367
+ eventName: scoped.eventName,
368
+ payload: scoped.payload,
369
+ ...(scoped.acpSessionId ? { acpSessionId: scoped.acpSessionId } : {}),
370
+ });
371
+ }
372
+ /**
373
+ * Close the history window: flush the open history messages (in first-chunk order, as
374
+ * `foldScopedReplayEvents` does at the end of its list) and report it. `ok: false` when the load
375
+ * failed or the connection closed — the daemon discards what it collected, as today's load does.
376
+ * `droppedCount` (history updates that could not be mapped) lets the daemon report a partial
377
+ * backfill. The `processor.history_event`s are unjournaled: a daemon that crashes inside the window
378
+ * restarts the load rather than resuming from a checkpoint cut inside it.
379
+ */
380
+ export function endHistory(state, out, ok) {
381
+ const history = state.history;
382
+ if (!history)
383
+ return;
384
+ if (ok) {
385
+ while (history.messages.length > 0)
386
+ flushHistoryMessage(state, history, history.messages[0].nativeSessionId, out);
387
+ }
388
+ state.history = null;
389
+ out.unjournaled({ t: 'processor.history_end', ok, droppedCount: history.droppedCount });
390
+ }