@ours.network/fleet 1.2.0-nightly.7 → 1.2.0-nightly.70

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 (414) hide show
  1. package/README.md +279 -68
  2. package/dist/account-origin.d.ts +2 -0
  3. package/dist/account-origin.js +6 -0
  4. package/dist/agent-ours/bridge.js +26 -9
  5. package/dist/agent-ours/correspondence.d.ts +10 -0
  6. package/dist/agent-ours/correspondence.js +1 -0
  7. package/dist/agent-ours/file-rpc.d.ts +12 -0
  8. package/dist/agent-ours/file-rpc.js +18 -4
  9. package/dist/agent-ours/harness.js +9 -1
  10. package/dist/agent-ours/mcp-endpoint.d.ts +19 -0
  11. package/dist/agent-ours/mcp-endpoint.js +98 -25
  12. package/dist/agent-ours/runtime.d.ts +9 -1
  13. package/dist/agent-ours/runtime.js +50 -2
  14. package/dist/agent-ours/service.d.ts +24 -1
  15. package/dist/agent-ours/service.js +97 -13
  16. package/dist/application/codex-models.d.ts +15 -0
  17. package/dist/application/codex-models.js +56 -0
  18. package/dist/application/conversation-history.d.ts +27 -0
  19. package/dist/application/conversation-history.js +215 -0
  20. package/dist/application/conversation-role-observer.d.ts +62 -0
  21. package/dist/application/conversation-role-observer.js +206 -0
  22. package/dist/application/fleet-query-service.d.ts +1 -1
  23. package/dist/application/fleet-query-service.js +2 -2
  24. package/dist/application/log-service.js +8 -8
  25. package/dist/application/model-catalog.d.ts +1 -1
  26. package/dist/application/model-catalog.js +5 -2
  27. package/dist/application/preset-provenance.d.ts +19 -0
  28. package/dist/application/preset-provenance.js +59 -0
  29. package/dist/application/role-creation-service.js +3 -2
  30. package/dist/application/role-removal-service.js +17 -3
  31. package/dist/application/role-repository.js +19 -2
  32. package/dist/application/room-layout-definitions.d.ts +45 -0
  33. package/dist/application/room-layout-definitions.js +130 -0
  34. package/dist/application/session-control.d.ts +61 -17
  35. package/dist/application/session-control.js +207 -23
  36. package/dist/application/supervisor-ours-tools.js +5 -11
  37. package/dist/application/task-layouts.d.ts +91 -0
  38. package/dist/application/task-layouts.js +259 -0
  39. package/dist/application/task-room-service.d.ts +99 -3
  40. package/dist/application/task-room-service.js +285 -32
  41. package/dist/application/types.d.ts +2 -0
  42. package/dist/atomic-file.d.ts +34 -1
  43. package/dist/atomic-file.js +161 -18
  44. package/dist/briefing.d.ts +3 -1
  45. package/dist/briefing.js +97 -31
  46. package/dist/build-info.json +9 -4
  47. package/dist/capabilities.d.ts +9 -1
  48. package/dist/capabilities.js +13 -0
  49. package/dist/cli.js +400 -37
  50. package/dist/client-profile.d.ts +5 -17
  51. package/dist/client-profile.js +4 -127
  52. package/dist/config.d.ts +45 -0
  53. package/dist/config.js +57 -6
  54. package/dist/creation.d.ts +1 -1
  55. package/dist/creation.js +4 -4
  56. package/dist/daemon-recovery.d.ts +1 -8
  57. package/dist/daemon-recovery.js +8 -113
  58. package/dist/docs.d.ts +1 -1
  59. package/dist/docs.js +207 -19
  60. package/dist/doctor.d.ts +4 -1
  61. package/dist/doctor.js +75 -60
  62. package/dist/erased-resources.d.ts +9 -0
  63. package/dist/erased-resources.js +87 -0
  64. package/dist/file-delivery/reader.d.ts +15 -0
  65. package/dist/file-delivery/reader.js +63 -0
  66. package/dist/file-delivery/store.d.ts +15 -0
  67. package/dist/file-delivery/store.js +124 -0
  68. package/dist/file-delivery/types.d.ts +19 -0
  69. package/dist/file-delivery/types.js +1 -0
  70. package/dist/fleet-command-audit.d.ts +7 -0
  71. package/dist/fleet-command-audit.js +24 -8
  72. package/dist/harness/agent-session.d.ts +4 -0
  73. package/dist/harness/claude-code-session.js +1 -1
  74. package/dist/harness/claude-code.js +21 -11
  75. package/dist/harness/claude-runtime.d.ts +12 -0
  76. package/dist/harness/claude-runtime.js +43 -0
  77. package/dist/harness/codex-app-server-proxy.d.ts +4 -1
  78. package/dist/harness/codex-app-server-proxy.js +41 -5
  79. package/dist/harness/codex-reasoning.d.ts +5 -0
  80. package/dist/harness/codex-reasoning.js +12 -0
  81. package/dist/harness/codex-runtime.d.ts +11 -1
  82. package/dist/harness/codex-runtime.js +31 -4
  83. package/dist/harness/codex-session.js +2 -2
  84. package/dist/harness/codex.js +24 -12
  85. package/dist/init-wizard.d.ts +2 -0
  86. package/dist/init-wizard.js +38 -19
  87. package/dist/isolation/policy.js +6 -1
  88. package/dist/isolation/types.d.ts +5 -0
  89. package/dist/managed-cli.d.ts +253 -0
  90. package/dist/managed-cli.js +923 -0
  91. package/dist/managed-recovery.d.ts +13 -0
  92. package/dist/managed-recovery.js +31 -0
  93. package/dist/minimal-setup.d.ts +2 -0
  94. package/dist/minimal-setup.js +44 -0
  95. package/dist/monitor.d.ts +8 -34
  96. package/dist/monitor.js +89 -152
  97. package/dist/notifications/fleet-producer.d.ts +19 -0
  98. package/dist/notifications/fleet-producer.js +208 -0
  99. package/dist/notifications/outbox.d.ts +46 -0
  100. package/dist/notifications/outbox.js +158 -0
  101. package/dist/notifications/target-cleanup.d.ts +10 -0
  102. package/dist/notifications/target-cleanup.js +63 -0
  103. package/dist/notifications/task-producer.d.ts +18 -0
  104. package/dist/notifications/task-producer.js +67 -0
  105. package/dist/ops.d.ts +2 -0
  106. package/dist/ops.js +20 -3
  107. package/dist/owner-channel/channel.js +17 -6
  108. package/dist/owner-channel/commands.d.ts +4 -0
  109. package/dist/owner-channel/commands.js +8 -0
  110. package/dist/owner-channel/lifecycle-outbox.js +4 -3
  111. package/dist/owner-channel/ours-client.js +2 -17
  112. package/dist/paths.d.ts +2 -0
  113. package/dist/paths.js +2 -0
  114. package/dist/preset-migration.js +43 -0
  115. package/dist/process-incarnation.d.ts +23 -0
  116. package/dist/process-incarnation.js +42 -0
  117. package/dist/reminders/manager.d.ts +75 -0
  118. package/dist/reminders/manager.js +278 -0
  119. package/dist/reminders/runtime.d.ts +27 -0
  120. package/dist/reminders/runtime.js +32 -0
  121. package/dist/reminders/schedule.d.ts +37 -0
  122. package/dist/reminders/schedule.js +104 -0
  123. package/dist/reminders/store.d.ts +341 -0
  124. package/dist/reminders/store.js +762 -0
  125. package/dist/reminders/tools.d.ts +20 -0
  126. package/dist/reminders/tools.js +114 -0
  127. package/dist/resolved-plan.js +1 -0
  128. package/dist/rooms-tasks/add-member.d.ts +48 -0
  129. package/dist/rooms-tasks/add-member.js +83 -0
  130. package/dist/rooms-tasks/archived-absence.d.ts +8 -0
  131. package/dist/rooms-tasks/archived-absence.js +48 -0
  132. package/dist/rooms-tasks/cli.js +65 -5
  133. package/dist/rooms-tasks/close.d.ts +6 -2
  134. package/dist/rooms-tasks/close.js +246 -37
  135. package/dist/rooms-tasks/config.d.ts +1 -1
  136. package/dist/rooms-tasks/config.js +11 -4
  137. package/dist/rooms-tasks/cowork-adapter.d.ts +12 -5
  138. package/dist/rooms-tasks/cowork-adapter.js +15 -121
  139. package/dist/rooms-tasks/cowork-http.js +56 -6
  140. package/dist/rooms-tasks/deletion.d.ts +1 -1
  141. package/dist/rooms-tasks/deletion.js +84 -5
  142. package/dist/rooms-tasks/erasure.d.ts +6 -0
  143. package/dist/rooms-tasks/erasure.js +173 -0
  144. package/dist/rooms-tasks/external-worker.d.ts +1 -1
  145. package/dist/rooms-tasks/external-worker.js +3 -4
  146. package/dist/rooms-tasks/layout-binding-client.d.ts +11 -0
  147. package/dist/rooms-tasks/layout-binding-client.js +56 -0
  148. package/dist/rooms-tasks/layout-binding-grants.d.ts +21 -0
  149. package/dist/rooms-tasks/layout-binding-grants.js +128 -0
  150. package/dist/rooms-tasks/layout-cli.d.ts +4 -0
  151. package/dist/rooms-tasks/layout-cli.js +107 -0
  152. package/dist/rooms-tasks/layout-config.d.ts +11 -0
  153. package/dist/rooms-tasks/layout-config.js +89 -0
  154. package/dist/rooms-tasks/layout-control.d.ts +21 -0
  155. package/dist/rooms-tasks/layout-control.js +52 -0
  156. package/dist/rooms-tasks/layout-member-retirement.d.ts +10 -0
  157. package/dist/rooms-tasks/layout-member-retirement.js +90 -0
  158. package/dist/rooms-tasks/layout-service.d.ts +43 -0
  159. package/dist/rooms-tasks/layout-service.js +203 -0
  160. package/dist/rooms-tasks/layout.d.ts +121 -0
  161. package/dist/rooms-tasks/layout.js +285 -0
  162. package/dist/rooms-tasks/legacy-task-member.d.ts +19 -0
  163. package/dist/rooms-tasks/legacy-task-member.js +116 -0
  164. package/dist/rooms-tasks/live-readiness.d.ts +18 -0
  165. package/dist/rooms-tasks/live-readiness.js +85 -0
  166. package/dist/rooms-tasks/member-ownership.d.ts +5 -0
  167. package/dist/rooms-tasks/member-ownership.js +40 -0
  168. package/dist/rooms-tasks/member-startup.d.ts +1 -0
  169. package/dist/rooms-tasks/member-startup.js +2 -0
  170. package/dist/rooms-tasks/provision.d.ts +3 -0
  171. package/dist/rooms-tasks/provision.js +101 -49
  172. package/dist/rooms-tasks/recovery.d.ts +19 -0
  173. package/dist/rooms-tasks/recovery.js +110 -0
  174. package/dist/rooms-tasks/room-state.d.ts +4 -2
  175. package/dist/rooms-tasks/room-state.js +47 -8
  176. package/dist/rooms-tasks/task-service-retirement.d.ts +11 -0
  177. package/dist/rooms-tasks/task-service-retirement.js +21 -0
  178. package/dist/rooms-tasks/task-state.d.ts +51 -8
  179. package/dist/rooms-tasks/task-state.js +245 -25
  180. package/dist/rooms-tasks/types.d.ts +40 -0
  181. package/dist/rooms-tasks/workspace-artifacts.d.ts +6 -0
  182. package/dist/rooms-tasks/workspace-artifacts.js +93 -0
  183. package/dist/rooms-tasks/workspace.d.ts +35 -0
  184. package/dist/rooms-tasks/workspace.js +325 -0
  185. package/dist/runner.d.ts +33 -4
  186. package/dist/runner.js +389 -56
  187. package/dist/session/acp.d.ts +75 -2
  188. package/dist/session/acp.js +345 -82
  189. package/dist/session/arbiter.d.ts +98 -0
  190. package/dist/session/arbiter.js +272 -3
  191. package/dist/session/codex-app-server.d.ts +45 -1
  192. package/dist/session/codex-app-server.js +225 -32
  193. package/dist/session/control.d.ts +17 -3
  194. package/dist/session/control.js +213 -23
  195. package/dist/session/conversation-normalizer.d.ts +2 -1
  196. package/dist/session/conversation-normalizer.js +1 -1
  197. package/dist/session/conversation-observation.d.ts +25 -0
  198. package/dist/session/conversation-observation.js +100 -0
  199. package/dist/session/conversation-replay.d.ts +50 -0
  200. package/dist/session/conversation-replay.js +203 -0
  201. package/dist/session/conversation-store.d.ts +15 -1
  202. package/dist/session/conversation-store.js +206 -26
  203. package/dist/session/conversation-types.d.ts +57 -4
  204. package/dist/session/prompt-batch.d.ts +79 -0
  205. package/dist/session/prompt-batch.js +120 -0
  206. package/dist/session/task-notice.d.ts +14 -0
  207. package/dist/session/task-notice.js +13 -0
  208. package/dist/session/types.d.ts +42 -1
  209. package/dist/setup-tunnel-preflight.d.ts +34 -0
  210. package/dist/setup-tunnel-preflight.js +62 -0
  211. package/dist/socket-path.d.ts +2 -0
  212. package/dist/socket-path.js +22 -0
  213. package/dist/spawn.d.ts +5 -1
  214. package/dist/spawn.js +40 -4
  215. package/dist/startup-prompt.d.ts +15 -0
  216. package/dist/startup-prompt.js +71 -0
  217. package/dist/startup-readiness.d.ts +32 -0
  218. package/dist/startup-readiness.js +101 -0
  219. package/dist/startup-telemetry.d.ts +16 -0
  220. package/dist/startup-telemetry.js +46 -0
  221. package/dist/subscriptions/cli.d.ts +91 -0
  222. package/dist/subscriptions/cli.js +223 -0
  223. package/dist/subscriptions/launch.d.ts +37 -0
  224. package/dist/subscriptions/launch.js +93 -0
  225. package/dist/subscriptions/login.d.ts +76 -0
  226. package/dist/subscriptions/login.js +207 -0
  227. package/dist/subscriptions/observed.d.ts +7 -0
  228. package/dist/subscriptions/observed.js +44 -0
  229. package/dist/subscriptions/probe.d.ts +10 -0
  230. package/dist/subscriptions/probe.js +73 -0
  231. package/dist/subscriptions/service.d.ts +102 -0
  232. package/dist/subscriptions/service.js +364 -0
  233. package/dist/subscriptions/store.d.ts +71 -0
  234. package/dist/subscriptions/store.js +140 -0
  235. package/dist/supervisor/adoption.d.ts +8 -0
  236. package/dist/supervisor/adoption.js +78 -0
  237. package/dist/supervisor/catalog.d.ts +62 -0
  238. package/dist/supervisor/catalog.js +254 -0
  239. package/dist/supervisor/fleet.d.ts +8 -0
  240. package/dist/supervisor/fleet.js +89 -0
  241. package/dist/supervisor/index.js +3 -6
  242. package/dist/supervisor/launchd.d.ts +1 -1
  243. package/dist/supervisor/launchd.js +26 -13
  244. package/dist/supervisor/legacy.d.ts +35 -0
  245. package/dist/supervisor/legacy.js +524 -0
  246. package/dist/supervisor/manager.d.ts +15 -0
  247. package/dist/supervisor/manager.js +270 -0
  248. package/dist/supervisor/registration-refresh.d.ts +45 -0
  249. package/dist/supervisor/registration-refresh.js +266 -0
  250. package/dist/supervisor/scope.d.ts +4 -0
  251. package/dist/supervisor/scope.js +10 -0
  252. package/dist/supervisor/systemd.d.ts +2 -2
  253. package/dist/supervisor/systemd.js +19 -33
  254. package/dist/task-supervision.d.ts +9 -0
  255. package/dist/task-supervision.js +145 -0
  256. package/dist/temp-idle.d.ts +17 -0
  257. package/dist/temp-idle.js +42 -0
  258. package/dist/temp-lifecycle.d.ts +23 -8
  259. package/dist/temp-lifecycle.js +123 -66
  260. package/dist/temp-supervisor-recovery.d.ts +1 -1
  261. package/dist/temp-supervisor-recovery.js +2 -2
  262. package/dist/tunnel-setup-completion.d.ts +7 -0
  263. package/dist/tunnel-setup-completion.js +13 -0
  264. package/dist/tunnel-setup-input.d.ts +19 -0
  265. package/dist/tunnel-setup-input.js +124 -0
  266. package/dist/web/agent-attachments.d.ts +29 -0
  267. package/dist/web/agent-attachments.js +162 -0
  268. package/dist/web/auth.d.ts +65 -2
  269. package/dist/web/auth.js +201 -11
  270. package/dist/web/available-port.d.ts +2 -0
  271. package/dist/web/available-port.js +23 -0
  272. package/dist/web/control.d.ts +3 -3
  273. package/dist/web/control.js +10 -8
  274. package/dist/web/conversation-stream-codec.d.ts +23 -0
  275. package/dist/web/conversation-stream-codec.js +110 -0
  276. package/dist/web/conversation-stream.d.ts +25 -0
  277. package/dist/web/conversation-stream.js +231 -0
  278. package/dist/web/fleet-config-service.d.ts +4 -1
  279. package/dist/web/fleet-config-service.js +46 -15
  280. package/dist/web/prefix-gateway.d.ts +32 -0
  281. package/dist/web/prefix-gateway.js +238 -0
  282. package/dist/web/runtime.d.ts +3 -1
  283. package/dist/web/runtime.js +128 -33
  284. package/dist/web/server.d.ts +16 -0
  285. package/dist/web/server.js +639 -55
  286. package/dist/web/service.d.ts +11 -2
  287. package/dist/web/service.js +30 -4
  288. package/dist/web/workspace-devices.d.ts +107 -0
  289. package/dist/web/workspace-devices.js +277 -0
  290. package/dist/web/workspace-tunnel.d.ts +1 -0
  291. package/dist/web/workspace-tunnel.js +34 -0
  292. package/dist/workspace-enrollment.d.ts +83 -0
  293. package/dist/workspace-enrollment.js +580 -0
  294. package/dist/workspace-replacement.d.ts +66 -0
  295. package/dist/workspace-replacement.js +220 -0
  296. package/docs/acp-files.md +146 -0
  297. package/docs/conversation-stream.md +190 -0
  298. package/docs/fleet-migration.md +54 -0
  299. package/docs/live-voice.md +13 -0
  300. package/docs/room-layouts.md +227 -0
  301. package/docs/self-reminders.md +374 -0
  302. package/docs/task-workspaces.md +225 -0
  303. package/docs/validation/managed-cli-permissions.md +421 -0
  304. package/examples/room-layouts/fresh.yaml +27 -0
  305. package/examples/room-layouts/scoped.yaml +21 -0
  306. package/examples/room-layouts/shared.yaml +19 -0
  307. package/package.json +24 -20
  308. package/presets/README.md +78 -0
  309. package/presets/brain-catalog.json +8 -2
  310. package/presets/fleet/agent_templates/Critic.yaml +1 -1
  311. package/presets/fleet/agent_templates/Developer.yaml +1 -1
  312. package/presets/fleet/agent_templates/Engineer.yaml +5 -0
  313. package/presets/fleet/agent_templates/LocalCoordinator.yaml +4 -2
  314. package/presets/fleet/agents/FleetCoordinator.yaml +1 -1
  315. package/presets/fleet/brains/claude-fable-5-1-high.yaml +5 -0
  316. package/presets/fleet/brains/claude-fable-5-1-low.yaml +5 -0
  317. package/presets/fleet/brains/claude-fable-5-1-max.yaml +5 -0
  318. package/presets/fleet/brains/claude-fable-5-1-medium.yaml +5 -0
  319. package/presets/fleet/brains/claude-fable-5-1-xhigh.yaml +5 -0
  320. package/presets/fleet/brains/claude-fable-5-high.yaml +1 -1
  321. package/presets/fleet/brains/claude-fable-5-low.yaml +1 -1
  322. package/presets/fleet/brains/claude-fable-5-max.yaml +1 -1
  323. package/presets/fleet/brains/claude-fable-5-medium.yaml +1 -1
  324. package/presets/fleet/brains/claude-fable-5-xhigh.yaml +1 -1
  325. package/presets/fleet/brains/claude-haiku-4-5-20251001-default.yaml +4 -0
  326. package/presets/fleet/brains/claude-opus-5-5-high.yaml +5 -0
  327. package/presets/fleet/brains/claude-opus-5-5-low.yaml +5 -0
  328. package/presets/fleet/brains/claude-opus-5-5-max.yaml +5 -0
  329. package/presets/fleet/brains/claude-opus-5-5-medium.yaml +5 -0
  330. package/presets/fleet/brains/claude-opus-5-5-xhigh.yaml +5 -0
  331. package/presets/fleet/brains/claude-opus-5-high.yaml +1 -1
  332. package/presets/fleet/brains/claude-opus-5-low.yaml +1 -1
  333. package/presets/fleet/brains/claude-opus-5-max.yaml +1 -1
  334. package/presets/fleet/brains/claude-opus-5-medium.yaml +1 -1
  335. package/presets/fleet/brains/claude-opus-5-xhigh.yaml +1 -1
  336. package/presets/fleet/brains/claude-sonnet-5-high.yaml +1 -1
  337. package/presets/fleet/brains/claude-sonnet-5-low.yaml +1 -1
  338. package/presets/fleet/brains/claude-sonnet-5-max.yaml +1 -1
  339. package/presets/fleet/brains/claude-sonnet-5-medium.yaml +1 -1
  340. package/presets/fleet/brains/claude-sonnet-5-xhigh.yaml +1 -1
  341. package/presets/fleet/brains/codex-gpt-5-3-codex-spark-high.yaml +1 -1
  342. package/presets/fleet/brains/codex-gpt-5-3-codex-spark-low.yaml +1 -1
  343. package/presets/fleet/brains/codex-gpt-5-3-codex-spark-medium.yaml +1 -1
  344. package/presets/fleet/brains/codex-gpt-5-3-codex-spark-xhigh.yaml +1 -1
  345. package/presets/fleet/brains/codex-gpt-5-4-high.yaml +1 -1
  346. package/presets/fleet/brains/codex-gpt-5-4-low.yaml +1 -1
  347. package/presets/fleet/brains/codex-gpt-5-4-medium.yaml +1 -1
  348. package/presets/fleet/brains/codex-gpt-5-4-mini-high.yaml +1 -1
  349. package/presets/fleet/brains/codex-gpt-5-4-mini-low.yaml +1 -1
  350. package/presets/fleet/brains/codex-gpt-5-4-mini-medium.yaml +1 -1
  351. package/presets/fleet/brains/codex-gpt-5-4-mini-xhigh.yaml +1 -1
  352. package/presets/fleet/brains/codex-gpt-5-4-xhigh.yaml +1 -1
  353. package/presets/fleet/brains/codex-gpt-5-5-high.yaml +1 -1
  354. package/presets/fleet/brains/codex-gpt-5-5-low.yaml +1 -1
  355. package/presets/fleet/brains/codex-gpt-5-5-medium.yaml +1 -1
  356. package/presets/fleet/brains/codex-gpt-5-5-xhigh.yaml +1 -1
  357. package/presets/fleet/brains/codex-gpt-5-6-luna-high.yaml +1 -1
  358. package/presets/fleet/brains/codex-gpt-5-6-luna-low.yaml +1 -1
  359. package/presets/fleet/brains/codex-gpt-5-6-luna-max.yaml +1 -1
  360. package/presets/fleet/brains/codex-gpt-5-6-luna-medium.yaml +1 -1
  361. package/presets/fleet/brains/codex-gpt-5-6-luna-xhigh.yaml +1 -1
  362. package/presets/fleet/brains/codex-gpt-5-6-sol-high.yaml +1 -1
  363. package/presets/fleet/brains/codex-gpt-5-6-sol-low.yaml +1 -1
  364. package/presets/fleet/brains/codex-gpt-5-6-sol-max.yaml +1 -1
  365. package/presets/fleet/brains/codex-gpt-5-6-sol-medium.yaml +1 -1
  366. package/presets/fleet/brains/codex-gpt-5-6-sol-ultra.yaml +1 -1
  367. package/presets/fleet/brains/codex-gpt-5-6-sol-xhigh.yaml +1 -1
  368. package/presets/fleet/brains/codex-gpt-5-6-terra-high.yaml +1 -1
  369. package/presets/fleet/brains/codex-gpt-5-6-terra-low.yaml +1 -1
  370. package/presets/fleet/brains/codex-gpt-5-6-terra-max.yaml +1 -1
  371. package/presets/fleet/brains/codex-gpt-5-6-terra-medium.yaml +1 -1
  372. package/presets/fleet/brains/codex-gpt-5-6-terra-ultra.yaml +1 -1
  373. package/presets/fleet/brains/codex-gpt-5-6-terra-xhigh.yaml +1 -1
  374. package/presets/fleet/brains/codex-gpt-6-1-sol-high.yaml +5 -0
  375. package/presets/fleet/brains/codex-gpt-6-1-sol-low.yaml +5 -0
  376. package/presets/fleet/brains/codex-gpt-6-1-sol-max.yaml +5 -0
  377. package/presets/fleet/brains/codex-gpt-6-1-sol-medium.yaml +5 -0
  378. package/presets/fleet/brains/codex-gpt-6-1-sol-ultra.yaml +5 -0
  379. package/presets/fleet/brains/codex-gpt-6-1-sol-xhigh.yaml +5 -0
  380. package/presets/fleet/brains/codex-gpt-6-astra-high.yaml +1 -1
  381. package/presets/fleet/brains/codex-gpt-6-astra-low.yaml +1 -1
  382. package/presets/fleet/brains/codex-gpt-6-astra-max.yaml +1 -1
  383. package/presets/fleet/brains/codex-gpt-6-astra-medium.yaml +1 -1
  384. package/presets/fleet/brains/codex-gpt-6-astra-ultra.yaml +1 -1
  385. package/presets/fleet/brains/codex-gpt-6-astra-xhigh.yaml +1 -1
  386. package/presets/fleet/brains/codex-gpt-6-luna-high.yaml +5 -0
  387. package/presets/fleet/brains/codex-gpt-6-luna-low.yaml +5 -0
  388. package/presets/fleet/brains/codex-gpt-6-luna-max.yaml +5 -0
  389. package/presets/fleet/brains/codex-gpt-6-luna-medium.yaml +5 -0
  390. package/presets/fleet/brains/codex-gpt-6-luna-xhigh.yaml +5 -0
  391. package/presets/fleet/brains/codex-gpt-6-sol-high.yaml +5 -0
  392. package/presets/fleet/brains/codex-gpt-6-sol-low.yaml +5 -0
  393. package/presets/fleet/brains/codex-gpt-6-sol-max.yaml +5 -0
  394. package/presets/fleet/brains/codex-gpt-6-sol-medium.yaml +5 -0
  395. package/presets/fleet/brains/codex-gpt-6-sol-ultra.yaml +5 -0
  396. package/presets/fleet/brains/codex-gpt-6-sol-xhigh.yaml +5 -0
  397. package/presets/fleet/roles/Coordinator.yaml +12 -11
  398. package/presets/fleet/roles/Critic.yaml +13 -0
  399. package/presets/fleet/roles/Developer.yaml +13 -0
  400. package/presets/fleet/roles/Engineer.yaml +53 -0
  401. package/presets/fleet/room_layouts/engineering.yaml +25 -0
  402. package/presets/fleet/room_layouts/pair.yaml +24 -0
  403. package/presets/fleet/room_layouts/single.yaml +17 -0
  404. package/presets/fleet/room_layouts/team.yaml +30 -0
  405. package/presets/fleet/room_templates/engineering.yaml +19 -0
  406. package/presets/manifest.json +2 -2
  407. package/dist/web-app/assets/index-59GF-gsZ.css +0 -1
  408. package/dist/web-app/assets/index-C0h3ALvs.js +0 -10
  409. package/dist/web-app/icons/ours-fleet-maskable.svg +0 -4
  410. package/dist/web-app/icons/ours-fleet.svg +0 -4
  411. package/dist/web-app/index.html +0 -17
  412. package/dist/web-app/manifest.webmanifest +0 -15
  413. package/dist/web-app/offline.html +0 -18
  414. package/dist/web-app/sw.js +0 -51
@@ -1,8 +1,12 @@
1
+ import { ConversationObservation } from './conversation-observation.js';
2
+ import { appendTaskCreated } from './task-notice.js';
1
3
  import { createHash, randomUUID } from 'node:crypto';
2
4
  import { existsSync, readFileSync, writeFileSync } from 'node:fs';
3
5
  import { isAbsolute, join, resolve } from 'node:path';
6
+ import { boundedJson } from './conversation-normalizer.js';
4
7
  import { ConversationEventStore } from './conversation-store.js';
5
8
  import { SessionEvents } from './events.js';
9
+ import { memberAuthority, memberBindings, pendingInventory, takeBatch, refuseAtRelease, RELEASE_GUARD_REFUSED, } from './prompt-batch.js';
6
10
  import { CodexAppServerTransport } from './codex-app-server-transport.js';
7
11
  import { CODEX_APP_SERVER_CANCEL_DEADLINE_EXCEEDED, SessionControlError, sessionBackendCapabilities, turnResult, } from './types.js';
8
12
  const PERMISSION_TIMEOUT_MS = 10 * 60_000;
@@ -12,7 +16,6 @@ const INTERRUPT_TERMINATE_GRACE_MS = 5_000;
12
16
  const TERMINAL_RECONCILE_QUIET_MS = 2_000;
13
17
  const TERMINAL_RECONCILE_REQUEST_TIMEOUT_MS = 5_000;
14
18
  const SCHEDULED_REDACTION = '[scheduled-loop content redacted]';
15
- const COMMENTARY_REDACTION = '[assistant commentary redacted]';
16
19
  const OWNER_ADMIN_CONTEXT_KEY = 'ours-fleet://prompt-provenance?source=owner_admin_console';
17
20
  const OWNER_CHANNEL_CONTEXT_KEY = 'ours-fleet://prompt-provenance?source=owner_channel';
18
21
  const isObject = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
@@ -24,6 +27,7 @@ function sourceFor(origin) {
24
27
  case 'owner': return { source: 'owner_channel', persistBody: false };
25
28
  case 'fleet-monitor': return { source: 'fleet_monitor', persistBody: false };
26
29
  case 'scheduled-loop': return { source: 'scheduled_loop', persistBody: false };
30
+ case 'self-reminder': return { source: 'fleet_monitor', persistBody: false };
27
31
  case 'local-console':
28
32
  default: return { source: 'local_console', persistBody: true };
29
33
  }
@@ -74,6 +78,31 @@ export function nativePromptAdditionalContext(origin) {
74
78
  };
75
79
  return undefined;
76
80
  }
81
+ const PROMPT_BATCH_CONTEXT_KEY = 'ours-fleet://prompt-batch';
82
+ /**
83
+ * Application context for a turn that carries several admitted prompts.
84
+ *
85
+ * The single-prompt context says "the accompanying user text", which would
86
+ * cover every member. A shared turn therefore carries this one entry instead:
87
+ * each member is its own user text item, in order, and its route and exact
88
+ * bytes are stated here by the server. Text imitating this wording is still
89
+ * only user text; it cannot add an application-context entry.
90
+ */
91
+ export function nativeBatchAdditionalContext(members) {
92
+ if (members.length === 1)
93
+ return nativePromptAdditionalContext(members[0].origin);
94
+ const bindings = memberBindings(members, origin => sourceFor(origin).source);
95
+ return {
96
+ [PROMPT_BATCH_CONTEXT_KEY]: {
97
+ kind: 'application',
98
+ value: `Fleet queued prompt batch: ${members.length} separately admitted prompts in submission order, `
99
+ + 'one user text item each. Server-generated provenance per item, describing only that item: '
100
+ + bindings.map(binding => `item ${binding.index} of ${binding.of} `
101
+ + `(source=${binding.source}, bytes=${binding.bytes}, sha256=${binding.sha256}): `
102
+ + `${memberAuthority(binding.source)}`).join('; ') + '.',
103
+ },
104
+ };
105
+ }
77
106
  function toolItem(item) {
78
107
  switch (item.type) {
79
108
  case 'commandExecution': return {
@@ -121,7 +150,13 @@ export class CodexAppServerSession {
121
150
  lastError;
122
151
  exit = null;
123
152
  queueDepth = 0;
153
+ deferredRecovered = [];
154
+ observation = new ConversationObservation(() => this.captureObservation());
124
155
  promptTail = Promise.resolve();
156
+ /** Admitted prompts not yet handed to the app-server, in admission order. */
157
+ pendingPrompts = [];
158
+ /** Admitted prompt → the turn that carries it, while that turn is open. */
159
+ sharedTurns = new Map();
125
160
  activeTurn;
126
161
  controllerCount = 0;
127
162
  controllerGrace;
@@ -139,6 +174,9 @@ export class CodexAppServerSession {
139
174
  roleId: options.name, log: line => options.log(`[${options.name}] ${line}`),
140
175
  });
141
176
  this.conversationStartCursor = this.conversation.lastCursor();
177
+ // A durable append can precede its inventory mutation. Capture only after
178
+ // the synchronous owner checkpoint, never the state at append notification.
179
+ this.conversation.subscribe(() => this.observation.scheduleCapture());
142
180
  // Use Fleet's provider-neutral resume marker so runner recovery rotates the
143
181
  // exact native thread id after a poisoned fast resume.
144
182
  this.threadFile = join(options.stateDir, '.session-id');
@@ -172,6 +210,9 @@ export class CodexAppServerSession {
172
210
  alive: this.isAlive(),
173
211
  readiness: this.readiness,
174
212
  sessionId: this.threadId,
213
+ // A shared turn is a human console turn if any member is: inbox traffic must not cut it short.
214
+ ...(this.activeTurn?.origin ? { activePromptSource: this.activeTurn.console
215
+ ? 'owner-admin-console' : this.activeTurn.origin.kind } : {}),
175
216
  lastError: this.lastError,
176
217
  pendingPermissionId: this.pendingPermissions.keys().next().value,
177
218
  runtimeModel: this.runtimeModel,
@@ -184,6 +225,9 @@ export class CodexAppServerSession {
184
225
  };
185
226
  }
186
227
  async queuePrompt(text, options = {}) {
228
+ // A guarded prompt must reach the model only through the release fence.
229
+ if (options.releaseGuard)
230
+ options = { ...options, interrupt: false, steer: false };
187
231
  if (this.closing || !this.threadId || !this.transport.isAlive())
188
232
  throw new SessionControlError('offline', this.lastError ?? 'Codex app-server session is offline');
189
233
  let delivery;
@@ -200,15 +244,18 @@ export class CodexAppServerSession {
200
244
  }
201
245
  const promptId = randomUUID();
202
246
  const queuedBehind = this.queueDepth;
203
- this.admit(promptId, text, queuedBehind, options);
204
- this.queueDepth++;
205
- const run = this.promptTail.then(() => this.runPrompt(text, promptId, options.origin));
206
- this.promptTail = run.then(() => undefined, () => undefined);
247
+ const run = this.observation.checkpoint(() => {
248
+ this.admit(promptId, text, queuedBehind, options);
249
+ this.queueDepth++;
250
+ return this.enqueue(promptId, text, options.origin, options.releaseGuard);
251
+ });
207
252
  const completion = run.then(result => {
208
253
  this.queueDepth = Math.max(0, this.queueDepth - 1);
254
+ this.observation.publish();
209
255
  return result;
210
256
  }, error => {
211
257
  this.queueDepth = Math.max(0, this.queueDepth - 1);
258
+ this.observation.publish();
212
259
  return turnResult(false, 'failed', error instanceof Error ? error.message : String(error));
213
260
  });
214
261
  return {
@@ -216,6 +263,53 @@ export class CodexAppServerSession {
216
263
  delivery: delivery ?? (queuedBehind ? 'queued' : 'started'),
217
264
  };
218
265
  }
266
+ /** The turn whose events and result answer this admitted prompt; itself unless a release shared it. */
267
+ sharedTurnId(promptId) {
268
+ return this.sharedTurns.get(promptId);
269
+ }
270
+ /** Each prompt keeps its own step in the chain; the step it reaches releases a whole snapshot. */
271
+ enqueue(promptId, text, origin, releaseGuard) {
272
+ const entry = {
273
+ promptId, text, origin, ...sourceFor(origin), admittedAt: new Date().toISOString(),
274
+ // The one text the native session runs as an operation instead of a turn.
275
+ command: text.trim() === '/compact',
276
+ ...(releaseGuard ? { releaseGuard } : {}),
277
+ };
278
+ this.pendingPrompts.push(entry);
279
+ const run = this.promptTail.then(() => this.release(entry));
280
+ this.promptTail = run.then(() => undefined, () => undefined);
281
+ return run;
282
+ }
283
+ /**
284
+ * The turn boundary: the first waiting prompt to get here synchronously
285
+ * takes every pending prompt delivered with it into one turn. A prompt
286
+ * admitted afterwards stays pending for the next boundary, and a step whose
287
+ * prompt was already taken reports that turn's result.
288
+ */
289
+ release(entry) {
290
+ if (entry.released)
291
+ return entry.released;
292
+ const refused = refuseAtRelease(this.pendingPrompts, entry, Boolean(this.threadId && this.transport.isAlive()));
293
+ if (refused) {
294
+ this.conversation.appendSafe({
295
+ kind: 'turn.completed', sessionGeneration: this.sessionGeneration,
296
+ promptId: entry.promptId, turnId: entry.promptId,
297
+ payload: { outcome: 'cancelled', stopReason: RELEASE_GUARD_REFUSED },
298
+ });
299
+ entry.released = Promise.resolve(refused);
300
+ return entry.released;
301
+ }
302
+ const members = takeBatch(this.pendingPrompts, entry);
303
+ for (const member of members)
304
+ this.sharedTurns.set(member.promptId, members[0].promptId);
305
+ const run = this.runPrompt(members).finally(() => {
306
+ for (const member of members)
307
+ this.sharedTurns.delete(member.promptId);
308
+ });
309
+ for (const member of members)
310
+ member.released = run;
311
+ return run;
312
+ }
219
313
  async submitPrompt(text, options = {}) {
220
314
  try {
221
315
  return await (await this.queuePrompt(text, options)).completion;
@@ -226,10 +320,20 @@ export class CodexAppServerSession {
226
320
  throw error;
227
321
  }
228
322
  }
323
+ liveVoiceSupported = true;
324
+ async interruptPrompt(generation, promptId) {
325
+ if (generation !== this.sessionGeneration)
326
+ throw new Error('session_changed: Agent session changed.');
327
+ if (!this.activeTurn?.promptIds.includes(promptId))
328
+ return { state: 'settled' };
329
+ return this.interrupt('local-console');
330
+ }
229
331
  async interrupt(source = 'local-console') {
230
332
  const active = this.activeTurn;
231
- if (!active || !this.threadId || !active.nativeTurnId)
333
+ if (!active || !this.threadId)
232
334
  return { state: 'settled' };
335
+ if (!active.nativeTurnId)
336
+ throw new SessionControlError('backend', 'The operation is still pending without a native turn ID. Cancellation is not confirmed; inspect or restart the agent if it does not progress.');
233
337
  active.cancellationSource ??= source;
234
338
  this.events.emit('state', { turnId: active.promptId, status: 'running', origin: active.origin });
235
339
  this.conversation.appendSafe({
@@ -334,7 +438,12 @@ export class CodexAppServerSession {
334
438
  });
335
439
  this.conversation.close();
336
440
  await this.transport.close();
441
+ this.observation.publish();
442
+ }
443
+ taskNoticeBinding() {
444
+ return this.activeTurn && this.threadId ? { sessionGeneration: this.sessionGeneration, acpSessionId: this.threadId, promptId: this.activeTurn.promptId } : undefined;
337
445
  }
446
+ recordTaskCreated(binding, notice) { appendTaskCreated(this.conversation, binding, notice); }
338
447
  conversationPage(request = {}) {
339
448
  const floor = Number(this.conversationStartCursor ?? 0);
340
449
  const requested = Number(request.after ?? 0);
@@ -349,11 +458,42 @@ export class CodexAppServerSession {
349
458
  }
350
459
  return { ...page, events: visible, snapshot: this.conversationSnapshot() };
351
460
  }
461
+ subscribeConversationFailure(listener) {
462
+ return this.conversation.subscribeFailure(listener);
463
+ }
464
+ conversationReplayAvailable(expectedGeneration) {
465
+ return expectedGeneration === this.sessionGeneration && this.conversation.generationDurable(expectedGeneration);
466
+ }
467
+ replayConversation(request) {
468
+ if (request.expectedGeneration !== this.sessionGeneration)
469
+ throw new Error('session generation changed');
470
+ return this.conversation.replay(request);
471
+ }
472
+ observeConversation(listener) {
473
+ return this.observation.observe(listener);
474
+ }
475
+ captureObservation() {
476
+ const snapshot = this.snapshot();
477
+ return {
478
+ ...this.conversationSnapshot(),
479
+ ...pendingInventory(this.pendingPrompts),
480
+ ledgerBarrier: Number(this.conversation.lastCursor() ?? 0),
481
+ alive: snapshot.alive,
482
+ readiness: snapshot.alive ? snapshot.readiness : 'offline',
483
+ activePromptIds: [...(this.activeTurn?.promptIds ?? [])],
484
+ pendingPermissions: [...this.pendingPermissions].flatMap(([permissionId, pending]) => pending.presented ? [{ permissionId, ...pending.presented }] : []),
485
+ commands: [{ name: 'compact', description: textBlock('Compact session context') }],
486
+ runtimeModel: snapshot.runtimeModel,
487
+ reasoningEffort: snapshot.reasoningEffort,
488
+ permissionMode: snapshot.permissionMode,
489
+ };
490
+ }
352
491
  conversationSnapshot() {
353
492
  return {
354
493
  sessionGeneration: this.sessionGeneration,
355
494
  readiness: this.isAlive() ? this.readiness : 'offline',
356
495
  queueDepth: this.queueDepth,
496
+ ...pendingInventory(this.pendingPrompts),
357
497
  pendingPermissionIds: [...this.pendingPermissions.keys()],
358
498
  ...(this.conversation.degraded ? { historyDegraded: true } : {}),
359
499
  };
@@ -367,11 +507,16 @@ export class CodexAppServerSession {
367
507
  const existing = this.conversation.receiptFor(command.commandId, bodyDigest);
368
508
  if (existing)
369
509
  return existing;
510
+ if (command.expectedSessionGeneration !== undefined && command.expectedSessionGeneration !== this.conversationSnapshot().sessionGeneration)
511
+ throw new Error('session_changed: Agent session changed. Record a new voice message.');
512
+ if (command.requireIdle && (this.queueDepth > 0 || this.conversationSnapshot().readiness !== 'idle'))
513
+ throw new Error('voice_busy: Agent is already working. Wait for the current turn.');
370
514
  const queued = await this.queuePrompt(command.text, {
371
515
  origin: { kind: 'owner-admin-console', commandId: command.commandId },
372
516
  actor: { browserSession: command.actorBrowserSession },
373
517
  });
374
518
  const receipt = {
519
+ sessionGeneration: this.sessionGeneration,
375
520
  commandId: command.commandId, promptId: queued.promptId,
376
521
  state: queued.queuedBehind ? 'queued' : 'starting', queuedBehind: queued.queuedBehind,
377
522
  acceptedAt: new Date().toISOString(), eventCursor: this.conversation.lastCursor() ?? '0',
@@ -387,6 +532,8 @@ export class CodexAppServerSession {
387
532
  this.transport.notify('initialized');
388
533
  const persisted = this.options.mode === 'resume' && existsSync(this.threadFile)
389
534
  ? readFileSync(this.threadFile, 'utf8').trim() : '';
535
+ if (this.options.requireResume && !persisted)
536
+ throw new Error('TASK_CONTEXT_RESUME_UNAVAILABLE');
390
537
  const common = {
391
538
  cwd: this.options.cwd,
392
539
  approvalPolicy: this.options.approvalPolicy,
@@ -406,6 +553,8 @@ export class CodexAppServerSession {
406
553
  this.threadId = string(thread?.id);
407
554
  if (!this.threadId)
408
555
  throw new Error('Codex app-server did not return a thread id');
556
+ if (this.options.requireResume && this.threadId !== persisted)
557
+ throw new Error('TASK_CONTEXT_RESUME_MISMATCH');
409
558
  writeFileSync(this.threadFile, this.threadId + '\n', { mode: 0o600 });
410
559
  const model = string(response.model) ?? this.options.model ?? undefined;
411
560
  if (model)
@@ -415,10 +564,15 @@ export class CodexAppServerSession {
415
564
  this.reasoningEffort = { value: effort };
416
565
  this.readiness = 'idle';
417
566
  this.events.emit('state', { status: 'idle', text: `Codex thread ${this.threadId}` });
567
+ this.conversation.appendSafe({
568
+ kind: 'capabilities.updated', sessionGeneration: this.sessionGeneration,
569
+ payload: { commands: [{ name: 'compact', description: textBlock('Compact session context') }] },
570
+ });
418
571
  this.conversation.appendSafe({
419
572
  kind: 'session.state', sessionGeneration: this.sessionGeneration,
420
573
  payload: { status: 'idle' },
421
574
  });
575
+ this.observation.publish();
422
576
  }
423
577
  recoverOpenPrompts() {
424
578
  for (const open of this.conversation.openPrompts()) {
@@ -433,15 +587,27 @@ export class CodexAppServerSession {
433
587
  });
434
588
  continue;
435
589
  }
436
- this.queueDepth++;
437
590
  const origin = open.commandId
438
591
  ? { kind: 'owner-admin-console', commandId: open.commandId }
439
592
  : undefined;
440
- const run = this.promptTail.then(() => this.runPrompt(open.text, open.promptId, origin));
441
- this.promptTail = run.then(() => undefined, () => undefined);
442
- void run.finally(() => { this.queueDepth = Math.max(0, this.queueDepth - 1); });
593
+ const recovered = { promptId: open.promptId, text: open.text, ...(origin ? { origin } : {}) };
594
+ if (this.options.deferRecoveredPrompts)
595
+ this.deferredRecovered.push(recovered);
596
+ else
597
+ this.dispatchRecovered(recovered);
443
598
  }
444
599
  }
600
+ /** Dispatch recovered prompts once the caller's control plane is listening. */
601
+ activateRecoveredPrompts() {
602
+ for (const recovered of this.deferredRecovered.splice(0))
603
+ this.dispatchRecovered(recovered);
604
+ }
605
+ dispatchRecovered({ promptId, text, origin }) {
606
+ this.queueDepth++;
607
+ const run = this.enqueue(promptId, text, origin);
608
+ this.observation.publish();
609
+ void run.finally(() => { this.queueDepth = Math.max(0, this.queueDepth - 1); this.observation.publish(); });
610
+ }
445
611
  admit(promptId, text, queuedBehind, options) {
446
612
  const { source, persistBody } = sourceFor(options.origin);
447
613
  const bytes = Buffer.byteLength(text);
@@ -470,30 +636,44 @@ export class CodexAppServerSession {
470
636
  else
471
637
  this.conversation.appendSafe(draft);
472
638
  }
473
- async runPrompt(text, promptId, origin) {
639
+ async runPrompt(members) {
640
+ const { text, promptId, origin } = members[0];
474
641
  if (!this.threadId || !this.transport.isAlive())
475
642
  return turnResult(false, 'failed', this.lastError ?? 'Codex app-server session is offline');
476
643
  let settle;
477
644
  const settled = new Promise(resolveResult => { settle = resolveResult; });
478
- const active = { promptId, origin, output: '', settled, settle };
645
+ const active = {
646
+ promptId, origin, output: '', settled, settle,
647
+ promptIds: members.map(member => member.promptId),
648
+ console: members.some(member => member.origin?.kind === 'owner-admin-console'),
649
+ };
479
650
  this.activeTurn = active;
480
651
  this.finalAnswerObserved = false;
481
652
  this.activeItems.clear();
482
653
  this.readiness = 'running';
654
+ this.observation.publish();
483
655
  this.events.emit('state', { turnId: promptId, status: 'running', origin });
484
- this.conversation.appendSafe({
656
+ members.forEach((member, index) => this.conversation.appendSafe({
485
657
  kind: 'prompt.started', sessionGeneration: this.sessionGeneration,
486
- promptId, turnId: promptId, source: sourceFor(origin).source, payload: {},
487
- });
658
+ promptId: member.promptId, turnId: promptId, source: sourceFor(member.origin).source,
659
+ payload: members.length > 1 ? { batch: { turnId: promptId, index, size: members.length } } : {},
660
+ }));
488
661
  try {
662
+ if (text.trim() === '/compact') {
663
+ // The acknowledgement is not completion. Standard turn notifications
664
+ // settle the same queued prompt and durable browser receipt.
665
+ await this.transport.request('thread/compact/start', { threadId: this.threadId });
666
+ return await settled;
667
+ }
489
668
  const response = await this.transport.request('turn/start', {
490
669
  threadId: this.threadId,
491
- input: [{ type: 'text', text, text_elements: [] }],
670
+ // One unchanged user text item per admitted prompt, in admission order.
671
+ input: members.map(member => ({ type: 'text', text: member.text, text_elements: [] })),
492
672
  approvalPolicy: this.options.approvalPolicy,
493
673
  model: this.options.model ?? null,
494
674
  effort: this.options.effort ?? null,
495
- ...(nativePromptAdditionalContext(origin)
496
- ? { additionalContext: nativePromptAdditionalContext(origin) } : {}),
675
+ ...(nativeBatchAdditionalContext(members)
676
+ ? { additionalContext: nativeBatchAdditionalContext(members) } : {}),
497
677
  });
498
678
  const turn = isObject(response.turn) ? response.turn : undefined;
499
679
  active.nativeTurnId ??= string(turn?.id);
@@ -699,7 +879,7 @@ export class CodexAppServerSession {
699
879
  promptId: this.activeTurn?.promptId, turnId: this.activeTurn?.promptId,
700
880
  messageId: id, source: 'agent',
701
881
  payload: {
702
- role: 'assistant', content: textBlock(delta, scheduled ? SCHEDULED_REDACTION : phase === 'commentary' ? COMMENTARY_REDACTION : undefined),
882
+ role: 'assistant', content: textBlock(delta, scheduled ? SCHEDULED_REDACTION : undefined),
703
883
  },
704
884
  });
705
885
  }
@@ -746,6 +926,10 @@ export class CodexAppServerSession {
746
926
  toolCallId: scheduled ? 'scheduled-loop-tool' : id, snapshot,
747
927
  title: scheduled ? 'scheduled-loop tool' : tool.title, status: tool.status,
748
928
  kind: string(item.type),
929
+ ...(!scheduled && item.arguments !== undefined ? { rawInput: boundedJson(item.arguments) } : {}),
930
+ ...(!scheduled && item.type === 'commandExecution' ? { rawInput: boundedJson({ command: item.command, cwd: item.cwd }), ...(item.aggregatedOutput !== undefined ? { rawOutput: boundedJson({ output: item.aggregatedOutput, exitCode: item.exitCode }) } : {}) } : {}),
931
+ ...(!scheduled && item.type === 'fileChange' && item.changes !== undefined ? { rawOutput: boundedJson(item.changes) } : {}),
932
+ ...(!scheduled && (item.result !== undefined || item.error !== undefined) ? { rawOutput: boundedJson({ result: item.result, error: item.error }) } : {}),
749
933
  },
750
934
  });
751
935
  }
@@ -768,14 +952,17 @@ export class CodexAppServerSession {
768
952
  cancellationSource: active.cancellationSource,
769
953
  });
770
954
  this.events.emit('state', { status: this.readiness });
771
- this.conversation.appendSafe({
772
- kind: 'turn.completed', sessionGeneration: this.sessionGeneration,
773
- promptId: active.promptId, turnId: active.promptId,
774
- payload: {
775
- outcome, ...(detail ? { stopReason: detail } : {}),
776
- ...(active.cancellationSource ? { cancellationSource: active.cancellationSource } : {}),
777
- },
778
- });
955
+ // Every member closes with the shared outcome, so none is left waiting.
956
+ for (const member of active.promptIds)
957
+ this.conversation.appendSafe({
958
+ kind: 'turn.completed', sessionGeneration: this.sessionGeneration,
959
+ promptId: member, turnId: active.promptId,
960
+ payload: {
961
+ outcome, ...(detail ? { stopReason: detail } : {}),
962
+ ...(active.cancellationSource ? { cancellationSource: active.cancellationSource } : {}),
963
+ },
964
+ });
965
+ this.observation.publish();
779
966
  active.settle(result);
780
967
  }
781
968
  /**
@@ -939,7 +1126,6 @@ export class CodexAppServerSession {
939
1126
  this.resolvePermission(permissionId, pending, 'denied', 'automatic', 'deny_once', unattended ? 'permissions.unattended=deny' : 'permissions.approval=deny', unattended ? 'no controller is attached' : 'the role denies permission requests');
940
1127
  return;
941
1128
  }
942
- this.pendingPermissions.set(permissionId, pending);
943
1129
  this.readiness = 'awaiting_permission';
944
1130
  const timeoutMs = this.options.permissionTimeoutMs ?? PERMISSION_TIMEOUT_MS;
945
1131
  const expiresAt = new Date(Date.now() + timeoutMs).toISOString();
@@ -949,19 +1135,23 @@ export class CodexAppServerSession {
949
1135
  ?? (method === 'item/fileChange/requestApproval' ? 'Apply file changes'
950
1136
  : method === 'item/permissions/requestApproval' ? 'Grant additional permissions'
951
1137
  : 'Run command');
1138
+ const presented = { toolCallId, title, options, expiresAt };
1139
+ pending.presented = presented;
1140
+ this.pendingPermissions.set(permissionId, pending);
952
1141
  this.events.emit('permission', {
953
1142
  turnId: this.activeTurn?.promptId, origin: this.activeTurn?.origin,
954
- permissionId, toolCallId, title, status: 'pending', options,
1143
+ permissionId, ...presented, status: 'pending',
955
1144
  });
956
1145
  this.conversation.appendSafe({
957
1146
  kind: 'permission.requested', sessionGeneration: this.sessionGeneration,
958
1147
  permissionId, promptId: this.activeTurn?.promptId, turnId: this.activeTurn?.promptId,
959
- toolCallId, payload: { toolCallId, title, options, expiresAt },
1148
+ toolCallId, payload: presented,
960
1149
  });
961
1150
  pending.expiry = setTimeout(() => {
962
1151
  this.autoResolvePermission(permissionId, pending, undefined, `no decision arrived within ${Math.round(timeoutMs / 1000)}s`);
963
1152
  }, timeoutMs);
964
1153
  pending.expiry.unref?.();
1154
+ this.observation.publish();
965
1155
  }
966
1156
  serverRequestResolved(params) {
967
1157
  const requestId = typeof params.requestId === 'string' || typeof params.requestId === 'number'
@@ -987,6 +1177,8 @@ export class CodexAppServerSession {
987
1177
  this.resolvePermission(permissionId, pending, 'denied', 'automatic', 'deny_once', policy, reason);
988
1178
  }
989
1179
  resolvePermission(permissionId, pending, decision, decisionSource, optionId, policy, reason) {
1180
+ if (!this.pendingPermissions.size && this.readiness === 'awaiting_permission')
1181
+ this.readiness = 'running';
990
1182
  this.events.emit('permission', {
991
1183
  turnId: this.activeTurn?.promptId, origin: this.activeTurn?.origin,
992
1184
  permissionId, toolCallId: pending.toolCallId, status: 'completed', decision,
@@ -999,8 +1191,7 @@ export class CodexAppServerSession {
999
1191
  payload: { decision, decisionSource, ...(optionId ? { optionId } : {}),
1000
1192
  ...(policy ? { policy } : {}), ...(reason ? { reason } : {}) },
1001
1193
  });
1002
- if (!this.pendingPermissions.size && this.readiness === 'awaiting_permission')
1003
- this.readiness = 'running';
1194
+ this.observation.publish();
1004
1195
  this.scheduleTerminalReconciliation();
1005
1196
  }
1006
1197
  currentEvent(event) {
@@ -1048,10 +1239,12 @@ export class CodexAppServerSession {
1048
1239
  if (this.activeTurn)
1049
1240
  this.finishTurn('failed', this.lastError);
1050
1241
  }
1242
+ this.observation.publish();
1051
1243
  }
1052
1244
  fail(error) {
1053
1245
  this.lastError = error instanceof Error ? error.message : String(error);
1054
1246
  this.readiness = 'failed';
1055
1247
  this.events.emit('error', { text: this.lastError });
1248
+ this.observation.publish();
1056
1249
  }
1057
1250
  }
@@ -1,4 +1,7 @@
1
+ import type { LayoutControlRequest } from '../rooms-tasks/layout-control.js';
2
+ import type { SupervisorCorrespondence, AgentHistoryQuery } from '../agent-ours/correspondence.js';
1
3
  import { type Socket } from 'node:net';
4
+ import { type PassiveConversationFollowRequest } from './conversation-replay.js';
2
5
  import type { AgentSession, ControlFailureKind, SessionEvent, SessionSnapshot } from './types.js';
3
6
  import type { OwnerChannelHandle, OwnerChannelManagementRequest } from '../owner-channel/channel.js';
4
7
  import type { ScheduledLoopManagerHandle } from '../loops/manager.js';
@@ -9,8 +12,13 @@ export interface ControlRequest {
9
12
  version: 1 | 2 | 3;
10
13
  id: string;
11
14
  token: string;
12
- command: 'status' | 'snapshot' | 'submit_prompt' | 'respond_permission' | 'interrupt' | 'follow' | 'events_since' | 'owner_channel_manage' | 'loop_status' | 'loop_run_now' | 'loop_disable' | 'loop_enable' | 'reload_config' | 'conversation_page' | 'conversation_follow' | 'submit_prompt_v2' | 'interrupt_v2' | 'respond_permission_v2' | 'fleet_spawn' | 'fleet_audit_begin' | 'fleet_audit_present' | 'fleet_audit_finish';
15
+ command: 'status' | 'snapshot' | 'submit_prompt' | 'respond_permission' | 'interrupt' | 'follow' | 'events_since' | 'owner_channel_manage' | 'loop_status' | 'loop_run_now' | 'loop_disable' | 'loop_enable' | 'reload_config' | 'conversation_page' | 'conversation_follow' | 'submit_prompt_v2' | 'submit_voice_prompt' | 'interrupt_v2' | 'interrupt_voice_v2' | 'layout_control' | 'agent_contacts' | 'agent_history' | 'respond_permission_v2' | 'fleet_spawn' | 'fleet_audit_begin' | 'fleet_audit_present' | 'fleet_audit_finish';
16
+ layout?: LayoutControlRequest;
17
+ agentHistory?: AgentHistoryQuery;
13
18
  text?: string;
19
+ expectedSessionGeneration?: string;
20
+ requireIdle?: boolean;
21
+ promptId?: string;
14
22
  permissionId?: string;
15
23
  optionId?: string;
16
24
  since?: number;
@@ -19,7 +27,8 @@ export interface ControlRequest {
19
27
  ownerChannel?: OwnerChannelManagementRequest;
20
28
  loop?: string;
21
29
  /** Conversation cursor: replay strictly after this durable seq. */
22
- after?: string;
30
+ after?: string | number;
31
+ expectedGeneration?: string;
23
32
  limit?: number;
24
33
  /** Idempotency key for v3 mutations. */
25
34
  commandId?: string;
@@ -112,9 +121,13 @@ export declare class RoleControlServer {
112
121
  private readonly sockets;
113
122
  /** Interrupt idempotency: same command id returns the first receipt. */
114
123
  private readonly interruptCommands;
124
+ private correspondence?;
125
+ setCorrespondence(value: SupervisorCorrespondence): void;
115
126
  private ownerChannel?;
116
127
  private loopManager?;
117
128
  private reloadConfig?;
129
+ private layoutControl?;
130
+ setLayoutControl(handler: (request: LayoutControlRequest) => Promise<unknown>): void;
118
131
  private fleetSpawner?;
119
132
  private fleetAuditor?;
120
133
  constructor(stateDir: string, session: AgentSession, log: (line: string) => void);
@@ -130,6 +143,7 @@ export declare class RoleControlServer {
130
143
  private handle;
131
144
  /** Version and capability gate shared by every conversation v3 command. */
132
145
  private requireConversation;
146
+ private observationFeatures;
133
147
  private write;
134
148
  }
135
149
  /**
@@ -149,7 +163,7 @@ export declare function followControl(stateDir: string, onMessage: (message: Rec
149
163
  * `{ version, conversationEvent }`. Closing the socket detaches the
150
164
  * controller-presence this connection contributed.
151
165
  */
152
- export declare function followConversation(stateDir: string, after: string | undefined, onMessage: (message: Record<string, unknown>) => void): Promise<{
166
+ export declare function followConversation(stateDir: string, after: string | undefined | PassiveConversationFollowRequest, onMessage: (message: Record<string, unknown>) => void): Promise<{
153
167
  socket: Socket;
154
168
  close(): void;
155
169
  }>;