@ours.network/fleet 1.2.0-nightly.9 → 2.0.0

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 (429) hide show
  1. package/README.md +280 -68
  2. package/dist/account-origin.d.ts +5 -0
  3. package/dist/account-origin.js +31 -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 +22 -0
  11. package/dist/agent-ours/mcp-endpoint.js +101 -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 +27 -1
  15. package/dist/agent-ours/service.js +107 -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 +31 -0
  19. package/dist/application/conversation-history.js +339 -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 +3 -3
  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/resource-observer.d.ts +43 -0
  30. package/dist/application/resource-observer.js +323 -0
  31. package/dist/application/role-creation-service.js +3 -2
  32. package/dist/application/role-removal-service.js +17 -3
  33. package/dist/application/role-repository.d.ts +3 -1
  34. package/dist/application/role-repository.js +89 -54
  35. package/dist/application/room-layout-definitions.d.ts +45 -0
  36. package/dist/application/room-layout-definitions.js +130 -0
  37. package/dist/application/session-control.d.ts +63 -17
  38. package/dist/application/session-control.js +221 -23
  39. package/dist/application/supervisor-ours-tools.js +5 -11
  40. package/dist/application/task-layouts.d.ts +91 -0
  41. package/dist/application/task-layouts.js +261 -0
  42. package/dist/application/task-room-service.d.ts +101 -3
  43. package/dist/application/task-room-service.js +286 -33
  44. package/dist/application/types.d.ts +2 -0
  45. package/dist/atomic-file.d.ts +34 -1
  46. package/dist/atomic-file.js +161 -18
  47. package/dist/briefing.d.ts +3 -1
  48. package/dist/briefing.js +120 -31
  49. package/dist/build-info.json +10 -5
  50. package/dist/capabilities.d.ts +9 -1
  51. package/dist/capabilities.js +13 -0
  52. package/dist/cli.js +391 -38
  53. package/dist/client-profile.d.ts +5 -17
  54. package/dist/client-profile.js +4 -127
  55. package/dist/config.d.ts +45 -0
  56. package/dist/config.js +57 -6
  57. package/dist/creation.d.ts +1 -1
  58. package/dist/creation.js +4 -4
  59. package/dist/daemon-recovery.d.ts +14 -9
  60. package/dist/daemon-recovery.js +124 -115
  61. package/dist/docs.d.ts +1 -1
  62. package/dist/docs.js +214 -20
  63. package/dist/doctor.d.ts +4 -1
  64. package/dist/doctor.js +75 -60
  65. package/dist/erased-resources.d.ts +9 -0
  66. package/dist/erased-resources.js +87 -0
  67. package/dist/file-delivery/reader.d.ts +15 -0
  68. package/dist/file-delivery/reader.js +63 -0
  69. package/dist/file-delivery/store.d.ts +15 -0
  70. package/dist/file-delivery/store.js +124 -0
  71. package/dist/file-delivery/types.d.ts +19 -0
  72. package/dist/file-delivery/types.js +1 -0
  73. package/dist/fleet-command-audit.d.ts +13 -0
  74. package/dist/fleet-command-audit.js +31 -9
  75. package/dist/harness/agent-session.d.ts +4 -0
  76. package/dist/harness/claude-code-session.js +1 -1
  77. package/dist/harness/claude-code.js +21 -11
  78. package/dist/harness/claude-runtime.d.ts +12 -0
  79. package/dist/harness/claude-runtime.js +43 -0
  80. package/dist/harness/codex-app-server-proxy.d.ts +4 -1
  81. package/dist/harness/codex-app-server-proxy.js +41 -5
  82. package/dist/harness/codex-reasoning.d.ts +5 -0
  83. package/dist/harness/codex-reasoning.js +12 -0
  84. package/dist/harness/codex-runtime.d.ts +11 -1
  85. package/dist/harness/codex-runtime.js +31 -4
  86. package/dist/harness/codex-session.js +2 -2
  87. package/dist/harness/codex.js +24 -12
  88. package/dist/init-wizard.d.ts +2 -0
  89. package/dist/init-wizard.js +38 -19
  90. package/dist/isolation/policy.js +6 -1
  91. package/dist/isolation/types.d.ts +5 -0
  92. package/dist/managed-cli.d.ts +253 -0
  93. package/dist/managed-cli.js +923 -0
  94. package/dist/managed-recovery.d.ts +13 -0
  95. package/dist/managed-recovery.js +31 -0
  96. package/dist/minimal-setup.d.ts +2 -0
  97. package/dist/minimal-setup.js +44 -0
  98. package/dist/monitor.d.ts +9 -34
  99. package/dist/monitor.js +90 -153
  100. package/dist/notifications/fleet-producer.d.ts +31 -0
  101. package/dist/notifications/fleet-producer.js +351 -0
  102. package/dist/notifications/outbox.d.ts +59 -0
  103. package/dist/notifications/outbox.js +199 -0
  104. package/dist/notifications/target-cleanup.d.ts +16 -0
  105. package/dist/notifications/target-cleanup.js +75 -0
  106. package/dist/notifications/task-producer.d.ts +20 -0
  107. package/dist/notifications/task-producer.js +100 -0
  108. package/dist/ops.d.ts +2 -0
  109. package/dist/ops.js +20 -3
  110. package/dist/owner-channel/channel.js +17 -6
  111. package/dist/owner-channel/commands.d.ts +4 -0
  112. package/dist/owner-channel/commands.js +8 -0
  113. package/dist/owner-channel/lifecycle-outbox.js +4 -3
  114. package/dist/owner-channel/ours-client.js +2 -17
  115. package/dist/paths.d.ts +5 -0
  116. package/dist/paths.js +5 -0
  117. package/dist/preset-migration.js +55 -0
  118. package/dist/process-incarnation.d.ts +23 -0
  119. package/dist/process-incarnation.js +42 -0
  120. package/dist/reminders/manager.d.ts +75 -0
  121. package/dist/reminders/manager.js +278 -0
  122. package/dist/reminders/runtime.d.ts +27 -0
  123. package/dist/reminders/runtime.js +32 -0
  124. package/dist/reminders/schedule.d.ts +37 -0
  125. package/dist/reminders/schedule.js +104 -0
  126. package/dist/reminders/store.d.ts +341 -0
  127. package/dist/reminders/store.js +762 -0
  128. package/dist/reminders/tools.d.ts +20 -0
  129. package/dist/reminders/tools.js +114 -0
  130. package/dist/resolved-plan.js +1 -0
  131. package/dist/rooms-tasks/add-member.d.ts +48 -0
  132. package/dist/rooms-tasks/add-member.js +84 -0
  133. package/dist/rooms-tasks/archived-absence.d.ts +4 -0
  134. package/dist/rooms-tasks/archived-absence.js +11 -0
  135. package/dist/rooms-tasks/cli.js +182 -5
  136. package/dist/rooms-tasks/close.d.ts +5 -2
  137. package/dist/rooms-tasks/close.js +224 -36
  138. package/dist/rooms-tasks/config.d.ts +1 -1
  139. package/dist/rooms-tasks/config.js +11 -4
  140. package/dist/rooms-tasks/cowork-adapter.d.ts +12 -5
  141. package/dist/rooms-tasks/cowork-adapter.js +15 -121
  142. package/dist/rooms-tasks/cowork-http.js +56 -6
  143. package/dist/rooms-tasks/deletion.d.ts +1 -1
  144. package/dist/rooms-tasks/deletion.js +66 -10
  145. package/dist/rooms-tasks/erasure.d.ts +6 -0
  146. package/dist/rooms-tasks/erasure.js +173 -0
  147. package/dist/rooms-tasks/external-worker.d.ts +1 -1
  148. package/dist/rooms-tasks/external-worker.js +3 -4
  149. package/dist/rooms-tasks/layout-binding-client.d.ts +11 -0
  150. package/dist/rooms-tasks/layout-binding-client.js +56 -0
  151. package/dist/rooms-tasks/layout-binding-grants.d.ts +21 -0
  152. package/dist/rooms-tasks/layout-binding-grants.js +128 -0
  153. package/dist/rooms-tasks/layout-cli.d.ts +4 -0
  154. package/dist/rooms-tasks/layout-cli.js +107 -0
  155. package/dist/rooms-tasks/layout-config.d.ts +11 -0
  156. package/dist/rooms-tasks/layout-config.js +89 -0
  157. package/dist/rooms-tasks/layout-control.d.ts +21 -0
  158. package/dist/rooms-tasks/layout-control.js +52 -0
  159. package/dist/rooms-tasks/layout-member-retirement.d.ts +10 -0
  160. package/dist/rooms-tasks/layout-member-retirement.js +90 -0
  161. package/dist/rooms-tasks/layout-service.d.ts +43 -0
  162. package/dist/rooms-tasks/layout-service.js +203 -0
  163. package/dist/rooms-tasks/layout.d.ts +121 -0
  164. package/dist/rooms-tasks/layout.js +286 -0
  165. package/dist/rooms-tasks/legacy-task-member.d.ts +19 -0
  166. package/dist/rooms-tasks/legacy-task-member.js +116 -0
  167. package/dist/rooms-tasks/live-readiness.d.ts +18 -0
  168. package/dist/rooms-tasks/live-readiness.js +85 -0
  169. package/dist/rooms-tasks/member-ownership.d.ts +5 -0
  170. package/dist/rooms-tasks/member-ownership.js +40 -0
  171. package/dist/rooms-tasks/member-startup.d.ts +1 -0
  172. package/dist/rooms-tasks/member-startup.js +2 -0
  173. package/dist/rooms-tasks/provision.d.ts +3 -0
  174. package/dist/rooms-tasks/provision.js +101 -49
  175. package/dist/rooms-tasks/recovery.d.ts +19 -0
  176. package/dist/rooms-tasks/recovery.js +110 -0
  177. package/dist/rooms-tasks/room-state.d.ts +4 -2
  178. package/dist/rooms-tasks/room-state.js +47 -8
  179. package/dist/rooms-tasks/task-review.d.ts +113 -0
  180. package/dist/rooms-tasks/task-review.js +561 -0
  181. package/dist/rooms-tasks/task-service-retirement.d.ts +11 -0
  182. package/dist/rooms-tasks/task-service-retirement.js +21 -0
  183. package/dist/rooms-tasks/task-state.d.ts +51 -5
  184. package/dist/rooms-tasks/task-state.js +358 -50
  185. package/dist/rooms-tasks/task-tools.d.ts +35 -0
  186. package/dist/rooms-tasks/task-tools.js +134 -0
  187. package/dist/rooms-tasks/types.d.ts +78 -0
  188. package/dist/rooms-tasks/workspace-artifacts.d.ts +6 -0
  189. package/dist/rooms-tasks/workspace-artifacts.js +93 -0
  190. package/dist/rooms-tasks/workspace.d.ts +35 -0
  191. package/dist/rooms-tasks/workspace.js +325 -0
  192. package/dist/runner.d.ts +23 -4
  193. package/dist/runner.js +409 -61
  194. package/dist/session/acp.d.ts +75 -2
  195. package/dist/session/acp.js +345 -82
  196. package/dist/session/arbiter.d.ts +98 -0
  197. package/dist/session/arbiter.js +272 -3
  198. package/dist/session/codex-app-server.d.ts +45 -1
  199. package/dist/session/codex-app-server.js +225 -32
  200. package/dist/session/control.d.ts +17 -3
  201. package/dist/session/control.js +219 -23
  202. package/dist/session/conversation-normalizer.d.ts +2 -1
  203. package/dist/session/conversation-normalizer.js +1 -1
  204. package/dist/session/conversation-observation.d.ts +25 -0
  205. package/dist/session/conversation-observation.js +100 -0
  206. package/dist/session/conversation-replay.d.ts +50 -0
  207. package/dist/session/conversation-replay.js +203 -0
  208. package/dist/session/conversation-store.d.ts +15 -1
  209. package/dist/session/conversation-store.js +213 -26
  210. package/dist/session/conversation-types.d.ts +57 -4
  211. package/dist/session/prompt-batch.d.ts +79 -0
  212. package/dist/session/prompt-batch.js +120 -0
  213. package/dist/session/task-notice.d.ts +14 -0
  214. package/dist/session/task-notice.js +13 -0
  215. package/dist/session/types.d.ts +42 -1
  216. package/dist/setup-tunnel-preflight.d.ts +34 -0
  217. package/dist/setup-tunnel-preflight.js +62 -0
  218. package/dist/socket-path.d.ts +2 -0
  219. package/dist/socket-path.js +22 -0
  220. package/dist/spawn.d.ts +5 -1
  221. package/dist/spawn.js +40 -4
  222. package/dist/startup-prompt.d.ts +15 -0
  223. package/dist/startup-prompt.js +71 -0
  224. package/dist/startup-readiness.d.ts +20 -1
  225. package/dist/startup-readiness.js +66 -3
  226. package/dist/startup-telemetry.d.ts +16 -0
  227. package/dist/startup-telemetry.js +46 -0
  228. package/dist/subscriptions/cli.d.ts +91 -0
  229. package/dist/subscriptions/cli.js +223 -0
  230. package/dist/subscriptions/launch.d.ts +37 -0
  231. package/dist/subscriptions/launch.js +93 -0
  232. package/dist/subscriptions/login.d.ts +77 -0
  233. package/dist/subscriptions/login.js +215 -0
  234. package/dist/subscriptions/observed.d.ts +7 -0
  235. package/dist/subscriptions/observed.js +44 -0
  236. package/dist/subscriptions/probe.d.ts +10 -0
  237. package/dist/subscriptions/probe.js +73 -0
  238. package/dist/subscriptions/service.d.ts +102 -0
  239. package/dist/subscriptions/service.js +364 -0
  240. package/dist/subscriptions/store.d.ts +71 -0
  241. package/dist/subscriptions/store.js +143 -0
  242. package/dist/supervisor/adoption.d.ts +8 -0
  243. package/dist/supervisor/adoption.js +78 -0
  244. package/dist/supervisor/catalog.d.ts +62 -0
  245. package/dist/supervisor/catalog.js +254 -0
  246. package/dist/supervisor/fleet.d.ts +8 -0
  247. package/dist/supervisor/fleet.js +89 -0
  248. package/dist/supervisor/index.js +3 -6
  249. package/dist/supervisor/launchd.d.ts +1 -1
  250. package/dist/supervisor/launchd.js +26 -13
  251. package/dist/supervisor/legacy.d.ts +35 -0
  252. package/dist/supervisor/legacy.js +524 -0
  253. package/dist/supervisor/manager.d.ts +15 -0
  254. package/dist/supervisor/manager.js +270 -0
  255. package/dist/supervisor/registration-refresh.d.ts +45 -0
  256. package/dist/supervisor/registration-refresh.js +266 -0
  257. package/dist/supervisor/scope.d.ts +4 -0
  258. package/dist/supervisor/scope.js +10 -0
  259. package/dist/supervisor/systemd.d.ts +2 -2
  260. package/dist/supervisor/systemd.js +18 -37
  261. package/dist/task-supervision.d.ts +9 -0
  262. package/dist/task-supervision.js +145 -0
  263. package/dist/temp-idle.d.ts +17 -0
  264. package/dist/temp-idle.js +42 -0
  265. package/dist/temp-lifecycle.d.ts +23 -8
  266. package/dist/temp-lifecycle.js +123 -66
  267. package/dist/temp-supervisor-recovery.d.ts +1 -1
  268. package/dist/temp-supervisor-recovery.js +2 -2
  269. package/dist/tunnel-setup-completion.d.ts +7 -0
  270. package/dist/tunnel-setup-completion.js +13 -0
  271. package/dist/tunnel-setup-input.d.ts +19 -0
  272. package/dist/tunnel-setup-input.js +130 -0
  273. package/dist/watchdog/query.d.ts +3 -1
  274. package/dist/watchdog/query.js +2 -1
  275. package/dist/web/agent-attachments.d.ts +29 -0
  276. package/dist/web/agent-attachments.js +162 -0
  277. package/dist/web/auth.d.ts +65 -2
  278. package/dist/web/auth.js +201 -11
  279. package/dist/web/available-port.d.ts +2 -0
  280. package/dist/web/available-port.js +23 -0
  281. package/dist/web/control.d.ts +3 -3
  282. package/dist/web/control.js +10 -8
  283. package/dist/web/conversation-stream-codec.d.ts +23 -0
  284. package/dist/web/conversation-stream-codec.js +110 -0
  285. package/dist/web/conversation-stream.d.ts +26 -0
  286. package/dist/web/conversation-stream.js +239 -0
  287. package/dist/web/events.d.ts +2 -0
  288. package/dist/web/events.js +9 -0
  289. package/dist/web/fleet-config-service.d.ts +7 -1
  290. package/dist/web/fleet-config-service.js +61 -16
  291. package/dist/web/prefix-gateway.d.ts +32 -0
  292. package/dist/web/prefix-gateway.js +248 -0
  293. package/dist/web/resource-views.d.ts +138 -0
  294. package/dist/web/resource-views.js +519 -0
  295. package/dist/web/runtime.d.ts +3 -1
  296. package/dist/web/runtime.js +132 -34
  297. package/dist/web/server.d.ts +19 -0
  298. package/dist/web/server.js +893 -71
  299. package/dist/web/service.d.ts +11 -2
  300. package/dist/web/service.js +30 -4
  301. package/dist/web/workspace-devices.d.ts +107 -0
  302. package/dist/web/workspace-devices.js +277 -0
  303. package/dist/web/workspace-tunnel.d.ts +1 -0
  304. package/dist/web/workspace-tunnel.js +34 -0
  305. package/dist/workspace-enrollment.d.ts +83 -0
  306. package/dist/workspace-enrollment.js +605 -0
  307. package/dist/workspace-replacement.d.ts +66 -0
  308. package/dist/workspace-replacement.js +238 -0
  309. package/docs/acp-files.md +146 -0
  310. package/docs/conversation-stream.md +216 -0
  311. package/docs/fleet-migration.md +54 -0
  312. package/docs/live-voice.md +13 -0
  313. package/docs/room-layouts.md +227 -0
  314. package/docs/self-reminders.md +374 -0
  315. package/docs/task-progress-review.md +143 -0
  316. package/docs/task-workspaces.md +225 -0
  317. package/docs/validation/managed-cli-permissions.md +421 -0
  318. package/examples/room-layouts/fresh.yaml +27 -0
  319. package/examples/room-layouts/scoped.yaml +21 -0
  320. package/examples/room-layouts/shared.yaml +19 -0
  321. package/package.json +25 -20
  322. package/presets/README.md +78 -0
  323. package/presets/brain-catalog.json +8 -2
  324. package/presets/fleet/agent_templates/Critic.yaml +1 -1
  325. package/presets/fleet/agent_templates/Developer.yaml +1 -1
  326. package/presets/fleet/agent_templates/Engineer.yaml +5 -0
  327. package/presets/fleet/agent_templates/LocalCoordinator.yaml +6 -3
  328. package/presets/fleet/agents/FleetCoordinator.yaml +1 -1
  329. package/presets/fleet/brains/claude-fable-5-1-high.yaml +5 -0
  330. package/presets/fleet/brains/claude-fable-5-1-low.yaml +5 -0
  331. package/presets/fleet/brains/claude-fable-5-1-max.yaml +5 -0
  332. package/presets/fleet/brains/claude-fable-5-1-medium.yaml +5 -0
  333. package/presets/fleet/brains/claude-fable-5-1-xhigh.yaml +5 -0
  334. package/presets/fleet/brains/claude-fable-5-high.yaml +1 -1
  335. package/presets/fleet/brains/claude-fable-5-low.yaml +1 -1
  336. package/presets/fleet/brains/claude-fable-5-max.yaml +1 -1
  337. package/presets/fleet/brains/claude-fable-5-medium.yaml +1 -1
  338. package/presets/fleet/brains/claude-fable-5-xhigh.yaml +1 -1
  339. package/presets/fleet/brains/claude-haiku-4-5-20251001-default.yaml +4 -0
  340. package/presets/fleet/brains/claude-opus-5-5-high.yaml +5 -0
  341. package/presets/fleet/brains/claude-opus-5-5-low.yaml +5 -0
  342. package/presets/fleet/brains/claude-opus-5-5-max.yaml +5 -0
  343. package/presets/fleet/brains/claude-opus-5-5-medium.yaml +5 -0
  344. package/presets/fleet/brains/claude-opus-5-5-xhigh.yaml +5 -0
  345. package/presets/fleet/brains/claude-opus-5-high.yaml +1 -1
  346. package/presets/fleet/brains/claude-opus-5-low.yaml +1 -1
  347. package/presets/fleet/brains/claude-opus-5-max.yaml +1 -1
  348. package/presets/fleet/brains/claude-opus-5-medium.yaml +1 -1
  349. package/presets/fleet/brains/claude-opus-5-xhigh.yaml +1 -1
  350. package/presets/fleet/brains/claude-sonnet-5-high.yaml +1 -1
  351. package/presets/fleet/brains/claude-sonnet-5-low.yaml +1 -1
  352. package/presets/fleet/brains/claude-sonnet-5-max.yaml +1 -1
  353. package/presets/fleet/brains/claude-sonnet-5-medium.yaml +1 -1
  354. package/presets/fleet/brains/claude-sonnet-5-xhigh.yaml +1 -1
  355. package/presets/fleet/brains/codex-gpt-5-3-codex-spark-high.yaml +1 -1
  356. package/presets/fleet/brains/codex-gpt-5-3-codex-spark-low.yaml +1 -1
  357. package/presets/fleet/brains/codex-gpt-5-3-codex-spark-medium.yaml +1 -1
  358. package/presets/fleet/brains/codex-gpt-5-3-codex-spark-xhigh.yaml +1 -1
  359. package/presets/fleet/brains/codex-gpt-5-4-high.yaml +1 -1
  360. package/presets/fleet/brains/codex-gpt-5-4-low.yaml +1 -1
  361. package/presets/fleet/brains/codex-gpt-5-4-medium.yaml +1 -1
  362. package/presets/fleet/brains/codex-gpt-5-4-mini-high.yaml +1 -1
  363. package/presets/fleet/brains/codex-gpt-5-4-mini-low.yaml +1 -1
  364. package/presets/fleet/brains/codex-gpt-5-4-mini-medium.yaml +1 -1
  365. package/presets/fleet/brains/codex-gpt-5-4-mini-xhigh.yaml +1 -1
  366. package/presets/fleet/brains/codex-gpt-5-4-xhigh.yaml +1 -1
  367. package/presets/fleet/brains/codex-gpt-5-5-high.yaml +1 -1
  368. package/presets/fleet/brains/codex-gpt-5-5-low.yaml +1 -1
  369. package/presets/fleet/brains/codex-gpt-5-5-medium.yaml +1 -1
  370. package/presets/fleet/brains/codex-gpt-5-5-xhigh.yaml +1 -1
  371. package/presets/fleet/brains/codex-gpt-5-6-luna-high.yaml +1 -1
  372. package/presets/fleet/brains/codex-gpt-5-6-luna-low.yaml +1 -1
  373. package/presets/fleet/brains/codex-gpt-5-6-luna-max.yaml +1 -1
  374. package/presets/fleet/brains/codex-gpt-5-6-luna-medium.yaml +1 -1
  375. package/presets/fleet/brains/codex-gpt-5-6-luna-xhigh.yaml +1 -1
  376. package/presets/fleet/brains/codex-gpt-5-6-sol-high.yaml +1 -1
  377. package/presets/fleet/brains/codex-gpt-5-6-sol-low.yaml +1 -1
  378. package/presets/fleet/brains/codex-gpt-5-6-sol-max.yaml +1 -1
  379. package/presets/fleet/brains/codex-gpt-5-6-sol-medium.yaml +1 -1
  380. package/presets/fleet/brains/codex-gpt-5-6-sol-ultra.yaml +1 -1
  381. package/presets/fleet/brains/codex-gpt-5-6-sol-xhigh.yaml +1 -1
  382. package/presets/fleet/brains/codex-gpt-5-6-terra-high.yaml +1 -1
  383. package/presets/fleet/brains/codex-gpt-5-6-terra-low.yaml +1 -1
  384. package/presets/fleet/brains/codex-gpt-5-6-terra-max.yaml +1 -1
  385. package/presets/fleet/brains/codex-gpt-5-6-terra-medium.yaml +1 -1
  386. package/presets/fleet/brains/codex-gpt-5-6-terra-ultra.yaml +1 -1
  387. package/presets/fleet/brains/codex-gpt-5-6-terra-xhigh.yaml +1 -1
  388. package/presets/fleet/brains/codex-gpt-6-1-sol-high.yaml +5 -0
  389. package/presets/fleet/brains/codex-gpt-6-1-sol-low.yaml +5 -0
  390. package/presets/fleet/brains/codex-gpt-6-1-sol-max.yaml +5 -0
  391. package/presets/fleet/brains/codex-gpt-6-1-sol-medium.yaml +5 -0
  392. package/presets/fleet/brains/codex-gpt-6-1-sol-ultra.yaml +5 -0
  393. package/presets/fleet/brains/codex-gpt-6-1-sol-xhigh.yaml +5 -0
  394. package/presets/fleet/brains/codex-gpt-6-astra-high.yaml +1 -1
  395. package/presets/fleet/brains/codex-gpt-6-astra-low.yaml +1 -1
  396. package/presets/fleet/brains/codex-gpt-6-astra-max.yaml +1 -1
  397. package/presets/fleet/brains/codex-gpt-6-astra-medium.yaml +1 -1
  398. package/presets/fleet/brains/codex-gpt-6-astra-ultra.yaml +1 -1
  399. package/presets/fleet/brains/codex-gpt-6-astra-xhigh.yaml +1 -1
  400. package/presets/fleet/brains/codex-gpt-6-luna-high.yaml +5 -0
  401. package/presets/fleet/brains/codex-gpt-6-luna-low.yaml +5 -0
  402. package/presets/fleet/brains/codex-gpt-6-luna-max.yaml +5 -0
  403. package/presets/fleet/brains/codex-gpt-6-luna-medium.yaml +5 -0
  404. package/presets/fleet/brains/codex-gpt-6-luna-xhigh.yaml +5 -0
  405. package/presets/fleet/brains/codex-gpt-6-sol-high.yaml +5 -0
  406. package/presets/fleet/brains/codex-gpt-6-sol-low.yaml +5 -0
  407. package/presets/fleet/brains/codex-gpt-6-sol-max.yaml +5 -0
  408. package/presets/fleet/brains/codex-gpt-6-sol-medium.yaml +5 -0
  409. package/presets/fleet/brains/codex-gpt-6-sol-ultra.yaml +5 -0
  410. package/presets/fleet/brains/codex-gpt-6-sol-xhigh.yaml +5 -0
  411. package/presets/fleet/roles/Coordinator.yaml +21 -13
  412. package/presets/fleet/roles/Critic.yaml +24 -0
  413. package/presets/fleet/roles/Developer.yaml +32 -0
  414. package/presets/fleet/roles/Engineer.yaml +72 -0
  415. package/presets/fleet/roles/LocalCoordinator.yaml +17 -0
  416. package/presets/fleet/room_layouts/engineering.yaml +25 -0
  417. package/presets/fleet/room_layouts/pair.yaml +24 -0
  418. package/presets/fleet/room_layouts/single.yaml +17 -0
  419. package/presets/fleet/room_layouts/team.yaml +30 -0
  420. package/presets/fleet/room_templates/engineering.yaml +19 -0
  421. package/presets/manifest.json +2 -2
  422. package/dist/web-app/assets/index-59GF-gsZ.css +0 -1
  423. package/dist/web-app/assets/index-C0h3ALvs.js +0 -10
  424. package/dist/web-app/icons/ours-fleet-maskable.svg +0 -4
  425. package/dist/web-app/icons/ours-fleet.svg +0 -4
  426. package/dist/web-app/index.html +0 -17
  427. package/dist/web-app/manifest.webmanifest +0 -15
  428. package/dist/web-app/offline.html +0 -18
  429. package/dist/web-app/sw.js +0 -51
@@ -0,0 +1,56 @@
1
+ import { statSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { resolveBundledAcpAgent } from '../harness/acp-agent.js';
4
+ import { probeCodexRuntime } from '../harness/codex-runtime.js';
5
+ import { codexOfferedModels, profileEnv } from '../subscriptions/cli.js';
6
+ import { profileHome, readSubscriptionState } from '../subscriptions/store.js';
7
+ const KNOWN_FOR_MS = 5 * 60_000;
8
+ const UNKNOWN_FOR_MS = 10_000;
9
+ /** When the profile's sign-in last changed; a new sign-in must not reuse another account's answer. */
10
+ function signInStamp(home) {
11
+ try {
12
+ return statSync(join(home, 'auth.json')).mtimeMs;
13
+ }
14
+ catch {
15
+ return 0;
16
+ }
17
+ }
18
+ /**
19
+ * The models offered to the active Codex account by the runtime that sessions will actually use.
20
+ * An answer is reused only for the same executable, version, profile and sign-in.
21
+ */
22
+ export function createCodexModelDiscovery(overrides = {}) {
23
+ const deps = {
24
+ runtime: () => probeCodexRuntime(resolveBundledAcpAgent('@agentclientprotocol/codex-acp', 'codex-acp', 'codex-acp'), process.env),
25
+ ask: codexOfferedModels,
26
+ now: Date.now,
27
+ ...overrides,
28
+ };
29
+ let cached;
30
+ let pending;
31
+ return async () => {
32
+ let key, executable, env;
33
+ try {
34
+ const profileId = readSubscriptionState().providers.codex.activeProfileId;
35
+ const profile = profileHome('codex', profileId);
36
+ const runtime = await deps.runtime();
37
+ executable = runtime.executable;
38
+ env = profileEnv('CODEX_HOME', profileId, profile);
39
+ key = [runtime.executable, runtime.version, profileId, signInStamp(profile)].join('\n');
40
+ }
41
+ catch (error) {
42
+ return { state: 'unknown', reason: error instanceof Error ? error.message : String(error) };
43
+ }
44
+ if (cached && cached.key === key && cached.until > deps.now())
45
+ return cached.value;
46
+ if (pending?.key === key)
47
+ return pending.answer;
48
+ const answer = deps.ask(executable, env).then(value => {
49
+ cached = { key, until: deps.now() + (value.state === 'known' ? KNOWN_FOR_MS : UNKNOWN_FOR_MS), value };
50
+ return value;
51
+ }).finally(() => { if (pending?.key === key)
52
+ pending = undefined; });
53
+ pending = { key, answer };
54
+ return answer;
55
+ };
56
+ }
@@ -0,0 +1,31 @@
1
+ import type { ConversationEventV1 } from '../session/conversation-types.js';
2
+ import type { ConversationPageView } from './session-control.js';
3
+ /** Whether a ledger event belongs in the conversation: the live generation, or history of the resumed ACP session. */
4
+ export declare function conversationEventVisible(event: ConversationEventV1, sessionGeneration: string, resumedSessionId?: string): boolean;
5
+ export interface ConversationTailPage extends ConversationPageView {
6
+ /** Pass as `before` to read the next older page. */
7
+ olderCursor?: string;
8
+ hasOlder: boolean;
9
+ /** Latest page only: older events the view still needs, the current session's latest capabilities and still-pending permission requests. */
10
+ context: ConversationEventV1[];
11
+ }
12
+ /**
13
+ * The newest `limit` visible events before `before` (or the newest overall),
14
+ * read backwards from the ledger so opening a long session costs one page.
15
+ * `nextCursor` is the newest ledger position seen, for forward `after` paging.
16
+ */
17
+ export declare function conversationTailPage(stateDir: string, request: {
18
+ before?: string;
19
+ limit?: number;
20
+ }, snapshot: ConversationPageView['snapshot'], resumedSessionId?: string, signal?: AbortSignal): Promise<ConversationTailPage>;
21
+ /** Read the existing ACP session ledger without opening its writer/recovery store. */
22
+ export declare function resumedConversationPage(stateDir: string, request: {
23
+ after?: string;
24
+ limit?: number;
25
+ }, live: ConversationPageView, expectedSessionId: string): Promise<ConversationPageView>;
26
+ /** Download authorization requires an actual published attachment, never an orphan copy. */
27
+ export declare function conversationHasAttachment(stateDir: string, attachment: import('../file-delivery/types.js').DeliveredFile): Promise<boolean>;
28
+ export declare function conversationPreview(stateDir: string, signal: AbortSignal): Promise<{
29
+ text: string;
30
+ at: string;
31
+ }>;
@@ -0,0 +1,339 @@
1
+ import { createReadStream } from 'node:fs';
2
+ import { open, readFile, readdir, stat } from 'node:fs/promises';
3
+ import { join } from 'node:path';
4
+ import { createInterface } from 'node:readline';
5
+ const HISTORICAL_KINDS = ['file.attached', 'fleet.task_created', 'prompt.admitted', 'message.chunk', 'message.replace', 'tool.upsert', 'tool.content_chunk', 'turn.completed'];
6
+ /** Whether a ledger event belongs in the conversation: the live generation, or history of the resumed ACP session. */
7
+ export function conversationEventVisible(event, sessionGeneration, resumedSessionId) {
8
+ return event.source !== 'agent_replay' && (event.sessionGeneration === sessionGeneration || (!!resumedSessionId && HISTORICAL_KINDS.includes(event.kind) && event.acpSessionId === resumedSessionId));
9
+ }
10
+ /** Newest-first lines of a file, read in chunks from its end; `visit` returns false to stop. */
11
+ async function readLinesBackward(path, visit, signal) {
12
+ signal?.throwIfAborted();
13
+ const file = await open(path, 'r');
14
+ try {
15
+ let position = (await file.stat()).size;
16
+ let carry = Buffer.alloc(0);
17
+ while (position > 0) {
18
+ signal?.throwIfAborted();
19
+ const size = Math.min(256 * 1024, position);
20
+ position -= size;
21
+ const chunk = Buffer.alloc(size);
22
+ await file.read(chunk, 0, size, position);
23
+ signal?.throwIfAborted();
24
+ let buffer = Buffer.concat([chunk, carry]);
25
+ let end = buffer.length;
26
+ for (let i = buffer.length - 1; i >= 0; i--) {
27
+ if (buffer[i] !== 10)
28
+ continue;
29
+ if (end > i + 1 && !visit(buffer.toString('utf8', i + 1, end)))
30
+ return false;
31
+ end = i;
32
+ }
33
+ carry = buffer.subarray(0, end);
34
+ }
35
+ if (carry.length && !visit(carry.toString('utf8')))
36
+ return false;
37
+ return true;
38
+ }
39
+ finally {
40
+ await file.close();
41
+ }
42
+ }
43
+ // Rotated segments never change, so their last cursor is reused until the file itself changes.
44
+ const lastSeqs = new Map();
45
+ /** The last event cursor in a segment, read from its tail; undefined when none is readable. */
46
+ async function lastSeq(path) {
47
+ const info = await stat(path).catch(() => undefined);
48
+ const key = info && `${info.dev}:${info.ino}:${info.size}:${info.mtimeMs}`;
49
+ const known = key ? lastSeqs.get(path) : undefined;
50
+ if (key && known?.key === key)
51
+ return known.seq;
52
+ let seq;
53
+ await readLinesBackward(path, line => { try {
54
+ const value = Number(JSON.parse(line).seq);
55
+ if (Number.isSafeInteger(value)) {
56
+ seq = value;
57
+ return false;
58
+ }
59
+ }
60
+ catch { } return true; });
61
+ if (key) {
62
+ lastSeqs.delete(path);
63
+ lastSeqs.set(path, { key, seq });
64
+ if (lastSeqs.size > 4096)
65
+ lastSeqs.delete(lastSeqs.keys().next().value);
66
+ }
67
+ return seq;
68
+ }
69
+ /**
70
+ * The newest `limit` visible events before `before` (or the newest overall),
71
+ * read backwards from the ledger so opening a long session costs one page.
72
+ * `nextCursor` is the newest ledger position seen, for forward `after` paging.
73
+ */
74
+ export async function conversationTailPage(stateDir, request, snapshot, resumedSessionId, signal) {
75
+ signal?.throwIfAborted();
76
+ const before = request.before === undefined ? Infinity : Number(request.before);
77
+ if (before !== Infinity && (!Number.isSafeInteger(before) || before < 0))
78
+ throw new Error('before must be a ledger cursor');
79
+ const limit = Math.min(1000, Math.max(1, Number.isFinite(request.limit) ? Math.floor(request.limit) : 200));
80
+ let files = [];
81
+ try {
82
+ files = (await readdir(join(stateDir, '.conversation'))).filter(n => /^events-\d{6}\.jsonl$/.test(n)).sort().reverse();
83
+ }
84
+ catch { }
85
+ const events = [];
86
+ let newest;
87
+ let hasOlder = false;
88
+ const observation = snapshot;
89
+ const barrier = observation.ledgerBarrier;
90
+ // Current supervisors capture these sanitized inventories together with the
91
+ // ledger barrier. The browser uses them directly, including authoritative
92
+ // empty arrays. Looking for their old ledger events would scan the entire
93
+ // generation on every open. Legacy/incomplete snapshots still need context.
94
+ const complete = !snapshot.observationFailure && Number.isSafeInteger(barrier) && barrier >= 0
95
+ && Number.isSafeInteger(observation.stateRevision) && observation.stateRevision >= 0;
96
+ const needsCapabilities = !complete || !Array.isArray(observation.commands);
97
+ const pending = new Set(complete && Array.isArray(observation.pendingPermissions)
98
+ && snapshot.pendingPermissionIds.every(id => observation.pendingPermissions.some(permission => permission.permissionId === id))
99
+ ? [] : snapshot.pendingPermissionIds);
100
+ let capabilities;
101
+ const context = [];
102
+ // Context only accompanies the newest page; older pages stop as soon as they are full.
103
+ const wantsContext = () => before === Infinity && ((needsCapabilities && !capabilities) || pending.size > 0);
104
+ const generation = `"sessionGeneration":${JSON.stringify(snapshot.sessionGeneration)}`;
105
+ for (const file of files) {
106
+ const more = await readLinesBackward(join(stateDir, '.conversation', file), line => {
107
+ if (hasOlder) {
108
+ // The page is full; only the current generation's context kinds matter. Generations are
109
+ // appended in order, so the first line of an older one ends the search.
110
+ if (!line.includes(generation))
111
+ return !line.includes('"sessionGeneration":') && wantsContext();
112
+ if (!line.includes('"capabilities.updated"') && !line.includes('"permission.requested"'))
113
+ return wantsContext();
114
+ }
115
+ let event;
116
+ try {
117
+ event = JSON.parse(line);
118
+ }
119
+ catch {
120
+ return true;
121
+ }
122
+ const seq = Number(event.seq);
123
+ if (!Number.isSafeInteger(seq))
124
+ return true;
125
+ if (barrier !== undefined && seq > barrier)
126
+ return true;
127
+ newest ??= seq;
128
+ if (seq < before && conversationEventVisible(event, snapshot.sessionGeneration, resumedSessionId)) {
129
+ const inPage = !hasOlder && events.length < limit;
130
+ if (event.sessionGeneration === snapshot.sessionGeneration) {
131
+ if (event.kind === 'capabilities.updated' && !capabilities) {
132
+ capabilities = event;
133
+ if (!inPage)
134
+ context.push(event);
135
+ }
136
+ if (event.kind === 'permission.requested' && event.permissionId && pending.delete(event.permissionId) && !inPage)
137
+ context.push(event);
138
+ }
139
+ if (inPage)
140
+ events.push(event);
141
+ else
142
+ hasOlder = true;
143
+ }
144
+ return !hasOlder || wantsContext();
145
+ }, signal);
146
+ if (!more)
147
+ break;
148
+ }
149
+ events.reverse();
150
+ context.reverse();
151
+ return { events, snapshot, hasOlder, context, hasMore: false,
152
+ ...(events.length ? { olderCursor: String(events[0].seq) } : {}),
153
+ ...(before === Infinity && (barrier !== undefined || newest !== undefined) ? { nextCursor: String(barrier ?? newest) } : {}) };
154
+ }
155
+ /** Read the existing ACP session ledger without opening its writer/recovery store. */
156
+ export async function resumedConversationPage(stateDir, request, live, expectedSessionId) {
157
+ let sessionId;
158
+ let files;
159
+ try {
160
+ sessionId = (await readFile(join(stateDir, '.acp-session-id'), 'utf8')).trim();
161
+ files = (await readdir(join(stateDir, '.conversation'))).filter(n => /^events-\d{6}\.jsonl$/.test(n)).sort();
162
+ }
163
+ catch {
164
+ return live;
165
+ }
166
+ if (!sessionId || sessionId !== expectedSessionId || !files.length)
167
+ return live;
168
+ const after = Number(request.after ?? 0);
169
+ if (!Number.isSafeInteger(after) || after < 0)
170
+ return live;
171
+ const limit = Math.min(1000, Math.max(1, Number.isFinite(request.limit) ? Math.floor(request.limit) : 200));
172
+ const events = [];
173
+ let next = String(after);
174
+ let first;
175
+ let hasMore = false;
176
+ scan: for (const file of files) {
177
+ // Forward polling asks for the newest few events: skip whole segments that end at or before the cursor.
178
+ const end = await lastSeq(join(stateDir, '.conversation', file));
179
+ if (end !== undefined && end <= after)
180
+ continue;
181
+ const input = createReadStream(join(stateDir, '.conversation', file), { encoding: 'utf8' });
182
+ const lines = createInterface({ input, crlfDelay: Infinity });
183
+ try {
184
+ for await (const line of lines) {
185
+ let event;
186
+ try {
187
+ event = JSON.parse(line);
188
+ }
189
+ catch {
190
+ continue;
191
+ }
192
+ const cursor = Number(event.seq);
193
+ if (!Number.isSafeInteger(cursor) || cursor <= after)
194
+ continue;
195
+ const historical = ['file.attached', 'fleet.task_created', 'prompt.admitted', 'message.chunk', 'message.replace', 'tool.upsert', 'tool.content_chunk', 'turn.completed'].includes(event.kind);
196
+ const visible = event.source !== 'agent_replay' && (event.sessionGeneration === live.snapshot.sessionGeneration || (historical && event.acpSessionId === sessionId));
197
+ if (!visible) {
198
+ next = String(cursor);
199
+ continue;
200
+ }
201
+ if (events.length === limit) {
202
+ hasMore = true;
203
+ break scan;
204
+ }
205
+ first ??= String(cursor);
206
+ events.push(event);
207
+ next = String(cursor);
208
+ }
209
+ }
210
+ finally {
211
+ lines.close();
212
+ input.destroy();
213
+ }
214
+ }
215
+ // If a fresh/resumed session changed during the read, use the live page only.
216
+ if ((await readFile(join(stateDir, '.acp-session-id'), 'utf8')).trim() !== sessionId)
217
+ return live;
218
+ return { ...live, events, firstAvailableCursor: first, nextCursor: next, hasMore };
219
+ }
220
+ /** Download authorization requires an actual published attachment, never an orphan copy. */
221
+ export async function conversationHasAttachment(stateDir, attachment) {
222
+ const dir = join(stateDir, '.conversation');
223
+ const names = (await readdir(dir)).filter(n => /^events-\d+\.jsonl$/.test(n)).sort().reverse();
224
+ let found = false;
225
+ for (const name of names) {
226
+ await readLinesBackward(join(dir, name), line => {
227
+ try {
228
+ const e = JSON.parse(line);
229
+ const a = e.payload.attachment;
230
+ if (e.kind === 'file.attached' && e.source === 'agent' && a?.id === attachment.id
231
+ && e.sessionGeneration === attachment.sessionGeneration && e.acpSessionId === attachment.acpSessionId
232
+ && e.turnId === attachment.turnId && JSON.stringify(a) === JSON.stringify(attachment))
233
+ found = true;
234
+ }
235
+ catch { /* unreadable lines cannot authorize a download */ }
236
+ return !found;
237
+ });
238
+ if (found)
239
+ break;
240
+ }
241
+ return found;
242
+ }
243
+ /** Passive, bounded last assistant text for directory previews. Never opens the
244
+ * ledger writer/recovery path or acquires a session/controller. An incomplete
245
+ * newest append is not committed yet; completed malformed records still fail. */
246
+ /** Bytes of a segment's tail a preview may consider, and the newest events it reads. */
247
+ const PREVIEW_WINDOW_BYTES = 2 * 1024 * 1024;
248
+ const PREVIEW_EVENTS = 200;
249
+ /**
250
+ * Newest-first completed events from the last PREVIEW_WINDOW_BYTES of one
251
+ * segment, read backwards in chunks until `need` events are found. A record
252
+ * cut by the window start is not complete and is skipped. Only the newest
253
+ * segment can have an in-flight append; elsewhere a partial record fails.
254
+ */
255
+ async function previewSegmentEvents(path, newest, need, signal) {
256
+ const events = [];
257
+ const file = await open(path, 'r');
258
+ try {
259
+ const size = (await file.stat()).size, floor = Math.max(0, size - PREVIEW_WINDOW_BYTES);
260
+ let position = size, carry = Buffer.alloc(0), trailing = true;
261
+ const take = (line) => {
262
+ const event = JSON.parse(line);
263
+ if (event.schemaVersion !== 1 || !Number.isSafeInteger(event.seq))
264
+ throw Error('preview ledger invalid');
265
+ events.push(event);
266
+ };
267
+ while (position > floor && events.length < need) {
268
+ signal.throwIfAborted();
269
+ const length = Math.min(64 * 1024, position - floor);
270
+ position -= length;
271
+ const chunk = Buffer.alloc(length);
272
+ await file.read(chunk, 0, length, position);
273
+ const buffer = Buffer.concat([chunk, carry]);
274
+ let end = buffer.length;
275
+ for (let i = buffer.length - 1; i >= 0 && events.length < need; i--) {
276
+ if (buffer[i] !== 10)
277
+ continue;
278
+ if (trailing) {
279
+ if (end > i + 1 && !newest)
280
+ throw Error('preview ledger has partial record');
281
+ trailing = false;
282
+ }
283
+ else
284
+ take(buffer.toString('utf8', i + 1, end));
285
+ end = i;
286
+ }
287
+ carry = buffer.subarray(0, end);
288
+ }
289
+ if (trailing && position === floor && (!newest || floor > 0) && size > 0)
290
+ throw Error('preview ledger has partial record');
291
+ // At the file start the remaining bytes are the first complete record.
292
+ if (!trailing && floor === 0 && position === 0 && events.length < need)
293
+ take(carry.toString('utf8'));
294
+ }
295
+ finally {
296
+ await file.close();
297
+ }
298
+ return events;
299
+ }
300
+ export async function conversationPreview(stateDir, signal) {
301
+ signal.throwIfAborted();
302
+ const dir = join(stateDir, '.conversation');
303
+ let files;
304
+ try {
305
+ files = (await readdir(dir)).filter(name => /^events-\d{6}\.jsonl$/.test(name)).sort().reverse();
306
+ }
307
+ catch (error) {
308
+ if (error.code === 'ENOENT')
309
+ return { text: 'No recent agent output', at: '' };
310
+ throw error;
311
+ }
312
+ const events = [];
313
+ for (const name of files) {
314
+ signal.throwIfAborted();
315
+ events.push(...await previewSegmentEvents(join(dir, name), name === files[0], PREVIEW_EVENTS - events.length, signal));
316
+ if (events.length >= PREVIEW_EVENTS)
317
+ break;
318
+ }
319
+ signal.throwIfAborted();
320
+ const assistant = (event) => ['message.chunk', 'message.replace'].includes(event.kind) && event.payload?.role === 'assistant' && typeof event.payload?.content?.type === 'string';
321
+ const end = events.findIndex(assistant);
322
+ if (end < 0)
323
+ return { text: 'No recent agent output', at: '' };
324
+ const last = events[end], parts = [];
325
+ for (let i = end; i < events.length; i++) {
326
+ const event = events[i];
327
+ if (last.messageId !== undefined) {
328
+ if (!assistant(event) || event.messageId !== last.messageId)
329
+ continue;
330
+ }
331
+ else if (!assistant(event) || event.messageId !== undefined)
332
+ break;
333
+ const content = event.payload.content;
334
+ parts.unshift(content.type === 'text' ? content.text : `[${content.type}]`);
335
+ if (event.kind === 'message.replace')
336
+ break;
337
+ }
338
+ return { text: parts.join('').replace(/\s+/g, ' ').trim().slice(0, 300) || 'No recent agent output', at: last.at ?? '' };
339
+ }
@@ -0,0 +1,62 @@
1
+ import { type FSWatcher } from 'node:fs';
2
+ import { type SessionBackendId } from '../config.js';
3
+ export interface ConversationRoleState {
4
+ roleId: string;
5
+ /** Connection-owned ordering; never a session stateRevision. */
6
+ roleRevision: number;
7
+ roleLifetime: string;
8
+ availability: 'available' | 'unavailable' | 'missing';
9
+ fallbackHarness?: string;
10
+ backend?: SessionBackendId;
11
+ stateDir?: string;
12
+ health: 'healthy' | 'unsupported' | 'failed';
13
+ failure?: 'watch-unsupported' | 'watch-error' | 'watch-closed' | 'role-read-failed' | 'observer-disposed';
14
+ }
15
+ export interface ConversationRoleObservation {
16
+ snapshot(): ConversationRoleState;
17
+ subscribe(listener: (state: ConversationRoleState) => void): {
18
+ snapshot: ConversationRoleState;
19
+ unsubscribe(): void;
20
+ };
21
+ dispose(): void;
22
+ }
23
+ export type ObserveConversationRole = (listener: (state: ConversationRoleState) => void) => ConversationRoleObservation;
24
+ export interface ConversationRoleObserverOptions {
25
+ roleId: string;
26
+ configPath?: string;
27
+ permanentRoot?: string;
28
+ temporaryRoot?: string;
29
+ watch?: (path: string, listener: (event: string, filename: string | null) => void) => Pick<FSWatcher, 'on' | 'close'>;
30
+ subscribeMutations?: (listener: () => void) => () => void;
31
+ }
32
+ /** Native directory notifications are assumed reliable on qualified host/mount setups.
33
+ * No periodic reads or claim of detecting every silently dropped filesystem event.
34
+ */
35
+ export declare class ConversationRoleObserver implements ConversationRoleObservation {
36
+ private readonly options;
37
+ private readonly listener;
38
+ private state;
39
+ private watchers;
40
+ private detach?;
41
+ private disposed;
42
+ private readonly listeners;
43
+ private queued;
44
+ private fingerprint?;
45
+ private readonly configPath;
46
+ private readonly permanent;
47
+ private readonly temporary;
48
+ constructor(options: ConversationRoleObserverOptions, listener: (state: ConversationRoleState) => void);
49
+ snapshot(): ConversationRoleState;
50
+ subscribe(listener: (state: ConversationRoleState) => void): {
51
+ snapshot: ConversationRoleState;
52
+ unsubscribe: () => void;
53
+ };
54
+ private publish;
55
+ dispose(): void;
56
+ private release;
57
+ private fail;
58
+ private schedule;
59
+ private refresh;
60
+ private install;
61
+ private watchFailure;
62
+ }