@north-light/crouter 0.3.349 → 0.3.351

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 (629) hide show
  1. package/bin/crtr-launcher +4 -0
  2. package/bin/runtime-generation-manifest.mjs +12 -2
  3. package/dist/api/client.d.ts +50 -7
  4. package/dist/api/client.js +2 -2
  5. package/dist/api/dto/analytics.d.ts +184 -0
  6. package/dist/api/dto/analytics.js +0 -0
  7. package/dist/api/dto/broker-ops.d.ts +43 -1
  8. package/dist/api/dto/config.d.ts +11 -0
  9. package/dist/api/dto/grants.d.ts +14 -0
  10. package/dist/api/dto/grants.js +0 -0
  11. package/dist/api/dto/human-requests.d.ts +14 -0
  12. package/dist/api/dto/memory.d.ts +6 -0
  13. package/dist/api/dto/modelauth.d.ts +35 -0
  14. package/dist/api/dto/node-records.d.ts +35 -0
  15. package/dist/api/dto/node-records.js +0 -0
  16. package/dist/api/dto/nodes.d.ts +5 -0
  17. package/dist/api/dto/profiles.d.ts +38 -3
  18. package/dist/api/dto/worktree.d.ts +11 -0
  19. package/dist/api/errors.d.ts +23 -1
  20. package/dist/api/errors.js +1 -1
  21. package/dist/api/index.d.ts +2 -0
  22. package/dist/api/index.js +1 -1
  23. package/dist/api/node-transport.js +1 -1
  24. package/dist/api/routes.d.ts +22 -0
  25. package/dist/api/routes.js +1 -1
  26. package/dist/build-root.d.ts +6 -1
  27. package/dist/build-root.js +1 -1
  28. package/dist/builtin-memory/crouter-sdk/client.md +34 -0
  29. package/dist/builtin-memory/crouter-sdk/errors.md +2 -0
  30. package/dist/builtin-memory/crouter-sdk/memory.md +2 -2
  31. package/dist/builtin-memory/crouter-sdk/streaming.md +21 -0
  32. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/claude-plugin-commands.ts +8 -4
  33. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/memory-slash-commands.ts +39 -118
  34. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.d.ts +6 -1
  35. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.js +41 -27
  36. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.ts +52 -29
  37. package/dist/cli.js +9 -8
  38. package/dist/clients/attach/chrome/inbox-strip.js +1 -1
  39. package/dist/clients/attach/chrome/roster.js +1 -1
  40. package/dist/clients/attach/config.js +1 -1
  41. package/dist/clients/attach/overlays/auth.js +2 -2
  42. package/dist/clients/attach/overlays/graph.js +1 -1
  43. package/dist/clients/attach/render/tool-calls.js +3 -3
  44. package/dist/clients/attach/session/connection.js +1 -1
  45. package/dist/clients/attach/session/profile-files.js +1 -1
  46. package/dist/clients/attach/viewer.js +1569 -816
  47. package/dist/commands/api-client.js +3 -3
  48. package/dist/commands/broker-permissions.d.ts +2 -0
  49. package/dist/commands/broker-permissions.js +1 -0
  50. package/dist/commands/canvas-analytics/chart.d.ts +52 -0
  51. package/dist/commands/canvas-analytics/chart.js +1 -0
  52. package/dist/commands/canvas-analytics/drilldown.d.ts +34 -0
  53. package/dist/commands/canvas-analytics/drilldown.js +1 -0
  54. package/dist/commands/canvas-analytics/format.d.ts +29 -0
  55. package/dist/commands/canvas-analytics/format.js +1 -0
  56. package/dist/commands/canvas-analytics/graph-detail.d.ts +2 -0
  57. package/dist/commands/canvas-analytics/graph-detail.js +2 -0
  58. package/dist/commands/canvas-analytics/graphs.d.ts +9 -0
  59. package/dist/commands/canvas-analytics/graphs.js +1 -0
  60. package/dist/commands/canvas-analytics/memory.d.ts +2 -0
  61. package/dist/commands/canvas-analytics/memory.js +1 -0
  62. package/dist/commands/canvas-analytics/overview.d.ts +2 -0
  63. package/dist/commands/canvas-analytics/overview.js +1 -0
  64. package/dist/commands/canvas-analytics/shell.d.ts +60 -0
  65. package/dist/commands/canvas-analytics/shell.js +2 -0
  66. package/dist/commands/canvas-analytics/time.d.ts +2 -0
  67. package/dist/commands/canvas-analytics/time.js +1 -0
  68. package/dist/commands/canvas-analytics/usage.d.ts +2 -0
  69. package/dist/commands/canvas-analytics/usage.js +1 -0
  70. package/dist/commands/canvas-analytics/view.d.ts +85 -0
  71. package/dist/commands/canvas-analytics/view.js +1 -0
  72. package/dist/commands/canvas-analytics.d.ts +2 -0
  73. package/dist/commands/canvas-analytics.js +1 -0
  74. package/dist/commands/canvas-prune.js +1 -1
  75. package/dist/commands/canvas.js +1 -1
  76. package/dist/commands/cron.js +5 -5
  77. package/dist/commands/human/components.d.ts +2 -0
  78. package/dist/commands/human/components.js +2 -2
  79. package/dist/commands/human/prompts.js +1 -1
  80. package/dist/commands/human/queue.js +1 -1
  81. package/dist/commands/memory/client.d.ts +11 -0
  82. package/dist/commands/memory/client.js +1 -0
  83. package/dist/commands/memory/delete.js +1 -1
  84. package/dist/commands/memory/edit.js +3 -3
  85. package/dist/commands/memory/find.js +1 -1
  86. package/dist/commands/memory/history.js +4 -4
  87. package/dist/commands/memory/lint.js +1 -1
  88. package/dist/commands/memory/list.d.ts +0 -2
  89. package/dist/commands/memory/list.js +1 -1
  90. package/dist/commands/memory/move.js +1 -1
  91. package/dist/commands/memory/origin.js +1 -1
  92. package/dist/commands/memory/read.d.ts +0 -5
  93. package/dist/commands/memory/read.js +3 -3
  94. package/dist/commands/memory/shared.d.ts +0 -178
  95. package/dist/commands/memory/shared.js +1 -12
  96. package/dist/commands/memory/write.js +5 -5
  97. package/dist/commands/node/bash.js +5 -5
  98. package/dist/commands/node/create.d.ts +0 -17
  99. package/dist/commands/node/create.js +2 -3
  100. package/dist/commands/node/inspect.js +6 -6
  101. package/dist/commands/node/lifecycle.js +2 -2
  102. package/dist/commands/node-context.js +2 -2
  103. package/dist/commands/node-inspect-artifacts.js +6 -6
  104. package/dist/commands/pkg/browse/catalog.js +1 -1
  105. package/dist/commands/pkg/browse/model.d.ts +1 -1
  106. package/dist/commands/pkg/market-manage.js +1 -1
  107. package/dist/commands/pkg/plugin-manage.js +10 -10
  108. package/dist/commands/profile/daemon-profiles.d.ts +13 -0
  109. package/dist/commands/profile/daemon-profiles.js +4 -0
  110. package/dist/commands/profile/delete.js +1 -1
  111. package/dist/commands/profile/env.d.ts +6 -0
  112. package/dist/commands/profile/env.js +2 -2
  113. package/dist/commands/profile/kind.js +1 -2
  114. package/dist/commands/profile/list.js +1 -1
  115. package/dist/commands/profile/meta.js +1 -1
  116. package/dist/commands/profile/new.js +1 -1
  117. package/dist/commands/profile/pause.js +1 -1
  118. package/dist/commands/profile/project.js +1 -1
  119. package/dist/commands/profile/rename.js +1 -1
  120. package/dist/commands/profile/show.js +1 -1
  121. package/dist/commands/profile.js +1 -1
  122. package/dist/commands/push.js +3 -3
  123. package/dist/commands/surface-inspect.js +1 -1
  124. package/dist/commands/sys/branch.js +1 -1
  125. package/dist/commands/sys/config.js +1 -1
  126. package/dist/commands/sys/connect.js +3 -3
  127. package/dist/commands/sys/context/admin/actions.js +1 -1
  128. package/dist/commands/sys/context/admin/model.d.ts +1 -0
  129. package/dist/commands/sys/context/admin/model.js +1 -1
  130. package/dist/commands/sys/context/admin.js +1 -1
  131. package/dist/commands/sys/context/expose.js +2 -1
  132. package/dist/commands/sys/context/prompt-review.js +2 -2
  133. package/dist/commands/sys/context/resolve.js +7 -7
  134. package/dist/commands/sys/context/sysprompt.js +1 -1
  135. package/dist/commands/sys/join.d.ts +1 -0
  136. package/dist/commands/sys/join.js +1 -0
  137. package/dist/commands/sys/migrate.js +1 -1
  138. package/dist/commands/sys/panels/models-panel.js +1 -1
  139. package/dist/commands/sys/panels/profiles-panel.d.ts +0 -1
  140. package/dist/commands/sys/panels/profiles-panel.js +1 -1
  141. package/dist/commands/sys/provider-login.js +6 -6
  142. package/dist/commands/sys/setup-core.d.ts +1 -1
  143. package/dist/commands/sys/setup-core.js +6 -6
  144. package/dist/commands/sys/setup-settings-runner.js +1 -1
  145. package/dist/commands/sys/setup.js +1 -1
  146. package/dist/commands/sys/spaces.d.ts +1 -0
  147. package/dist/commands/sys/spaces.js +2 -0
  148. package/dist/commands/sys/sync-deps.js +2 -2
  149. package/dist/commands/sys/sync-project-guidance.js +4 -4
  150. package/dist/commands/sys/sync-skills.js +2 -2
  151. package/dist/commands/sys/worktrees.d.ts +1 -0
  152. package/dist/commands/sys/worktrees.js +1 -1
  153. package/dist/commands/sys.js +1 -1
  154. package/dist/core/auth-file.js +2 -2
  155. package/dist/core/bash-job-supervisor.d.ts +6 -0
  156. package/dist/core/bash-job-supervisor.js +4 -0
  157. package/dist/core/bash-jobs.d.ts +13 -6
  158. package/dist/core/bash-jobs.js +8 -7
  159. package/dist/core/broker-client/transport-relay.d.ts +6 -3
  160. package/dist/core/broker-client/transport-relay.js +1 -1
  161. package/dist/core/broker-client/transport-socket.d.ts +6 -1
  162. package/dist/core/broker-client/transport-socket.js +1 -1
  163. package/dist/core/canvas/canvas.d.ts +39 -18
  164. package/dist/core/canvas/canvas.js +21 -20
  165. package/dist/core/canvas/context-strip.d.ts +20 -0
  166. package/dist/core/canvas/context-strip.js +5 -0
  167. package/dist/core/canvas/crons.d.ts +12 -20
  168. package/dist/core/canvas/crons.js +15 -13
  169. package/dist/core/canvas/db.js +2 -2
  170. package/dist/core/canvas/deliveries.d.ts +4 -1
  171. package/dist/core/canvas/deliveries.js +1 -1
  172. package/dist/core/canvas/executions.js +1 -1
  173. package/dist/core/canvas/history.d.ts +2 -1
  174. package/dist/core/canvas/history.js +17 -18
  175. package/dist/core/canvas/memory-reads.d.ts +19 -0
  176. package/dist/core/canvas/memory-reads.js +1 -0
  177. package/dist/core/canvas/migrations.d.ts +0 -4
  178. package/dist/core/canvas/migrations.js +99 -32
  179. package/dist/core/canvas/nav-render.js +1 -1
  180. package/dist/core/canvas/node-agent-paths.d.ts +8 -0
  181. package/dist/core/canvas/node-agent-paths.js +1 -0
  182. package/dist/core/canvas/node-recap.d.ts +2 -2
  183. package/dist/core/canvas/node-recap.js +2 -2
  184. package/dist/core/canvas/node-tokens.d.ts +24 -0
  185. package/dist/core/canvas/node-tokens.js +5 -0
  186. package/dist/core/canvas/paths.d.ts +16 -19
  187. package/dist/core/canvas/paths.js +1 -1
  188. package/dist/core/canvas/render-source.d.ts +2 -2
  189. package/dist/core/canvas/render-source.js +6 -9
  190. package/dist/core/canvas/sessions.d.ts +18 -0
  191. package/dist/core/canvas/sessions.js +4 -1
  192. package/dist/core/canvas/types.d.ts +22 -6
  193. package/dist/core/command-hooks/compose.js +1 -1
  194. package/dist/core/command-hooks/discovery.d.ts +15 -1
  195. package/dist/core/command-hooks/discovery.js +1 -1
  196. package/dist/core/command-hooks/help.d.ts +2 -2
  197. package/dist/core/command-hooks/lifecycle-create.d.ts +1 -1
  198. package/dist/core/command-hooks/lifecycle-create.js +1 -1
  199. package/dist/core/command-hooks/transport/exec-invoke.d.ts +2 -0
  200. package/dist/core/command-hooks/transport/exec-invoke.js +1 -1
  201. package/dist/core/command-hooks/transport/exec-lifecycle.d.ts +1 -0
  202. package/dist/core/command-hooks/transport/exec-lifecycle.js +1 -1
  203. package/dist/core/command-hooks/transport/plan.d.ts +3 -0
  204. package/dist/core/command-hooks/transport/plan.js +1 -0
  205. package/dist/core/command-plugins/discovery.js +1 -1
  206. package/dist/core/command.d.ts +6 -2
  207. package/dist/core/command.js +6 -6
  208. package/dist/core/config.d.ts +8 -5
  209. package/dist/core/config.js +1 -1
  210. package/dist/core/conversation-store/client-worker.d.ts +1 -0
  211. package/dist/core/conversation-store/client-worker.js +1 -0
  212. package/dist/core/conversation-store/client.d.ts +2 -0
  213. package/dist/core/conversation-store/client.js +2 -0
  214. package/dist/core/conversation-store/file-store.d.ts +37 -0
  215. package/dist/core/conversation-store/file-store.js +9 -0
  216. package/dist/core/conversation-store/index.d.ts +50 -0
  217. package/dist/core/conversation-store/index.js +1 -0
  218. package/dist/core/conversation-store/listener.d.ts +4 -0
  219. package/dist/core/conversation-store/listener.js +3 -0
  220. package/dist/core/conversation-store/patch.d.ts +1 -0
  221. package/dist/core/conversation-store/patch.js +1 -0
  222. package/dist/core/directory/join.d.ts +27 -0
  223. package/dist/core/directory/join.js +1 -0
  224. package/dist/core/disk-usage.d.ts +4 -0
  225. package/dist/core/disk-usage.js +1 -0
  226. package/dist/core/events/emit.d.ts +2 -0
  227. package/dist/core/events/emit.js +3 -1
  228. package/dist/core/feed/feed.js +4 -4
  229. package/dist/core/feed/messages.d.ts +3 -0
  230. package/dist/core/feed/messages.js +6 -6
  231. package/dist/core/fs-utils.d.ts +2 -0
  232. package/dist/core/fs-utils.js +3 -3
  233. package/dist/core/grants/local.d.ts +4 -0
  234. package/dist/core/grants/local.js +1 -0
  235. package/dist/core/grants/mirror.d.ts +44 -0
  236. package/dist/core/grants/mirror.js +4 -0
  237. package/dist/core/grants/on-sync.d.ts +22 -0
  238. package/dist/core/grants/on-sync.js +1 -0
  239. package/dist/core/grants/remove.d.ts +7 -0
  240. package/dist/core/grants/remove.js +1 -0
  241. package/dist/core/grants/sandboxes.d.ts +7 -0
  242. package/dist/core/grants/sandboxes.js +1 -0
  243. package/dist/core/grants/sync.d.ts +12 -0
  244. package/dist/core/grants/sync.js +1 -0
  245. package/dist/core/help/memory-extensions.d.ts +3 -0
  246. package/dist/core/help/memory-extensions.js +2 -0
  247. package/dist/core/help.d.ts +14 -0
  248. package/dist/core/help.js +7 -7
  249. package/dist/core/host-exports/builtins.js +3 -3
  250. package/dist/core/host-exports/export.js +3 -3
  251. package/dist/core/human/action-binding.d.ts +2 -0
  252. package/dist/core/human/action-binding.js +1 -1
  253. package/dist/core/human/feedback-companion.d.ts +0 -1
  254. package/dist/core/human/feedback-companion.js +1 -1
  255. package/dist/core/human/page-schema.d.ts +1 -1
  256. package/dist/core/inspector/core.d.ts +2 -0
  257. package/dist/core/inspector/core.js +1 -1
  258. package/dist/core/inspector/tui.js +2 -2
  259. package/dist/core/installed-plugins.js +1 -1
  260. package/dist/core/io.js +6 -6
  261. package/dist/core/keybindings/catalog.d.ts +1 -1
  262. package/dist/core/keybindings/catalog.js +1 -1
  263. package/dist/core/layout-migrate/index.d.ts +15 -0
  264. package/dist/core/layout-migrate/index.js +4 -0
  265. package/dist/core/layout-migrate/paths.d.ts +26 -0
  266. package/dist/core/layout-migrate/paths.js +1 -0
  267. package/dist/core/layout-migrate/stored-paths.d.ts +2 -0
  268. package/dist/core/layout-migrate/stored-paths.js +11 -0
  269. package/dist/core/layout-migrate/stores.d.ts +17 -0
  270. package/dist/core/layout-migrate/stores.js +4 -0
  271. package/dist/core/layout.d.ts +26 -0
  272. package/dist/core/layout.js +2 -0
  273. package/dist/core/llm/run.d.ts +60 -0
  274. package/dist/core/llm/run.js +4 -0
  275. package/dist/core/memory/cli-selector.d.ts +13 -0
  276. package/dist/core/memory/cli-selector.js +1 -0
  277. package/dist/core/memory/history.d.ts +5 -4
  278. package/dist/core/memory/history.js +6 -6
  279. package/dist/core/memory/inline-ref-inventory.d.ts +2 -1
  280. package/dist/core/memory/inline-ref-inventory.js +1 -1
  281. package/dist/core/memory/lint.js +2 -2
  282. package/dist/core/memory/mutation-domain.d.ts +2 -2
  283. package/dist/core/memory/mutation-domain.js +8 -7
  284. package/dist/core/memory/mutations.js +1 -1
  285. package/dist/core/memory/service.d.ts +5 -0
  286. package/dist/core/memory/service.js +2 -2
  287. package/dist/core/memory-resolver.d.ts +11 -7
  288. package/dist/core/memory-resolver.js +2 -2
  289. package/dist/core/model-auth/daemon-login.d.ts +13 -0
  290. package/dist/core/model-auth/daemon-login.js +1 -0
  291. package/dist/core/model-auth/flows.d.ts +45 -0
  292. package/dist/core/model-auth/flows.js +1 -0
  293. package/dist/core/model-auth/handoff-jti.d.ts +4 -0
  294. package/dist/core/model-auth/handoff-jti.js +1 -0
  295. package/dist/core/model-routes.js +1 -1
  296. package/dist/core/nested-stores.d.ts +2 -1
  297. package/dist/core/nested-stores.js +1 -2
  298. package/dist/core/preview-registry.js +2 -2
  299. package/dist/core/profiles/env-store.js +2 -2
  300. package/dist/core/profiles/manifest.d.ts +16 -5
  301. package/dist/core/profiles/manifest.js +1 -1
  302. package/dist/core/provider-management.js +1 -1
  303. package/dist/core/review/birth.js +1 -1
  304. package/dist/core/review/companion.d.ts +0 -2
  305. package/dist/core/review/companion.js +1 -1
  306. package/dist/core/review/fork.js +2 -2
  307. package/dist/core/review/realize.js +1 -1
  308. package/dist/core/review/stage.d.ts +1 -1
  309. package/dist/core/review/stage.js +1 -1
  310. package/dist/core/review/types.d.ts +1 -1
  311. package/dist/core/runs/events.d.ts +34 -0
  312. package/dist/core/runs/events.js +1 -0
  313. package/dist/core/runs/operations.d.ts +43 -0
  314. package/dist/core/runs/operations.js +12 -0
  315. package/dist/core/runtime/bearings-render.d.ts +2 -2
  316. package/dist/core/runtime/bearings-render.js +11 -11
  317. package/dist/core/runtime/bearings.js +2 -2
  318. package/dist/core/runtime/broker/cli-relay.d.ts +5 -0
  319. package/dist/core/runtime/broker/cli-relay.js +1 -0
  320. package/dist/core/runtime/broker/client-registry.d.ts +0 -5
  321. package/dist/core/runtime/broker/client-registry.js +1 -1
  322. package/dist/core/runtime/broker/daemon-ops.d.ts +28 -1
  323. package/dist/core/runtime/broker/daemon-ops.js +1 -1
  324. package/dist/core/runtime/broker/engine-drive.d.ts +0 -2
  325. package/dist/core/runtime/broker/engine-drive.js +1 -1
  326. package/dist/core/runtime/broker/fault-retry.d.ts +9 -0
  327. package/dist/core/runtime/broker/fault-retry.js +1 -1
  328. package/dist/core/runtime/broker/frame-dispatch.d.ts +5 -9
  329. package/dist/core/runtime/broker/frame-dispatch.js +1 -1
  330. package/dist/core/runtime/broker/frame-engine-control.d.ts +3 -2
  331. package/dist/core/runtime/broker/frame-engine-control.js +1 -1
  332. package/dist/core/runtime/broker/frame-memory-refs.d.ts +4 -3
  333. package/dist/core/runtime/broker/frame-memory-refs.js +1 -1
  334. package/dist/core/runtime/broker/frame-read.js +1 -1
  335. package/dist/core/runtime/broker/frame-session.js +1 -1
  336. package/dist/core/runtime/broker/held-deferred-inbox.d.ts +3 -1
  337. package/dist/core/runtime/broker/held-deferred-inbox.js +1 -1
  338. package/dist/core/runtime/broker/inbox.d.ts +1 -2
  339. package/dist/core/runtime/broker/inbox.js +7 -10
  340. package/dist/core/runtime/broker/model-adapter.d.ts +9 -0
  341. package/dist/core/runtime/broker/model-adapter.js +2 -0
  342. package/dist/core/runtime/broker/node-token.d.ts +3 -0
  343. package/dist/core/runtime/broker/node-token.js +1 -0
  344. package/dist/core/runtime/broker/read-ops.js +1 -1
  345. package/dist/core/runtime/broker/rebind.d.ts +2 -0
  346. package/dist/core/runtime/broker/rebind.js +1 -1
  347. package/dist/core/runtime/broker/tool-groups.js +1 -1
  348. package/dist/core/runtime/broker/turn-ignition.d.ts +3 -3
  349. package/dist/core/runtime/broker/turn-ignition.js +1 -1
  350. package/dist/core/runtime/broker-cli.js +3 -3
  351. package/dist/core/runtime/broker-extension-render.d.ts +2 -5
  352. package/dist/core/runtime/broker-extension-render.js +4 -4
  353. package/dist/core/runtime/broker-persona-guidance.js +3 -3
  354. package/dist/core/runtime/broker-protocol.d.ts +7 -8
  355. package/dist/core/runtime/broker.js +1 -1
  356. package/dist/core/runtime/canvas-extensions.d.ts +1 -0
  357. package/dist/core/runtime/canvas-extensions.js +1 -1
  358. package/dist/core/runtime/close.d.ts +9 -0
  359. package/dist/core/runtime/close.js +1 -1
  360. package/dist/core/runtime/deliver-live.js +1 -1
  361. package/dist/core/runtime/fleet.d.ts +1 -1
  362. package/dist/core/runtime/front-door-login.js +1 -1
  363. package/dist/core/runtime/front-door.js +2 -2
  364. package/dist/core/runtime/headless-pi.d.ts +1 -1
  365. package/dist/core/runtime/headless-pi.js +1 -1
  366. package/dist/core/runtime/host.d.ts +1 -1
  367. package/dist/core/runtime/host.js +3 -1
  368. package/dist/core/runtime/invocation.d.ts +3 -0
  369. package/dist/core/runtime/kickoff.d.ts +1 -0
  370. package/dist/core/runtime/kickoff.js +16 -16
  371. package/dist/core/runtime/launch-target.d.ts +1 -1
  372. package/dist/core/runtime/launch-target.js +1 -1
  373. package/dist/core/runtime/launch.d.ts +10 -35
  374. package/dist/core/runtime/launch.js +1 -1
  375. package/dist/core/runtime/lifecycle.js +2 -2
  376. package/dist/core/runtime/memory.d.ts +1 -1
  377. package/dist/core/runtime/memory.js +1 -1
  378. package/dist/core/runtime/model-registry.js +1 -1
  379. package/dist/core/runtime/model-swap.d.ts +17 -19
  380. package/dist/core/runtime/model-swap.js +1 -1
  381. package/dist/core/runtime/node-read.js +3 -2
  382. package/dist/core/runtime/nodes.d.ts +7 -0
  383. package/dist/core/runtime/nodes.js +1 -1
  384. package/dist/core/runtime/outcome-document.js +1 -1
  385. package/dist/core/runtime/package-health.js +2 -2
  386. package/dist/core/runtime/persona.js +2 -2
  387. package/dist/core/runtime/pi-vendored.js +1 -1
  388. package/dist/core/runtime/placement-tmux.d.ts +1 -1
  389. package/dist/core/runtime/placement-tmux.js +1 -1
  390. package/dist/core/runtime/placement.js +1 -1
  391. package/dist/core/runtime/promote.js +1 -1
  392. package/dist/core/runtime/provider-credential-gate.js +2 -2
  393. package/dist/core/runtime/recovery-hold.d.ts +2 -0
  394. package/dist/core/runtime/recovery-hold.js +1 -0
  395. package/dist/core/runtime/recycle.js +1 -1
  396. package/dist/core/runtime/reopen.js +1 -1
  397. package/dist/core/runtime/reset.js +1 -1
  398. package/dist/core/runtime/revive.d.ts +1 -1
  399. package/dist/core/runtime/revive.js +2 -3
  400. package/dist/core/runtime/roadmap.js +4 -4
  401. package/dist/core/runtime/run-command.d.ts +6 -0
  402. package/dist/core/runtime/run-command.js +1 -1
  403. package/dist/core/runtime/session-branch.d.ts +2 -8
  404. package/dist/core/runtime/session-branch.js +1 -1
  405. package/dist/core/runtime/session-list-cache.d.ts +6 -22
  406. package/dist/core/runtime/session-list-cache.js +1 -1
  407. package/dist/core/runtime/situational-context.js +2 -2
  408. package/dist/core/runtime/spawn-env.d.ts +6 -6
  409. package/dist/core/runtime/spawn-env.js +1 -1
  410. package/dist/core/runtime/spawn.d.ts +5 -0
  411. package/dist/core/runtime/spawn.js +2 -2
  412. package/dist/core/runtime/stop-guard.js +2 -2
  413. package/dist/core/runtime/stop-signals.d.ts +2 -2
  414. package/dist/core/runtime/stop-signals.js +1 -1
  415. package/dist/core/runtime/structured-output.d.ts +10 -4
  416. package/dist/core/runtime/structured-output.js +4 -4
  417. package/dist/core/runtime/tmux-bindings.js +3 -3
  418. package/dist/core/runtime/tmux-driver.d.ts +4 -0
  419. package/dist/core/runtime/tmux-driver.js +7 -7
  420. package/dist/core/runtime/view-socket.d.ts +9 -2
  421. package/dist/core/runtime/view-socket.js +1 -1
  422. package/dist/core/runtime/warm-pool.js +1 -1
  423. package/dist/core/scope.d.ts +3 -2
  424. package/dist/core/scope.js +1 -1
  425. package/dist/core/scoped-state/db.js +1 -1
  426. package/dist/core/scoped-state/migrate.js +3 -3
  427. package/dist/core/scoped-state/profiles.d.ts +2 -1
  428. package/dist/core/scoped-state/profiles.js +1 -1
  429. package/dist/core/scoped-state/schema.d.ts +2 -1
  430. package/dist/core/scoped-state/schema.js +4 -4
  431. package/dist/core/scopes.d.ts +2 -2
  432. package/dist/core/scopes.js +1 -1
  433. package/dist/core/secrets.d.ts +1 -0
  434. package/dist/core/secrets.js +2 -2
  435. package/dist/core/spaces/mounts.d.ts +32 -0
  436. package/dist/core/spaces/mounts.js +1 -0
  437. package/dist/core/spaces/open-beneath.d.ts +71 -0
  438. package/dist/core/spaces/open-beneath.js +1 -0
  439. package/dist/core/spaces/permissions.d.ts +46 -0
  440. package/dist/core/spaces/permissions.js +1 -0
  441. package/dist/core/spaces/process.d.ts +27 -0
  442. package/dist/core/spaces/process.js +1 -0
  443. package/dist/core/spaces/space.d.ts +8 -0
  444. package/dist/core/spaces/space.js +2 -0
  445. package/dist/core/spaces/stop.d.ts +8 -0
  446. package/dist/core/spaces/stop.js +2 -0
  447. package/dist/core/spaces/users.d.ts +19 -0
  448. package/dist/core/spaces/users.js +1 -0
  449. package/dist/core/subscription-state.d.ts +2 -0
  450. package/dist/core/subscription-state.js +3 -3
  451. package/dist/core/substrate/frontmatter-validation.js +1 -1
  452. package/dist/core/substrate/injected-store.d.ts +28 -3
  453. package/dist/core/substrate/injected-store.js +2 -1
  454. package/dist/core/substrate/listings.js +1 -1
  455. package/dist/core/substrate/memory-events.d.ts +6 -0
  456. package/dist/core/substrate/memory-events.js +1 -0
  457. package/dist/core/substrate/on-read-node.js +1 -1
  458. package/dist/core/substrate/on-read.d.ts +6 -6
  459. package/dist/core/substrate/on-read.js +5 -5
  460. package/dist/core/substrate/plan.js +1 -1
  461. package/dist/core/substrate/render-node.js +1 -1
  462. package/dist/core/substrate/render.d.ts +4 -3
  463. package/dist/core/substrate/render.js +38 -38
  464. package/dist/core/substrate/schema.d.ts +6 -0
  465. package/dist/core/substrate/schema.js +1 -1
  466. package/dist/core/tui/panel.js +1 -1
  467. package/dist/core/user-settings.d.ts +12 -0
  468. package/dist/core/user-settings.js +1 -1
  469. package/dist/core/worktree-mutation-async.js +5 -5
  470. package/dist/core/worktree-quarantine.js +1 -1
  471. package/dist/core/worktree-remove.d.ts +15 -0
  472. package/dist/core/worktree-remove.js +1 -0
  473. package/dist/core/worktree-sweep.js +6 -6
  474. package/dist/daemon/analytics/compute.d.ts +37 -0
  475. package/dist/daemon/analytics/compute.js +1 -0
  476. package/dist/daemon/analytics/scan-worker.d.ts +1 -0
  477. package/dist/daemon/analytics/scan-worker.js +2 -0
  478. package/dist/daemon/analytics/scan.d.ts +37 -0
  479. package/dist/daemon/analytics/scan.js +1 -0
  480. package/dist/daemon/api/app-listener.d.ts +11 -0
  481. package/dist/daemon/api/app-listener.js +21 -0
  482. package/dist/daemon/api/bridge.js +5 -5
  483. package/dist/daemon/api/handlers/analytics.d.ts +2 -0
  484. package/dist/daemon/api/handlers/analytics.js +1 -0
  485. package/dist/daemon/api/handlers/attach.js +1 -1
  486. package/dist/daemon/api/handlers/bash-jobs.js +2 -2
  487. package/dist/daemon/api/handlers/bash.js +1 -1
  488. package/dist/daemon/api/handlers/broker-ops.js +1 -1
  489. package/dist/daemon/api/handlers/canvas.d.ts +1 -1
  490. package/dist/daemon/api/handlers/canvas.js +6 -6
  491. package/dist/daemon/api/handlers/crons.js +1 -1
  492. package/dist/daemon/api/handlers/files.d.ts +1 -1
  493. package/dist/daemon/api/handlers/files.js +1 -1
  494. package/dist/daemon/api/handlers/health.js +2 -2
  495. package/dist/daemon/api/handlers/hook-exec.d.ts +2 -0
  496. package/dist/daemon/api/handlers/hook-exec.js +1 -0
  497. package/dist/daemon/api/handlers/human-requests.js +1 -1
  498. package/dist/daemon/api/handlers/inbox.js +1 -1
  499. package/dist/daemon/api/handlers/llm.d.ts +2 -0
  500. package/dist/daemon/api/handlers/llm.js +3 -0
  501. package/dist/daemon/api/handlers/memory-reads.d.ts +4 -0
  502. package/dist/daemon/api/handlers/memory-reads.js +1 -0
  503. package/dist/daemon/api/handlers/memory.js +5 -1
  504. package/dist/daemon/api/handlers/messages.js +2 -2
  505. package/dist/daemon/api/handlers/modelauth.js +1 -1
  506. package/dist/daemon/api/handlers/node-outcomes.js +1 -1
  507. package/dist/daemon/api/handlers/node-records.d.ts +2 -0
  508. package/dist/daemon/api/handlers/node-records.js +3 -0
  509. package/dist/daemon/api/handlers/nodes.d.ts +1 -1
  510. package/dist/daemon/api/handlers/nodes.js +1 -1
  511. package/dist/daemon/api/handlers/profiles.d.ts +4 -1
  512. package/dist/daemon/api/handlers/profiles.js +1 -1
  513. package/dist/daemon/api/handlers/reports.js +5 -3
  514. package/dist/daemon/api/handlers/reviews.d.ts +1 -1
  515. package/dist/daemon/api/handlers/reviews.js +1 -1
  516. package/dist/daemon/api/handlers/run-routes.d.ts +2 -0
  517. package/dist/daemon/api/handlers/run-routes.js +1 -0
  518. package/dist/daemon/api/handlers/runs.d.ts +9 -0
  519. package/dist/daemon/api/handlers/runs.js +1 -0
  520. package/dist/daemon/api/handlers/subscriptions.js +1 -1
  521. package/dist/daemon/api/handlers/worktree.js +1 -1
  522. package/dist/daemon/api/map.d.ts +10 -4
  523. package/dist/daemon/api/map.js +2 -2
  524. package/dist/daemon/api/operations.d.ts +18 -0
  525. package/dist/daemon/api/operations.js +1 -0
  526. package/dist/daemon/api/principal.d.ts +42 -0
  527. package/dist/daemon/api/principal.js +1 -0
  528. package/dist/daemon/api/router.d.ts +27 -3
  529. package/dist/daemon/api/router.js +1 -1
  530. package/dist/daemon/api/server.d.ts +4 -0
  531. package/dist/daemon/api/server.js +1 -1
  532. package/dist/daemon/api/vendor-signin.d.ts +7 -0
  533. package/dist/daemon/api/vendor-signin.js +77 -0
  534. package/dist/daemon/api/viewer-presence.d.ts +3 -0
  535. package/dist/daemon/api/viewer-presence.js +1 -0
  536. package/dist/daemon/cron/armed-context.d.ts +4 -0
  537. package/dist/daemon/cron/armed-context.js +1 -1
  538. package/dist/daemon/cron/escalation.js +3 -3
  539. package/dist/daemon/cron/lease-recovery.js +1 -1
  540. package/dist/daemon/cron/sinks.js +2 -2
  541. package/dist/daemon/cron-run.d.ts +5 -5
  542. package/dist/daemon/cron-run.js +1 -1
  543. package/dist/daemon/crtrd.js +8 -7
  544. package/dist/daemon/delivery/run-delivery.d.ts +4 -0
  545. package/dist/daemon/delivery/run-delivery.js +1 -1
  546. package/dist/daemon/fleet.d.ts +1 -1
  547. package/dist/daemon/fleet.js +6 -6
  548. package/dist/daemon/human/finish.js +7 -7
  549. package/dist/daemon/joined-owner.d.ts +5 -0
  550. package/dist/daemon/joined-owner.js +1 -0
  551. package/dist/daemon/manage.js +2 -2
  552. package/dist/daemon/messaging/node-message.js +1 -1
  553. package/dist/daemon/park-activity.js +1 -1
  554. package/dist/daemon/reconcilers/bash-deadline.js +1 -1
  555. package/dist/daemon/reconcilers/broker-supervision.d.ts +1 -1
  556. package/dist/daemon/reconcilers/broker-supervision.js +4 -4
  557. package/dist/daemon/reconcilers/delivery-lane.js +1 -1
  558. package/dist/daemon/reconcilers/live-obligation.d.ts +7 -0
  559. package/dist/daemon/reconcilers/live-obligation.js +1 -1
  560. package/dist/daemon/reconcilers/node-lifecycle/tick.js +1 -1
  561. package/dist/daemon/reconcilers/storage-maintenance.d.ts +20 -1
  562. package/dist/daemon/reconcilers/storage-maintenance.js +1 -1
  563. package/dist/daemon/runs/append-section.d.ts +6 -0
  564. package/dist/daemon/runs/append-section.js +2 -0
  565. package/dist/daemon/runs/observer.d.ts +5 -0
  566. package/dist/daemon/runs/observer.js +4 -0
  567. package/dist/launcher/bwrap.d.ts +4 -0
  568. package/dist/launcher/bwrap.js +2 -0
  569. package/dist/launcher/client.d.ts +2 -0
  570. package/dist/launcher/client.js +3 -0
  571. package/dist/launcher/main.d.ts +1 -0
  572. package/dist/launcher/main.js +3 -0
  573. package/dist/launcher/netrule.d.ts +1 -0
  574. package/dist/launcher/netrule.js +1 -0
  575. package/dist/launcher/seccomp.d.ts +1 -0
  576. package/dist/launcher/seccomp.js +1 -0
  577. package/dist/launcher/spec.d.ts +88 -0
  578. package/dist/launcher/spec.js +1 -0
  579. package/dist/launcher/users.d.ts +18 -0
  580. package/dist/launcher/users.js +7 -0
  581. package/dist/launcher/validate.d.ts +22 -0
  582. package/dist/launcher/validate.js +1 -0
  583. package/dist/migrations/corpus.js +3 -3
  584. package/dist/migrations/runner.js +1 -1
  585. package/dist/native/linux/addon.node +0 -0
  586. package/dist/native/linux.d.ts +29 -0
  587. package/dist/native/linux.js +1 -0
  588. package/dist/pi-extensions/broker-local.js +2 -2
  589. package/dist/pi-extensions/canvas-bash-valve.d.ts +1 -3
  590. package/dist/pi-extensions/canvas-bash-valve.js +4 -7
  591. package/dist/pi-extensions/canvas-context-intro.d.ts +1 -2
  592. package/dist/pi-extensions/canvas-context-intro.js +2 -2
  593. package/dist/pi-extensions/canvas-doc-substrate.js +6 -6
  594. package/dist/pi-extensions/canvas-inbox-watcher.d.ts +2 -1
  595. package/dist/pi-extensions/canvas-inbox-watcher.js +2 -1
  596. package/dist/pi-extensions/canvas-passive-context.d.ts +1 -1
  597. package/dist/pi-extensions/canvas-passive-context.js +11 -11
  598. package/dist/pi-extensions/canvas-recap.js +6 -6
  599. package/dist/pi-extensions/canvas-stophook.js +1 -1
  600. package/dist/pi-extensions/canvas-structured-output.js +4 -4
  601. package/dist/pi-extensions/canvas-tool-guide.js +1 -1
  602. package/dist/pi-extensions/system-prompt-entry.d.ts +15 -0
  603. package/dist/pi-extensions/system-prompt-entry.js +1 -0
  604. package/dist/shared/env.d.ts +5 -1
  605. package/dist/shared/env.js +1 -1
  606. package/dist/shared/strip-cd-prefix.d.ts +1 -0
  607. package/dist/shared/strip-cd-prefix.js +1 -0
  608. package/dist/types.d.ts +31 -15
  609. package/docs/cli/memory-and-preferences.md +3 -1
  610. package/docs/sdk/client.md +34 -0
  611. package/docs/sdk/errors.md +2 -0
  612. package/docs/sdk/memory.md +2 -2
  613. package/docs/sdk/streaming.md +21 -0
  614. package/package.json +18 -4
  615. package/packages/crouter-identity/dist/index.d.ts +54 -0
  616. package/packages/crouter-identity/dist/index.js +166 -0
  617. package/packages/crouter-identity/package.json +33 -0
  618. package/runtime.lock.json +34 -8
  619. package/scripts/build-native-linux.mjs +16 -0
  620. package/scripts/install-runtime.mjs +9 -7
  621. package/scripts/lib/isolation-env.mjs +42 -0
  622. package/scripts/runtime-smoke.mjs +49 -0
  623. package/src/native/linux/addon.c +249 -0
  624. package/dist/core/profiles/state-block.d.ts +0 -4
  625. package/dist/core/profiles/state-block.js +0 -3
  626. package/dist/core/runtime/broker/auth-reload.d.ts +0 -41
  627. package/dist/core/runtime/broker/auth-reload.js +0 -1
  628. package/dist/core/substrate/cli-context-delivery.d.ts +0 -22
  629. package/dist/core/substrate/cli-context-delivery.js +0 -1
@@ -1,3 +1,4 @@
1
+ import type { MemoryTarget } from '../memory-resolver.js';
1
2
  import type { NodeConfigSubject } from '../substrate/subject-fields.js';
2
3
  import type { ExposureTarget } from '../substrate/injected-store.js';
3
4
  import type { BrokerExtensionNodeDTO, BrokerExtensionStateDTO } from '../../api/dto/broker-ops.js';
@@ -10,10 +11,6 @@ export declare function buildProjectContextBlockForBroker(cwd: string): string;
10
11
  * another (see situational-context.ts). '' when none is set. */
11
12
  export declare function buildContextBearingsFromState(state: BrokerExtensionStateDTO, projectContext: string, situational?: string, target?: ExposureTarget): string;
12
13
  export declare function buildForkBearingsFromState(state: BrokerExtensionStateDTO, situational?: string): string;
13
- export declare function renderPreferencesFromState(state: BrokerExtensionStateDTO, target?: ExposureTarget): string;
14
14
  /** The same preference block without the extension-state DTO, for the daemon-side
15
15
  * claim path that holds a node's subject directly. */
16
- export declare function renderPreferencesForNodeSubject(nodeId: string, subject: NodeConfigSubject | null, target?: ExposureTarget): string;
17
- /** A canonical report ref has already been validated by crtrd in state. The
18
- * broker reads only its local filesystem content; no canvas accessor is needed. */
19
- export declare function reportPathFromRef(ref: string, reportNodes: ReadonlyMap<string, unknown>): string | null;
16
+ export declare function renderPreferencesForNodeSubject(nodeId: string, subject: NodeConfigSubject | null, target?: ExposureTarget, grantee?: string, memoryTarget?: MemoryTarget): string;
@@ -1,5 +1,5 @@
1
- var k=Object.defineProperty;var s=(e,r)=>k(e,"name",{value:r,configurable:!0});import{contextDir as h,nodeDir as b}from"../canvas/paths.js";import{interpolateNodePaths as v}from"../canvas/paths.js";import{fullName as l}from"../canvas/labels.js";import{renderKnowledgeForSubject as x,renderPreferencesForSubject as _}from"../substrate/render.js";import{renderWorkspaceOpenDocsForSubject as $}from"../substrate/on-read.js";import{buildProjectContextBlock as N,contextDirNote as j,profileNote as S,relativeLabel as F,renderGraphMap as T,buildIdentityAssertion as B,worktreeNote as C}from"./bearings-render.js";function q(e){const r=(e.icon??"").trim(),t=e.name!==e.kind?e.name.trim():"",o=t!==""?t:(e.description??"").trim()||e.name;return r===""?o:`${r} ${o}`}s(q,"editorLabelForBrokerNode");function E(e){return N(e)}s(E,"buildProjectContextBlockForBroker");function D(e){return j(e)}s(D,"contextDirNote");function p(e){return S(e.cwd,e.profile_id)}s(p,"profileNote");function G(e){return F(e)}s(G,"relativeLabel");function f(e){const{ancestors:r,children:t,node:o}=e;return T(o.node_id,o.kind,o.mode,r,t)}s(f,"graphMap");function m(e){const{node:r,fork_source:t}=e,o=t===null?r.fork_from??"":`${r.fork_from} ("${l(t)}")`;return B(r.node_id,r.kind,r.mode,r.fork_from,o)}s(m,"identity");function w(e){return C(e.managed_worktree)}s(w,"worktreeNote");function P(e){const r=e.review_binding;if(r==null)return"";if(r.kind==="page_feedback"){const t=r.review_id,o=r.target_file;return`You exist for one page's feedback conversation \u2014 ticket \`${t}\`, page source \`${o}\`. Think with the person about this one page and answer in a few plain sentences from the context you already carry. Revise the page in place with \`crtr human send --replace ${t} --page ${o}\` \u2014 it swaps in on their screen immediately \u2014 and briefly say what changed; a silent swap leaves them guessing. After dealing with an open feedback item \u2014 by revising the page or answering it here \u2014 resolve it with \`crtr human feedback resolve <comment_id>\`; \`crtr human feedback list ${t}\` shows each item's id and status. Never author feedback or resolve an item before dealing with it \u2014 a sent comment is immutable, and resolution is your report that the work is done. Asked to act beyond this page, give your advice and point the person at submitting it: the submitted answer is what reaches the task's owner, while work done here is invisible to it and ends when the ticket settles. When a question needs real exploration, delegate it to a child node and keep talking while it runs. The inherited conversation belongs to the origin node, not you \u2014 its task stays with it; carry only the context needed for this page. The person's visible transcript begins at the boundary marker above; everything earlier is context they cannot see \u2014 never treat it as shared ground; when they ask about it, answer plainly in your own words rather than replaying it.`}return`You exist for one human review of \`${r.target_file}\`. The inherited conversation belongs to the origin node, not you \u2014 carry only the context needed for this review. The person's visible transcript begins at the boundary marker above; everything earlier is context they cannot see.`}s(P,"reviewNote");function K(e,r,t="",o){const{node:i}=e,n=["<crtr-bearings>",m(e)],c=f(e);c!==""&&n.push("","## Your place in the canvas",c),n.push("","## Your context directory",D(i.node_id));const d=p(i);d!==""&&n.push("",d);const u=w(i);u!==""&&n.push("","## Your managed worktree",u),i.mode==="orchestrator"&&n.push("",`Because you persist across refresh cycles, your context directory (${h(i.node_id)}) is also where a future cycle of you resumes the work \u2014 keep the working notes and decisions a refreshed you would need there, alongside the docs you share with the nodes you spawn.`),n.push("</crtr-bearings>");const a=x(e.subject,i.node_id,o),g=$(e.subject,i.cwd,i.profile_id,o);return[n.join(`
2
- `),a,g,t,r].filter(y=>y!=="").join(`
3
- `)}s(K,"buildContextBearingsFromState");function U(e,r=""){const{node:t,fork_source:o}=e,i=o?.status==="active"||o?.status==="idle"?`Source node ${o.node_id} ("${l(o)}") is still live and still holds the mandate from the copied conversation; do not resume that work here.`:"The source node\u2019s earlier graph position, lifecycle, children, schedules, worktree, situational context, and context-directory path do not carry over. Shared conversation, project, and operating context remain reference material.",n=["<crtr-bearings>",m(e),"",i,"","## Your node now",`Lifecycle: ${t.lifecycle}.`],c=f(e);if(n.push(...c===""?["Canvas: independent root with no parent or inherited graph edges."]:["",c]),n.push(`Context directory: \`${h(t.node_id)}\` (\`$CRTR_CONTEXT_DIR\`). Use this path in place of every source-node context path above.`),(o===null||o.cwd!==t.cwd)&&n.push(`Working directory: \`${t.cwd}\`.`),o===null||o.profile_id!==t.profile_id){const a=p(t);a!==""&&n.push(a)}const d=w(t);d!==""&&n.push("","## Your managed worktree",d),t.mode==="orchestrator"&&n.push("",`Because you persist across refresh cycles, your context directory (${h(t.node_id)}) is also where a future cycle of you resumes the work \u2014 keep the working notes and decisions a refreshed you would need there, alongside the docs you share with the nodes you spawn.`);const u=P(t);return u!==""&&n.push("",u),n.push("","The first real user message after these bearings is your mandate.","</crtr-bearings>"),[n.join(`
1
+ var k=Object.defineProperty;var s=(e,r)=>k(e,"name",{value:r,configurable:!0});import{contextDir as h,interpolateNodePaths as b}from"../canvas/paths.js";import{fullName as l}from"../canvas/labels.js";import{renderKnowledgeForSubject as v,renderPreferencesForSubject as x}from"../substrate/render.js";import{renderWorkspaceOpenDocsForSubject as _}from"../substrate/on-read.js";import{buildProjectContextBlock as $,contextDirNote as N,profileNote as j,relativeLabel as S,renderGraphMap as F,buildIdentityAssertion as T,worktreeNote as B}from"./bearings-render.js";function M(e){const r=(e.icon??"").trim(),t=e.name!==e.kind?e.name.trim():"",o=t!==""?t:(e.description??"").trim()||e.name;return r===""?o:`${r} ${o}`}s(M,"editorLabelForBrokerNode");function W(e){return $(e)}s(W,"buildProjectContextBlockForBroker");function C(e,r){return N(e,r)}s(C,"contextDirNote");function p(e){return j(e.cwd,e.profile_id)}s(p,"profileNote");function O(e){return S(e)}s(O,"relativeLabel");function f(e){const{ancestors:r,children:t,node:o}=e;return F(o.node_id,o.kind,o.mode,r,t)}s(f,"graphMap");function w(e){const{node:r,fork_source:t}=e,o=t===null?r.fork_from??"":`${r.fork_from} ("${l(t)}")`;return T(r.node_id,r.kind,r.mode,r.fork_from,o)}s(w,"identity");function g(e){return B(e.managed_worktree)}s(g,"worktreeNote");function Y(e){const r=e.review_binding;if(r==null)return"";if(r.kind==="page_feedback"){const t=r.review_id,o=r.target_file;return`You exist for one page's feedback conversation \u2014 ticket \`${t}\`, page source \`${o}\`. Think with the person about this one page and answer in a few plain sentences from the context you already carry. Revise the page in place with \`crtr human send --replace ${t} --page ${o}\` \u2014 it swaps in on their screen immediately \u2014 and briefly say what changed; a silent swap leaves them guessing. After dealing with an open feedback item \u2014 by revising the page or answering it here \u2014 resolve it with \`crtr human feedback resolve <comment_id>\`; \`crtr human feedback list ${t}\` shows each item's id and status. Never author feedback or resolve an item before dealing with it \u2014 a sent comment is immutable, and resolution is your report that the work is done. Asked to act beyond this page, give your advice and point the person at submitting it: the submitted answer is what reaches the task's owner, while work done here is invisible to it and ends when the ticket settles. When a question needs real exploration, delegate it to a child node and keep talking while it runs. The inherited conversation belongs to the origin node, not you \u2014 its task stays with it; carry only the context needed for this page. The person's visible transcript begins at the boundary marker above; everything earlier is context they cannot see \u2014 never treat it as shared ground; when they ask about it, answer plainly in your own words rather than replaying it.`}return`You exist for one human review of \`${r.target_file}\`. The inherited conversation belongs to the origin node, not you \u2014 carry only the context needed for this review. The person's visible transcript begins at the boundary marker above; everything earlier is context they cannot see.`}s(Y,"reviewNote");function q(e,r,t="",o){const{node:i}=e,n=["<crtr-bearings>",w(e)],c=f(e);c!==""&&n.push("","## Your place in the canvas",c),n.push("","## Your context directory",C(i.node_id,i.grantee));const d=p(i);d!==""&&n.push("",d);const u=g(i);u!==""&&n.push("","## Your managed worktree",u),i.mode==="orchestrator"&&n.push("",`Because you persist across refresh cycles, your context directory (${h(i.node_id,i.grantee)}) is also where a future cycle of you resumes the work \u2014 keep the working notes and decisions a refreshed you would need there, alongside the docs you share with the nodes you spawn.`),n.push("</crtr-bearings>");const a=v(e.subject,i.node_id,o,void 0,i.grantee),m=_(e.subject,i.cwd,i.profile_id,o);return[n.join(`
2
+ `),a,m,t,r].filter(y=>y!=="").join(`
3
+ `)}s(q,"buildContextBearingsFromState");function E(e,r=""){const{node:t,fork_source:o}=e,i=o?.status==="active"||o?.status==="idle"?`Source node ${o.node_id} ("${l(o)}") is still live and still holds the mandate from the copied conversation; do not resume that work here.`:"The source node\u2019s earlier graph position, lifecycle, children, schedules, worktree, situational context, and context-directory path do not carry over. Shared conversation, project, and operating context remain reference material.",n=["<crtr-bearings>",w(e),"",i,"","## Your node now",`Lifecycle: ${t.lifecycle}.`],c=f(e);if(n.push(...c===""?["Canvas: independent root with no parent or inherited graph edges."]:["",c]),n.push(`Context directory: \`${h(t.node_id,t.grantee)}\` (\`$CRTR_CONTEXT_DIR\`). Use this path in place of every source-node context path above.`),(o===null||o.cwd!==t.cwd)&&n.push(`Working directory: \`${t.cwd}\`.`),o===null||o.profile_id!==t.profile_id){const a=p(t);a!==""&&n.push(a)}const d=g(t);d!==""&&n.push("","## Your managed worktree",d),t.mode==="orchestrator"&&n.push("",`Because you persist across refresh cycles, your context directory (${h(t.node_id,t.grantee)}) is also where a future cycle of you resumes the work \u2014 keep the working notes and decisions a refreshed you would need there, alongside the docs you share with the nodes you spawn.`);const u=Y(t);return u!==""&&n.push("",u),n.push("","The first real user message after these bearings is your mandate.","</crtr-bearings>"),[n.join(`
4
4
  `),r].filter(a=>a!=="").join(`
5
- `)}s(U,"buildForkBearingsFromState");function X(e,r){return Y(e.node.node_id,e.subject,r)}s(X,"renderPreferencesFromState");function Y(e,r,t){return v(_(r,t).block,e)}s(Y,"renderPreferencesForNodeSubject");function z(e,r){const t=e.indexOf(":");if(t<=0)return null;const o=e.slice(0,t),i=e.slice(t+1);return!r.has(o)||!i.startsWith("reports/")||i.includes("..")||i.startsWith("/")?null:`${b(o)}/${i}`}s(z,"reportPathFromRef");export{K as buildContextBearingsFromState,U as buildForkBearingsFromState,E as buildProjectContextBlockForBroker,q as editorLabelForBrokerNode,Y as renderPreferencesForNodeSubject,X as renderPreferencesFromState,z as reportPathFromRef};
5
+ `)}s(E,"buildForkBearingsFromState");function G(e,r,t,o,i){return b(x(r,t,void 0,i).block,e,o)}s(G,"renderPreferencesForNodeSubject");export{q as buildContextBearingsFromState,E as buildForkBearingsFromState,W as buildProjectContextBlockForBroker,M as editorLabelForBrokerNode,G as renderPreferencesForNodeSubject};
@@ -1,4 +1,4 @@
1
- var g=Object.defineProperty;var i=(e,o)=>g(e,"name",{value:o,configurable:!0});import{contextDir as b}from"../canvas/paths.js";import{emitEvent as S}from"../events/emit.js";import{brokerExtensionState as m,commitBrokerPersonaAck as h}from"./broker/daemon-ops.js";import{readRoadmap as C,roadmapPath as v}from"./roadmap.js";import{buildSubPersonaMenu as y,renderConfigChangeDelta as E}from"../substrate/render.js";import{cloneContextExposureState as T,contextExposureStatesEqual as _,exposureTarget as P,loadContextExposureState as Y,mergeContextExposureState as j,replaceContextExposureState as D,saveContextExposureState as w,sharedContextExposureState as $}from"../substrate/injected-store.js";import{formatCard as G}from"../../shared/generated-context.js";function B(e){return`Because you persist across refresh cycles, your context directory (${b(e)}) is also where a future cycle of you resumes the work \u2014 keep the working notes and decisions a refreshed you would need there, alongside the docs you share with the nodes you spawn.`}i(B,"orchestratorContextNote");function H(e){const o=C(e.node_id)??"(no roadmap yet)",r=v(e.node_id);return[`You are now a ${e.kind.toUpperCase()} ORCHESTRATOR. Your scarce resource is your own context window.`,"Your job is to manage context and delegate \u2014 not to do the goal yourself.","",`Your roadmap scaffold (\`${r}\`) \u2014 author it now: state the goal, exit criteria, and the phase skeleton, using the approach below. Current contents:`,"",o,"",B(e.node_id),"",'Your three long-term memory scopes (user-global, project, node-local) already surface in your bearings at boot. What promotion changes is USE, not access: you now persist across refresh cycles, so node-local carries what THIS goal needs between your refreshes, and durable facts you commit to user-global or project outlive this node. Use `crtr memory write` to save a document; `crtr memory list` to browse; `crtr memory find` to search (see "Your long-term memory" above for the full substrate flow).',"","Then delegate each phase with `crtr node new --kind <kind>`. When your context fills, run `crtr node yield` to refresh against this roadmap."].join(`
2
- `)}i(H,"orchestrationGuidance");function M(){return"You are HANDS-ON again \u2014 base mode. Do the work yourself in THIS window and finish it here; stop delegating by default. You no longer drive a roadmap, so `crtr node yield` is not your exit. Spawn a child only for a cleanly separable unit, never as your first move."}i(M,"baseModeGuidance");function R(e,o){if(e.kind===o.kind)return"";const r=y(e.kind),t=y(o.kind);return r===t?"":t===""?`The ${o.kind} kind has no specialist sub-personas available.`:t}i(R,"subPersonaGuidance");function A(e,o,r,t){const n=[];return o.mode!==r.mode&&n.push(r.mode==="orchestrator"?H(e.node):M()),n.push(R(o,r)),n.push(E(e.subject,e.node.node_id,P(t,"transcript"))),n.filter(a=>a!=="").join(`
1
+ var C=Object.defineProperty;var s=(o,e)=>C(o,"name",{value:e,configurable:!0});import{contextDir as h}from"../canvas/paths.js";import{existsSync as S,readFileSync as v}from"node:fs";import{join as E}from"node:path";import{emitEvent as T}from"../events/emit.js";import{brokerContext as P,brokerContextEvent as Y,brokerExtensionState as y,commitBrokerContext as w,commitBrokerPersonaAck as k}from"./broker/daemon-ops.js";import{buildSubPersonaMenu as x}from"../substrate/render.js";import{contextExposureStatesEqual as _,mergeContextExposureState as j,replaceContextExposureState as D,restoreContextExposure as g,sharedContextExposureState as $,snapshotContextExposure as B}from"../substrate/injected-store.js";import{formatCard as G}from"../../shared/generated-context.js";function H(o,e){return`Because you persist across refresh cycles, your context directory (${h(o,e)}) is also where a future cycle of you resumes the work \u2014 keep the working notes and decisions a refreshed you would need there, alongside the docs you share with the nodes you spawn.`}s(H,"orchestratorContextNote");function M(o){const e=E(h(o.node_id,o.grantee),"roadmap.md"),r=S(e)?v(e,"utf8"):"(no roadmap yet)";return[`You are now a ${o.kind.toUpperCase()} ORCHESTRATOR. Your scarce resource is your own context window.`,"Your job is to manage context and delegate \u2014 not to do the goal yourself.","",`Your roadmap scaffold (\`${e}\`) \u2014 author it now: state the goal, exit criteria, and the phase skeleton, using the approach below. Current contents:`,"",r,"",H(o.node_id,o.grantee),"",'Your three long-term memory scopes (user-global, project, node-local) already surface in your bearings at boot. What promotion changes is USE, not access: you now persist across refresh cycles, so node-local carries what THIS goal needs between your refreshes, and durable facts you commit to user-global or project outlive this node. Use `crtr memory write` to save a document; `crtr memory list` to browse; `crtr memory find` to search (see "Your long-term memory" above for the full substrate flow).',"","Then delegate each phase with `crtr node new --kind <kind>`. When your context fills, run `crtr node yield` to refresh against this roadmap."].join(`
2
+ `)}s(M,"orchestrationGuidance");function A(){return"You are HANDS-ON again \u2014 base mode. Do the work yourself in THIS window and finish it here; stop delegating by default. You no longer drive a roadmap, so `crtr node yield` is not your exit. Spawn a child only for a cleanly separable unit, never as your first move."}s(A,"baseModeGuidance");function N(o,e){if(o.kind===e.kind)return"";const r=x(o.kind),t=x(e.kind);return r===t?"":t===""?`The ${e.kind} kind has no specialist sub-personas available.`:t}s(N,"subPersonaGuidance");function O(o,e,r,t){const n=[];return e.mode!==r.mode&&n.push(r.mode==="orchestrator"?M(o.node):A()),n.push(N(e,r)),n.push(t),n.filter(c=>c!=="").join(`
3
3
 
4
- `)}i(A,"transitionGuidance");function p(e){const o=e.node,r={kind:o.kind,mode:o.mode,lifecycle:o.lifecycle},t=o.persona_ack,n=t===void 0?r:{kind:t.kind??o.kind,mode:t.mode,lifecycle:t.lifecycle};return n.kind===r.kind&&n.mode===r.mode&&n.lifecycle===r.lifecycle?null:{from:n,to:r}}i(p,"personaDriftFromBrokerState");async function K(e){const o=p(e);if(o===null)return!1;if(!(await h(e.node.node_id,o)).applied)throw new Error(`persona baseline acknowledgment was rejected for ${e.node.node_id}`);return!0}i(K,"acknowledgePersonaBaseline");async function N(e,o){const r=e.node.node_id,t=$(r),n=Y(r);if(j(t,n),t.preferenceSnapshot===null)throw new Error(`context preference snapshot is missing for ${r}`);_(t,n)||w(r,t);let a=e,d=p(a);if(d===null)return!1;const u=T(t);let s=d.from;for(;;){const c={kind:a.node.kind,mode:a.node.mode,lifecycle:a.node.lifecycle};if(s.kind!==c.kind||s.mode!==c.mode||s.lifecycle!==c.lifecycle){const l=A(a,s,c,u);l!==""&&await o(G("persona-transition",{},l)),s=c,D(t,u),w(r,t)}if(d=p(a),d===null||(await h(r,d)).applied)return!0;a=await m(r)}}i(N,"deliverPendingPersonaTransition");function L(e,o,r=()=>{}){const{agent:t}=o,n=t.transformContext;t.transformContext=async(a,d)=>{const u=n===void 0?a:await n(a,d);try{const s=await m(e);return await N(s,c=>{const f={nodeId:e},l={role:"custom",customType:"crtr-persona-transition",content:c,display:!0,details:f,timestamp:Date.now()};o.sessionManager.appendCustomMessageEntry("crtr-persona-transition",c,!0,f);const k=t.state.messages;for(const x of new Set([k,a,u]))x.push(l)}),u}catch(s){throw r(),S({event:"broker.daemon.operation.failed",level:"error",node_id:e,error:s,fields:{operation:"persona_transition"}}),s}}}i(L,"installPersonaTransitionGate");export{K as acknowledgePersonaBaseline,N as deliverPendingPersonaTransition,L as installPersonaTransitionGate,p as personaDriftFromBrokerState};
4
+ `)}s(O,"transitionGuidance");function m(o){const e=o.node,r={kind:e.kind,mode:e.mode,lifecycle:e.lifecycle},t=e.persona_ack,n=t===void 0?r:{kind:t.kind??e.kind,mode:t.mode,lifecycle:t.lifecycle};return n.kind===r.kind&&n.mode===r.mode&&n.lifecycle===r.lifecycle?null:{from:n,to:r}}s(m,"personaDriftFromBrokerState");async function Q(o){const e=m(o);if(e===null)return!1;if(!(await k(o.node.node_id,e)).applied)throw new Error(`persona baseline acknowledgment was rejected for ${o.node.node_id}`);return!0}s(Q,"acknowledgePersonaBaseline");async function R(o,e){const r=o.node.node_id,t=$(r),n=await P(r,"preferences"),c=g(n.snapshot);if(j(t,c),t.preferenceSnapshot===null)throw new Error(`context preference snapshot is missing for ${r}`);_(t,c)||await w(r,B(t),n.loads);let i=o,d=m(i);if(d===null)return!1;let a=d.from;for(;;){const u={kind:i.node.kind,mode:i.node.mode,lifecycle:i.node.lifecycle};if(a.kind!==u.kind||a.mode!==u.mode||a.lifecycle!==u.lifecycle){const l=await Y(r,"persona"),f=O(i,a,u,l.content);f!==""&&await e(G("persona-transition",{},f)),a=u,await w(r,l.snapshot,l.loads),D(t,g(l.snapshot))}if(d=m(i),d===null||(await k(r,d)).applied)return!0;i=await y(r)}}s(R,"deliverPendingPersonaTransition");function V(o,e,r=()=>{}){const{agent:t}=e,n=t.transformContext;t.transformContext=async(c,i)=>{const d=n===void 0?c:await n(c,i);try{const a=await y(o);return await R(a,u=>{const p={nodeId:o},l={role:"custom",customType:"crtr-persona-transition",content:u,display:!0,details:p,timestamp:Date.now()};e.sessionManager.appendCustomMessageEntry("crtr-persona-transition",u,!0,p);const f=t.state.messages;for(const b of new Set([f,c,d]))b.push(l)}),d}catch(a){throw r(),T({event:"broker.daemon.operation.failed",level:"error",node_id:o,error:a,fields:{operation:"persona_transition"}}),a}}}s(V,"installPersonaTransitionGate");export{Q as acknowledgePersonaBaseline,R as deliverPendingPersonaTransition,V as installPersonaTransitionGate,m as personaDriftFromBrokerState};
@@ -2,6 +2,7 @@ import type { AgentSession, AgentSessionEvent, RpcExtensionUIRequest, RpcExtensi
2
2
  import type { Api, ImageContent, Model } from '@earendil-works/pi-ai';
3
3
  import type { BrokerErrorFrame, BrokerNodeNamedFrame } from '../../api/dto/broker.js';
4
4
  import type { ToolGroupSummary } from '../../shared/tool-groups.js';
5
+ import type { ModelIntent } from '../../types.js';
5
6
  import type { MessageOrigin, MessageVisibility } from './stamp/protocol.js';
6
7
  /** pi's own RPC types, re-exported unchanged. `broker-protocol` stays the one
7
8
  * import site for the wire union; the shapes themselves are pi's, versioned by
@@ -177,17 +178,15 @@ export interface ByeFrame {
177
178
  export interface ShutdownFrame {
178
179
  type: 'shutdown';
179
180
  }
180
- /** `setModel(model)` — `/model` (selector resolves → chosen id). `pinned`,
181
- * when present, is the durable-pin decision for this change — decided by the
182
- * SENDER from the model's RAW pre-normalize token (a caller that must
183
- * normalize before sending, e.g. `setModelLive`, computes it from the token
184
- * it normalized away). Omitted — the common case, where `model` itself IS the
185
- * raw/explicit token (a slash-command arg, or a concrete picker pick) — the
186
- * broker derives it from `model`'s own shape. */
181
+ /** `setModel(model)` — `/model` (selector resolves → chosen id). `intent`,
182
+ * when present, is the portable routing contract the SENDER derived from the
183
+ * RAW token it normalized before sending (e.g. `setModelLive`). Omitted, the
184
+ * broker derives it from `model` itself (`explicitModelIntent`): a portable
185
+ * token such as `anthropic/strong` becomes an intent, a concrete id stays exact. */
187
186
  export interface SetModelFrame {
188
187
  type: 'set_model';
189
188
  model: string;
190
- pinned?: boolean;
189
+ intent?: ModelIntent;
191
190
  }
192
191
  /** Push a custom message into a LIVE engine's session WITHOUT waking it.
193
192
  *
@@ -1 +1 @@
1
- var ve=Object.defineProperty;var e=(t,n)=>ve(t,"name",{value:n,configurable:!0});import{envModelIntent as he,envNodeCwd as _e,envNodeId as we,envProfileId as ye}from"../../shared/env.js";import{createServer as Se}from"node:net";import{existsSync as se,readFileSync as be,unlinkSync as ae}from"node:fs";import{join as K}from"node:path";import{randomUUID as M}from"node:crypto";import{mark as Te}from"../timing.js";import{getAgentDir as V,initTheme as Ee,ModelRegistry as ke,ModelRuntime as Re}from"@earendil-works/pi-coding-agent";import{nodeDir as xe,viewSocketPath as Ce}from"../canvas/paths.js";import{bindBrokerEventSource as Ae}from"../events/source.js";import{emitEvent as T}from"../events/emit.js";import{operationIdContext as Me}from"../events/operation-id.js";import{findMissingPackagePaths as Pe}from"./package-health.js";import{FRONT_DOOR_ENV as Ie}from"./front-door.js";import{CANVAS_EXTENSIONS as X,piInvocationToSdkConfig as Oe}from"./launch.js";import{assertEngineVersion as De,loadBrokerEngine as Fe}from"./broker-sdk.js";import{resolveBundledPiPackageDir as Ne}from"./pi-cli.js";import{captureSessionChatCapabilities as Le}from"./command-surface.js";import{PoolCredentialStore as $e}from"../pool-credential-store.js";import{mutateBrokerFault as U,recordBrokerTurn as de}from"./broker/daemon-ops.js";import{modelRequestFromConfig as je,selectInitialModelRoute as Be,unregisteredConcreteModel as Ge}from"../model-routes.js";import{KNOWN_STREAM_WAIT_UI as Ue}from"./stream-watchdog.js";import{probeOnline as We}from"./connectivity.js";import{CRTR_CYCLE_CUSTOM_TYPE as qe,cycleAwareMessages as Ke}from"./session-cycles.js";import{projectTranscript as Ve}from"./session-visibility.js";import{currentTurnVisibility as Xe}from"./turn-visibility.js";import{isUnknownModel as H}from"./model-selection.js";import{BrokerClientRegistry as He}from"./broker/client-registry.js";import{ToolGroupTracker as Ye}from"./broker/tool-groups.js";import{onNodeNamed as ze}from"./broker/node-named.js";import{FaultRetry as Je}from"./broker/fault-retry.js";import{createTurnAdmissionGate as Qe}from"./broker/turn-admission.js";import{BROKER_IDLE_TURN_START as Ze}from"./broker/held-deferred-inbox.js";import{EventProjection as et}from"./broker/event-projection.js";import{createFrameDispatchContext as tt,handleFrame as nt}from"./broker/frame-dispatch.js";import{hydratePersistedAdvertisedCommandMessages as ot,installAdvertisedCommandInvocationContract as rt}from"./advertised-command-invocation.js";import{RebindDriver as it}from"./broker/rebind.js";import{beginRuntimeTeardown as st}from"./broker/extension-abort.js";import{decodeKickoffOrigin as at,KICKOFF_ORIGIN_ENV as dt}from"./stamp/protocol.js";import{announceMessageOrigin as lt}from"./stamp/channel.js";import{brokerExtensionState as ct,commitBrokerModel as mt}from"./broker/daemon-ops.js";import{FrameOverflowError as ut,normalizeSnapshotTail as ft}from"./broker-protocol.js";import{ReviewBoundaryNavigationError as gn,REVIEW_BOUNDARY_NAVIGATION_CODE as vn}from"./broker/frame-replies.js";function Y(t){return new ke(t.modelRuntime)}e(Y,"registryOf");function pt(t){return{authPath:K(t,"auth.json"),modelsPath:K(t,"models.json")}}e(pt,"modelRuntimePaths");function L(t,n){if(t==null||H(t))return null;const s=n!==void 0&&n!==""&&n!=="off"?`:${n}`:"";return`${t.provider}/${t.id}${s}`}e(L,"formatModelSpec");function gt(t,n){const s=L(t,void 0);return s===null?null:`${s}:${n===void 0||n===""?"off":n}`}e(gt,"formatExactModelSpec");const vt=12e4;let W=null;function ht(){const t=W;if(W=null,t!==null)try{t.dispose()}catch{}}e(ht,"disposeActiveSession");async function un(t,n=process.hrtime.bigint(),s=new Date().toISOString()){Ae(t),Me.fresh(()=>{T({level:"info",event:"broker.startup.cli_entry",ts:s,duration_ms:0,fields:{runtime_version:process.version,engine_version:null,model:null}}),T({level:"info",event:"broker.startup.module_loaded",duration_ms:Number(process.hrtime.bigint()-n)/1e6,fields:{runtime_version:process.version,engine_version:null,model:null}})});const p=new Set;let i=null;const a=e((o,r=null)=>{p.has(o)||(p.add(o),Te(o,{duration_ms:Number(process.hrtime.bigint()-n)/1e6}),T({level:"info",event:o,duration_ms:Number(process.hrtime.bigint()-n)/1e6,fields:{runtime_version:process.version,engine_version:i,model:r}}))},"emitStartupMilestone");process.env[Ie]="1",process.env.CRTR_BROKER_PID=String(process.pid),delete process.env.TMUX_PANE,delete process.env.TMUX;const d=await Fe();De(d.VERSION),i=d.VERSION;const l=xe(t),m=K(l,"broker-launch.json"),h=JSON.parse(be(m,"utf8")),g=Oe(h);g.modelExact===!0?process.env.CRTR_MODEL_EXACT="1":delete process.env.CRTR_MODEL_EXACT;let{session:_,services:S,resuming:k,runtime:E}=await St(d,g);const R=(await ct(t)).node.review_binding?.review_id;W=_;const B=We;try{process.env.PI_PACKAGE_DIR=Ne(),Ee(S.settingsManager.getTheme(),!1)}catch(o){T({level:"error",event:"broker.theme.initialization_failed",error:o})}try{for(const o of Pe(V()))T({level:"warn",event:"broker.startup.warning",fields:{stage:"package_health",source:o.source,resolved_path:o.resolved}})}catch{}const x=Ce(t),u=new He(t),D=new Map,b=new Ye(t,o=>u.broadcast(o));ze(o=>u.broadcast({type:"node_named",...o}));let P=!1,F=!1,A,$,c,C,N,z=e(()=>{},"notifyTurnAccepted"),J=e(()=>{},"resetFrameState");c=new it({nodeId:t,cfg:g,session:_,services:S,runtime:E,registry:u,toolGroups:b,uiContext:e(()=>$,"uiContext"),faultRetry:e(()=>C,"faultRetry"),projection:e(()=>N,"projection"),setActiveSession:e(o=>{W=o},"setActiveSession"),disposeAndExit:e((o,r)=>j(o,r),"disposeAndExit"),onSessionRebind:e(()=>{J()},"onSessionRebind"),reWelcomeAll:e(()=>te(),"reWelcomeAll")});const Q=e(async(o,r=!1)=>{const f=c.session(),v=L(f.model,f.thinkingLevel);if(v===null)return null;const w=await mt(t,{spec:v,pinnedOverride:o,userSelected:r});return r&&(delete process.env.CRTR_MODEL_INTENT,process.env.CRTR_MODEL_EXACT="1",g.model=w.modelOverride,g.modelExact=!0),w.modelOverride},"persistModelChoice"),Z=e(async(o=!0,r,f=!1)=>{const v=c.session(),w=L(v.model,v.thinkingLevel),y=o?await Q(r,f):w;u.broadcast({type:"model_changed",model:H(v.model)?void 0:v.model,spec:y})},"broadcastModelChanged"),q=Qe(),me=e(o=>{q.admit(r=>{const f=c.session();return f.prompt(o,{preflightResult:r,...f.isStreaming?{streamingBehavior:"steer"}:{}}).catch(v=>{T({level:"error",event:"broker.inbox.idle_prompt_failed",error:v})})})},"startIdleInboxTurn");globalThis[Ze]=me,C=new Je({nodeId:t,cfg:g,retryProbe:B,currentSession:e(()=>c.session(),"currentSession"),currentServices:e(()=>c.services(),"currentServices"),installedGeneration:e(()=>c.installedGeneration(),"installedGeneration"),registryOf:Y,formatModelSpec:L,broadcastModelChanged:Z,turnAdmission:q}),N=new et({registry:u,faultRetry:C,installedGeneration:e(()=>c.installedGeneration(),"installedGeneration"),currentSession:e(()=>c.session(),"currentSession"),notifyTurnAccepted:e(()=>z(),"notifyTurnAccepted"),emitStartupMilestone:a,formatModelSpec:L});const ue=e(o=>{const r=c.session(),f=wt(r,R),v=ft(o.snapshotTail),w=f===void 0||v===void 0?f:f.slice(-v),y=w?.map(({message:O})=>O)??r.sessionManager.buildSessionContext().messages,G=b.summaries(),ie=w!==void 0&&v!==void 0?_t(y):void 0,ge=ie===void 0?G:Object.fromEntries(Object.entries(G).filter(([O])=>ie.has(O)));return{messages:y,...w===void 0?{}:{messageIds:w.map(({id:O})=>O)},messageVisibility:w?.map(({visibility:O})=>O)??y.map(()=>"visible"),turnVisibility:Xe(),stats:r.getSessionStats(),state:{model:H(r.model)?void 0:r.model,thinkingLevel:r.thinkingLevel,isStreaming:r.isStreaming,isCompacting:r.isCompacting,steeringMode:r.steeringMode,followUpMode:r.followUpMode,sessionFile:r.sessionFile,sessionId:r.sessionId,sessionName:r.sessionName,autoCompactionEnabled:r.autoCompactionEnabled,messageCount:r.messages.length,pendingMessageCount:r.pendingMessageCount},display:{...u.displaySnapshot()},toolGroupSummaries:ge,workingActivity:N.currentWorkingActivity(),queued:{steering:[...r.getSteeringMessages()],followUp:[...r.getFollowUpMessages()]}}},"buildSnapshot"),ee=e(o=>{const r=o.role==="controller"?D.values().next().value:void 0;u.sendFrame(o,{type:"welcome",snapshot:ue(o),role:o.role,pending_dialog:r!==void 0?r.request:null,agentDir:V()},!0)},"sendWelcome"),fe=e(o=>{const r=[...D.values()];for(let f=1;f<r.length;f++)u.sendFrame(o,r[f].request)},"replayExtraPendingDialogsTo"),te=e(()=>{u.forEachHelloed(ee)},"reWelcomeAll"),ne=e(o=>{if(!P){P=!0,b.persistPendingSummary(),N.dispose(),ht();try{A?.close()}catch{}u.dispose();try{se(x)&&ae(x)}catch{}u.clearAttachState(),process.exit(o)}},"completeExit"),j=e((o,r=0)=>{if(P)return;const f=o==="shutdown-hook"||o==="shutdown-after-settle";if(f&&b.finishOpenToolGroup(!0),f&&b.hasSummaryTasks()){if(F)return;F=!0,b.waitForSummaryTasks().finally(()=>ne(r));return}ne(r)},"disposeAndExit");$=bt({writable:e(()=>u.writableClients(),"writable"),forward:e((o,r)=>u.sendFrame(o,r),"forward"),pending:D,broadcast:e(o=>u.broadcastUi(o),"broadcast"),onKnownStreamWait:e(o=>N.knownStreamWait(o),"onKnownStreamWait")}),c.setRebindSession(),await c.enqueueRebind(_,S);const I=tt({nodeId:t,cfg:g,registry:u,toolGroups:b,projection:N,rebind:c,boundaryReviewId:R,pendingDialogs:D,sendWelcome:ee,replayExtraPendingDialogsTo:fe,reWelcomeAll:te,disposeAndExit:j,persistModelChoice:Q,broadcastModelChanged:Z,registryOf:Y,formatModelSpec:L,formatExactModelSpec:gt,turnAdmission:q,resolveLaunchModel:ce});z=I.notifyTurnAccepted,J=I.resetForSession;try{se(x)&&ae(x)}catch{}A=Se(o=>{const r=u.create(o);o.on("data",v=>{let w;try{w=r.decoder.push(v)}catch(y){y instanceof ut?(u.sendFrame(r,{type:"error",code:"frame_overflow",message:y.message}),u.dropClient(r,`frame overflow: ${y.message}`)):u.dropClient(r,`decoder error: ${String(y)}`);return}for(const y of w)try{nt(I,r,y)}catch{}});const f=e(()=>{u.removeClient(r)},"drop");o.on("close",f),o.on("error",()=>{})}),A.on("error",o=>{P||(T({level:"error",event:"broker.socket.failed",error:o}),j("socket-error",1))}),A.listen(x,async()=>{Promise.all([U(t,{op:"clear",link:"viewer\u2194broker"}),U(t,{op:"clear",link:"relay\u2194broker"})]).catch(r=>T({level:"error",event:"broker.daemon.operation.failed",node_id:t,error:r,fields:{operation:"broker_socket_bound_fault_clear"}}));let o;try{o=await C.recoverOnStartup()}catch(r){T({level:"error",event:"broker.daemon.operation.failed",node_id:t,error:r,fields:{operation:"recovery_startup"}}),j("recovery-startup-failed",1);return}if(o!=="retry-armed"&&g.firstPrompt!==void 0&&g.firstPrompt!==""){const r=at(process.env[dt]);r!==null&&lt(g.firstPrompt,r),I.kickoff(g.firstPrompt)}}),u.persistAttachState();const pe=2500;let oe=!1;const re=e(async o=>{if(P||oe)return;if(oe=!0,c.isAgentRunActive()||c.session().isStreaming||I.pendingPromptDispatches()>0){const f=Date.now()+pe;for(;I.pendingPromptDispatches()>0&&!c.session().isStreaming&&Date.now()<f;)await new Promise(v=>setTimeout(v,25));if(c.session().isStreaming){const v=f-Date.now();if(v>0){let w;try{st(),await Promise.race([c.session().abort().then(()=>!0,()=>!1),new Promise(G=>{w=setTimeout(()=>G(!1),v)})])&&await de(t,{event:"closed",end_reason:"teardown-aborted"})}finally{w!==void 0&&clearTimeout(w)}}}else(I.pendingPromptDispatches()>0||c.isAgentRunActive())&&await de(t,{event:"interrupted"})}j(o)},"abortAndExit");process.on("SIGTERM",()=>{re("SIGTERM")}),process.on("SIGINT",()=>{re("SIGINT")})}e(un,"runBroker");function _t(t){const n=new Set;for(const s of t)if(!(s.role!=="assistant"||!Array.isArray(s.content)))for(const p of s.content)p!==null&&typeof p=="object"&&p.type==="toolCall"&&typeof p.id=="string"&&n.add(p.id);return n}e(_t,"toolCallIds");function wt(t,n){const s=t.sessionManager,p=Ke(s);return p!==void 0&&ot(p.map(({message:i})=>i)),p===void 0?void 0:Ve(p,{boundaryReviewId:n,sessionEntries:s.getEntries?.()})}e(wt,"snapshotMessages");function le(){const t=we();if(t===void 0||t==="")throw new Error("broker launch is missing CRTR_NODE_ID");return t}e(le,"currentBrokerNodeId");async function ce(t,n){const s=je(n.model,he(),n.modelExact===!0);if(s===void 0)return;const p=Y(t),i={cwd:_e()??n.cwd,profileId:ye()},a=Ge(s,p,i);if(a!==void 0)throw await U(le(),{op:"record",input:{link:"crtr\u2192pi",op:"model resolution at launch",kind:"model-not-found",retry:{disposition:"fatal"},message:`model '${a.request.spec}' is not registered in the serving model registry`}}),new Error(`[broker] FATAL: model '${a.request.spec}' is not registered in the serving model registry`);const d=Be(s,p,i),l=d.selected;if(l!==void 0){const m=l.candidate;return(m.rank??0)>0&&T({level:"warn",event:"broker.model.launch_fallback",fields:{requested:n.model,selected:`${m.providerId}/${m.modelId}`,route_id:m.routeId,credential_source:m.credentialSource,rank:m.rank}}),{model:l.model,thinkingLevel:m.thinkingLevel}}if(n.modelExact===!0){const m=d.rejected.map(({candidate:h,reason:g})=>`'${h.providerId}/${h.modelId}' ${g}`).join("; ");throw await U(le(),{op:"record",input:{link:"crtr\u2192pi",op:"model resolution at launch",kind:"model-not-found",retry:{disposition:"fatal"},message:`exact-consult model '${n.model}' is unavailable \u2014 refusing to substitute (${m})`}}),new Error(`[broker] FATAL: exact-consult model '${n.model}' is unavailable`)}T({level:"warn",event:"broker.model.none_viable",fields:{rejected_candidates:d.rejected.slice(0,16).map(({candidate:m,reason:h})=>({provider:m.providerId,model:m.modelId,reason:h,route_id:m.routeId,credential_source:m.credentialSource})),rejected_candidates_omitted:Math.max(0,d.rejected.length-16)}})}e(ce,"resolveLaunchModel");function yt(t){let n=!0;return{runtime:new Proxy(t,{get(p,i,a){return n&&i==="getAvailableSnapshot"?()=>[]:n&&i==="getAvailable"?async()=>[]:n&&i==="getModel"?()=>{}:Reflect.get(p,i,a)}}),reveal:e(()=>{n=!1},"reveal")}}e(yt,"modelLessRegistry");async function St(t,n){const s=V(),p=e(async _=>{const{authPath:S,modelsPath:k}=pt(_.agentDir),E=await Re.create({credentials:new $e(S),modelsPath:k}),R=await t.createAgentSessionServices({cwd:_.cwd,agentDir:_.agentDir,modelRuntime:E,resourceLoaderOptions:{additionalExtensionPaths:n.extensionPaths,appendSystemPrompt:n.appendSystemPromptPath!==void 0?[n.appendSystemPromptPath]:void 0,noContextFiles:!0}}),B=R.resourceLoader.getExtensions();if(n.extensionPaths.some(A=>X.includes(A))){const A=new Set(B.extensions.map(c=>c.path)),$=X.filter(c=>!A.has(c));if($.length>0){const c=B.errors.filter(C=>X.includes(C.path)).map(C=>`${C.path}: ${C.error}`).join("; ");throw new Error(`[broker] FATAL: mandatory canvas extensions failed to load: ${$.join(", ")}${c===""?"":` (${c})`}`)}}const x=await ce(R,n),u=x?.model,D=x?.thinkingLevel,b=x===void 0?yt(R.modelRuntime):void 0,P=b!==void 0?{...R,modelRuntime:b.runtime}:R,F=await t.createAgentSessionFromServices({services:P,sessionManager:_.sessionManager,model:u,thinkingLevel:D,tools:n.tools,sessionStartEvent:_.sessionStartEvent});return rt(F.session),Le(F.session),b?.reveal(),{...F,services:R}},"buildForManager"),i=n.resumeSessionPath,a=n.forkFrom!==void 0&&n.forkFrom!=="";if(!a&&(i===void 0||i==="")&&n.resumeSessionId!==void 0&&n.resumeSessionId!=="")throw new Error(`[broker] resume requires a session .jsonl PATH; got only a bare id '${n.resumeSessionId}' (pi_session_file was never captured for this node)`);const d=!a&&i!==void 0&&i!=="",l=d&&n.newCycle===!0,m=d&&!l;let h;if(a)h=t.SessionManager.forkFrom(n.forkFrom,n.cwd);else if(m||l){if(h=t.SessionManager.open(i),l){const _=h.getLeafId();h.resetLeaf(),h.appendCustomEntry(qe,{cycle:Number(process.env.CRTR_CYCLES),fromLeaf:_})}}else h=t.SessionManager.create(n.cwd);if(t.createAgentSessionRuntime!==void 0){const _=e(async k=>{const E=await p({cwd:k.cwd,agentDir:k.agentDir,sessionManager:k.sessionManager,sessionStartEvent:k.sessionStartEvent});return{...E,diagnostics:E.services.diagnostics??[]}},"factory"),S=await t.createAgentSessionRuntime(_,{cwd:n.cwd,agentDir:s,sessionManager:h});return{session:S.session,services:S.services,resuming:m,runtime:S}}const g=await p({cwd:n.cwd,agentDir:s,sessionManager:h});return{session:g.session,services:g.services,resuming:m,runtime:void 0}}e(St,"buildBrokerSession");function bt(t){const n=e((i,a,d,l)=>{if(l?.signal?.aborted)return Promise.resolve(i);const m=t.writable();return m.length===0?Promise.resolve(i):new Promise(h=>{let g;const _=e(()=>{g!==void 0&&clearTimeout(g),l?.signal?.removeEventListener("abort",S),t.pending.delete(a.id)},"cleanup"),S=e(()=>{_(),t.broadcast({type:"extension_ui_dismiss",id:a.id}),h(i)},"onAbort");l?.signal?.addEventListener("abort",S,{once:!0});const k=l?.timeout!==void 0?l.timeout:vt;g=setTimeout(()=>{_(),t.broadcast({type:"extension_ui_dismiss",id:a.id}),h(i)},k),typeof g.unref=="function"&&g.unref(),t.pending.set(a.id,{request:a,resolve:e(E=>{_(),t.broadcast({type:"extension_ui_dismiss",id:a.id}),h(d(E))},"resolve")});for(const E of m)t.forward(E,a)})},"dialogPromise"),s=e(()=>{},"noop");return{[Ue]:t.onKnownStreamWait??(i=>()=>{}),get theme(){const i=globalThis[Symbol.for("@earendil-works/pi-coding-agent:theme")];if(i==null)throw new Error("Theme not initialized. Call initTheme() first.");return i},select:e((i,a,d)=>n(void 0,{type:"extension_ui_request",id:M(),method:"select",title:i,options:a,timeout:d?.timeout},l=>"cancelled"in l&&l.cancelled?void 0:"value"in l?l.value:void 0,d),"select"),confirm:e((i,a,d)=>n(!1,{type:"extension_ui_request",id:M(),method:"confirm",title:i,message:a,timeout:d?.timeout},l=>"cancelled"in l&&l.cancelled?!1:"confirmed"in l?l.confirmed:!1,d),"confirm"),input:e((i,a,d)=>n(void 0,{type:"extension_ui_request",id:M(),method:"input",title:i,placeholder:a,timeout:d?.timeout},l=>"cancelled"in l&&l.cancelled?void 0:"value"in l?l.value:void 0,d),"input"),editor:e((i,a)=>n(void 0,{type:"extension_ui_request",id:M(),method:"editor",title:i,prefill:a},d=>"cancelled"in d&&d.cancelled?void 0:"value"in d?d.value:void 0),"editor"),setStatus:e((i,a)=>t.broadcast({type:"extension_ui_request",id:M(),method:"setStatus",statusKey:i,statusText:a}),"setStatus"),setWidget:e((i,a,d)=>{typeof a!="function"&&t.broadcast({type:"extension_ui_request",id:M(),method:"setWidget",widgetKey:i,widgetLines:a,widgetPlacement:d?.placement})},"setWidget"),setTitle:e(i=>t.broadcast({type:"extension_ui_request",id:M(),method:"setTitle",title:i}),"setTitle"),notify:e((i,a)=>{const d=a==="warn"?"warning":a;t.broadcast({type:"extension_ui_request",id:M(),method:"notify",message:i,notifyType:d})},"notify"),onTerminalInput:e(()=>s,"onTerminalInput"),setWorkingMessage:s,setWorkingVisible:s,setWorkingIndicator:s,setHiddenThinkingLabel:s,setFooter:s,setHeader:s,custom:e(()=>Promise.resolve(void 0),"custom"),pasteToEditor:s,setEditorText:s,getEditorText:e(()=>"","getEditorText"),addAutocompleteProvider:s,setEditorComponent:s,getEditorComponent:e(()=>{},"getEditorComponent"),getAllThemes:e(()=>[],"getAllThemes"),getTheme:e(()=>{},"getTheme"),setTheme:s,getToolsExpanded:e(()=>!1,"getToolsExpanded"),setToolsExpanded:s}}e(bt,"makeBrokerUiContext");export{vn as REVIEW_BOUNDARY_NAVIGATION_CODE,gn as ReviewBoundaryNavigationError,St as buildBrokerSession,ht as disposeActiveSession,bt as makeBrokerUiContext,un as runBroker,wt as snapshotMessages};
1
+ var Ce=Object.defineProperty;var n=(t,i)=>Ce(t,"name",{value:i,configurable:!0});import{envModelIntent as Me,envNodeCwd as Ae,envNodeId as xe,envProfileId as Pe}from"../../shared/env.js";import{createServer as Ie}from"node:net";import{existsSync as he,readFileSync as Oe,unlinkSync as _e}from"node:fs";import{join as Se}from"node:path";import{randomUUID as C}from"node:crypto";import{mark as Ne}from"../timing.js";import{installSessionManagerStorePatch as De}from"../conversation-store/index.js";import{getAgentDir as ee,initTheme as Fe,ModelRegistry as Le,ModelRuntime as $e}from"@earendil-works/pi-coding-agent";import{nodeRunDir as Be,viewSocketPath as Ue}from"../canvas/paths.js";import{bindBrokerEventSource as Ge}from"../events/source.js";import{emitEvent as E,flushBrokerLog as je}from"../events/emit.js";import{operationIdContext as Ke}from"../events/operation-id.js";import{findMissingPackagePaths as We}from"./package-health.js";import{installBrokerConfigSnapshot as qe}from"../config.js";import{FRONT_DOOR_ENV as Ve}from"./front-door.js";import{CANVAS_EXTENSIONS as ne,piInvocationToSdkConfig as Xe}from"./launch.js";import{assertEngineVersion as He,loadBrokerEngine as Ye}from"./broker-sdk.js";import{resolveBundledPiPackageDir as ze}from"./pi-cli.js";import{captureSessionChatCapabilities as Je}from"./command-surface.js";import{InMemoryCredentialStore as Qe}from"@earendil-works/pi-ai";import{configureBrokerModelRuntime as Ze}from"./broker/model-adapter.js";import{mutateBrokerFault as H,recordBrokerTurn as ye}from"./broker/daemon-ops.js";import{modelRequestFromConfig as en,expandModelCandidates as nn,parseModelSpec as tn,unregisteredConcreteModel as on}from"../model-routes.js";import{KNOWN_STREAM_WAIT_UI as rn}from"./stream-watchdog.js";import{probeOnline as sn}from"./connectivity.js";import{CRTR_CYCLE_CUSTOM_TYPE as an,cycleAwareMessages as dn}from"./session-cycles.js";import{projectTranscript as ln}from"./session-visibility.js";import{currentTurnVisibility as cn}from"./turn-visibility.js";import{isUnknownModel as te}from"./model-selection.js";import{BrokerClientRegistry as mn}from"./broker/client-registry.js";import{ToolGroupTracker as un}from"./broker/tool-groups.js";import{onNodeNamed as fn}from"./broker/node-named.js";import{FaultRetry as pn}from"./broker/fault-retry.js";import{createTurnAdmissionGate as gn}from"./broker/turn-admission.js";import{BROKER_IDLE_TURN_START as vn,BROKER_RUN_TURN_BUSY as hn}from"./broker/held-deferred-inbox.js";import{EventProjection as _n}from"./broker/event-projection.js";import{createFrameDispatchContext as Sn,handleFrame as yn}from"./broker/frame-dispatch.js";import{hydratePersistedAdvertisedCommandMessages as wn,installAdvertisedCommandInvocationContract as bn}from"./advertised-command-invocation.js";import{RebindDriver as Rn}from"./broker/rebind.js";import{beginRuntimeTeardown as Tn}from"./broker/extension-abort.js";import{receiveNodeToken as En}from"./broker/node-token.js";import{serveCliRelay as kn}from"./broker/cli-relay.js";import{decodeKickoffOrigin as Cn,KICKOFF_ORIGIN_ENV as Mn}from"./stamp/protocol.js";import{announceMessageOrigin as An}from"./stamp/channel.js";import{brokerExtensionState as xn,brokerMemoryRefs as Pn,commitBrokerModel as In}from"./broker/daemon-ops.js";import{FrameOverflowError as On,normalizeSnapshotTail as Nn}from"./broker-protocol.js";import{ReviewBoundaryNavigationError as Ut,REVIEW_BOUNDARY_NAVIGATION_CODE as Gt}from"./broker/frame-replies.js";function oe(t){return new Le(t.modelRuntime)}n(oe,"registryOf");function L(t,i){if(t==null||te(t))return null;const s=i!==void 0&&i!==""&&i!=="off"?`:${i}`:"";return`${t.provider}/${t.id}${s}`}n(L,"formatModelSpec");function Dn(t,i){const s=L(t,void 0);return s===null?null:`${s}:${i===void 0||i===""?"off":i}`}n(Dn,"formatExactModelSpec");const Fn=12e4;let Y=null;function Ln(){const t=Y;if(Y=null,t!==null)try{t.dispose()}catch{}}n(Ln,"disposeActiveSession");async function Lt(t,i=process.hrtime.bigint(),s=new Date().toISOString()){Ge(t);const p=await En(),r=await kn(t,p);process.env.CRTR_API_SOCKET=r.path,Ke.fresh(()=>{E({level:"info",event:"broker.startup.cli_entry",ts:s,duration_ms:0,fields:{runtime_version:process.version,engine_version:null,model:null}}),E({level:"info",event:"broker.startup.module_loaded",duration_ms:Number(process.hrtime.bigint()-i)/1e6,fields:{runtime_version:process.version,engine_version:null,model:null}})});const a=new Set;let c=null;const l=n((e,o=null)=>{a.has(e)||(a.add(e),Ne(e,{duration_ms:Number(process.hrtime.bigint()-i)/1e6}),E({level:"info",event:e,duration_ms:Number(process.hrtime.bigint()-i)/1e6,fields:{runtime_version:process.version,engine_version:c,model:o}}))},"emitStartupMilestone");process.env[Ve]="1",process.env.CRTR_BROKER_PID=String(process.pid),delete process.env.TMUX_PANE,delete process.env.TMUX,De(t);const f=await Ye();He(f.VERSION),c=f.VERSION;const h=Be(t),T=Se(h,"broker-launch.json"),_=JSON.parse(Oe(T,"utf8"));if(!_.configSnapshot)throw new Error("broker launch is missing its config snapshot");qe(_.configSnapshot);const g=Xe(_);g.modelExact===!0?process.env.CRTR_MODEL_EXACT="1":delete process.env.CRTR_MODEL_EXACT;const y=await Pn(t);let b,M;const K=n(e=>{b!==void 0?b(e):M??=e},"onSignal");process.on("SIGTERM",()=>K("SIGTERM")),process.on("SIGINT",()=>K("SIGINT"));let{session:$,services:A,resuming:ie,runtime:B}=await jn(f,g);const P=(await xn(t)).node.review_binding?.review_id,w=process.env.CRTR_RUN_ID!==void 0&&process.env.CRTR_RUN_ID!=="";Y=$;const N=sn;try{process.env.PI_PACKAGE_DIR=ze(),Fe(A.settingsManager.getTheme(),!1)}catch(e){E({level:"error",event:"broker.theme.initialization_failed",error:e})}try{for(const e of We(ee()))E({level:"warn",event:"broker.startup.warning",fields:{stage:"package_health",source:e.source,resolved_path:e.resolved}})}catch{}const U=Ue(t),v=new mn(t),W=new Map,I=new un(t,e=>v.broadcast(e));fn(e=>v.broadcast({type:"node_named",...e}));let D=!1,re=!1,q,se,m,V,F,ae=n(()=>{},"notifyTurnAccepted"),de=n(()=>{},"resetFrameState");const z=gn(),J=[];let G=!1,le;const Q=n(()=>{if(G||m.isReplacing()||m.isAgentRunActive()||m.session().isStreaming)return;const e=J.shift();e&&ce(e.text,e.messageIds)},"drainPendingRunPrompt"),ce=n((e,o=[])=>{if(w&&(G||m.isReplacing()||m.isAgentRunActive()||m.session().isStreaming)){J.push({text:e,messageIds:o});return}w&&(G=!0),z.admit(d=>{const u=m.session();return w&&u.isStreaming?(J.unshift({text:e,messageIds:o}),d(),Promise.resolve()):(w&&o.length>0&&u.sessionManager.appendCustomEntry("crtr-turn-input",{message_ids:o}),u.prompt(e,{preflightResult:d,...!w&&u.isStreaming?{streamingBehavior:"steer"}:{}}))}).catch(d=>{E({level:"error",event:"broker.inbox.idle_prompt_failed",error:d})}).finally(()=>{w&&(G=!1,Q())})},"startIdleInboxTurn");globalThis[vn]=ce,m=new Rn({nodeId:t,cfg:g,session:$,services:A,runtime:B,registry:v,toolGroups:I,uiContext:n(()=>se,"uiContext"),faultRetry:n(()=>V,"faultRetry"),projection:n(()=>F,"projection"),setActiveSession:n(e=>{if(Y=e,le?.(),w){let o="stop";le=e.subscribe(d=>{if(d.type==="agent_start"&&(o="stop"),d.type==="agent_end"){const u=[...d.messages??[]].reverse().find(S=>S.role==="assistant");u&&(o=u.stopReason)}d.type==="agent_settled"&&(e.sessionManager.appendCustomEntry("crtr-turn-end",{stop_reason:o}),queueMicrotask(()=>{m.session()===e&&Q()}))})}},"setActiveSession"),disposeAndExit:n((e,o)=>j(e,o),"disposeAndExit"),onSessionRebind:n(()=>{de()},"onSessionRebind"),onReplacementIdle:n(()=>{w&&Q()},"onReplacementIdle"),reWelcomeAll:n(()=>pe(),"reWelcomeAll")});const me=n(async(e,o=!1)=>{const d=m.session(),u=L(d.model,d.thinkingLevel);if(u===null)return null;const S=await In(t,{spec:u,...e!==void 0?{intent:e}:{},userSelected:o});return o&&(g.model=S.modelOverride,e!==void 0?(process.env.CRTR_MODEL_INTENT=`${e.family}/${e.strength}`,delete process.env.CRTR_MODEL_EXACT,g.modelExact=void 0):(delete process.env.CRTR_MODEL_INTENT,process.env.CRTR_MODEL_EXACT="1",g.modelExact=!0)),S.modelOverride},"persistModelChoice"),ue=n(async(e=!0,o,d=!1)=>{const u=m.session(),S=L(u.model,u.thinkingLevel),R=e?await me(o,d):S;v.broadcast({type:"model_changed",model:te(u.model)?void 0:u.model,spec:R})},"broadcastModelChanged");V=new pn({nodeId:t,cfg:g,retryProbe:N,currentSession:n(()=>m.session(),"currentSession"),currentServices:n(()=>m.services(),"currentServices"),installedGeneration:n(()=>m.installedGeneration(),"installedGeneration"),registryOf:oe,formatModelSpec:L,broadcastModelChanged:ue,turnAdmission:z}),F=new _n({registry:v,faultRetry:V,installedGeneration:n(()=>m.installedGeneration(),"installedGeneration"),currentSession:n(()=>m.session(),"currentSession"),notifyTurnAccepted:n(()=>ae(),"notifyTurnAccepted"),emitStartupMilestone:l,formatModelSpec:L});const be=n(e=>{const o=m.session(),d=Bn(o,P),u=Nn(e.snapshotTail),S=d===void 0||u===void 0?d:d.slice(-u),R=S?.map(({message:O})=>O)??o.sessionManager.buildSessionContext().messages,X=I.summaries(),ve=S!==void 0&&u!==void 0?$n(R):void 0,ke=ve===void 0?X:Object.fromEntries(Object.entries(X).filter(([O])=>ve.has(O)));return{messages:R,...S===void 0?{}:{messageIds:S.map(({id:O})=>O)},messageVisibility:S?.map(({visibility:O})=>O)??R.map(()=>"visible"),turnVisibility:cn(),stats:o.getSessionStats(),state:{model:te(o.model)?void 0:o.model,thinkingLevel:o.thinkingLevel,isStreaming:o.isStreaming,isCompacting:o.isCompacting,steeringMode:o.steeringMode,followUpMode:o.followUpMode,sessionFile:o.sessionFile,sessionId:o.sessionId,sessionName:o.sessionName,autoCompactionEnabled:o.autoCompactionEnabled,messageCount:o.messages.length,pendingMessageCount:o.pendingMessageCount},display:{...v.displaySnapshot()},toolGroupSummaries:ke,workingActivity:F.currentWorkingActivity(),queued:{steering:[...o.getSteeringMessages()],followUp:[...o.getFollowUpMessages()]}}},"buildSnapshot"),fe=n(e=>{const o=e.role==="controller"?W.values().next().value:void 0;v.sendFrame(e,{type:"welcome",snapshot:be(e),role:e.role,pending_dialog:o!==void 0?o.request:null,agentDir:ee()},!0)},"sendWelcome"),Re=n(e=>{const o=[...W.values()];for(let d=1;d<o.length;d++)v.sendFrame(e,o[d].request)},"replayExtraPendingDialogsTo"),pe=n(()=>{v.forEachHelloed(fe)},"reWelcomeAll"),ge=n(async e=>{if(!D){D=!0,I.persistPendingSummary(),F.dispose(),Ln();try{q?.close()}catch{}r.close(),v.dispose();try{he(U)&&_e(U)}catch{}v.clearAttachState(),await je(),process.exit(e)}},"completeExit"),j=n((e,o=0)=>{if(D)return;const d=e==="shutdown-hook"||e==="shutdown-after-settle";if(d&&I.finishOpenToolGroup(!0),d&&I.hasSummaryTasks()){if(re)return;re=!0,I.waitForSummaryTasks().finally(()=>ge(o));return}ge(o)},"disposeAndExit");se=Kn({writable:n(()=>v.writableClients(),"writable"),forward:n((e,o)=>v.sendFrame(e,o),"forward"),pending:W,broadcast:n(e=>v.broadcastUi(e),"broadcast"),onKnownStreamWait:n(e=>F.knownStreamWait(e),"onKnownStreamWait")}),m.setRebindSession(),await m.enqueueRebind($,A);const k=Sn({nodeId:t,registry:v,toolGroups:I,projection:F,rebind:m,boundaryReviewId:P,pendingDialogs:W,sendWelcome:fe,replayExtraPendingDialogsTo:Re,reWelcomeAll:pe,disposeAndExit:j,persistModelChoice:me,broadcastModelChanged:ue,registryOf:oe,formatModelSpec:L,formatExactModelSpec:Dn,turnAdmission:z,memoryInventory:y});ae=k.notifyTurnAccepted,de=k.resetForSession,globalThis[hn]=()=>G||k.pendingPromptDispatches()>0||m.isAgentRunActive()||m.session().isStreaming;const Te=2500;let Z=!1;const Ee=n(async e=>{if(D||Z)return;if(Z=!0,m.isAgentRunActive()||m.session().isStreaming||k.pendingPromptDispatches()>0){const d=Date.now()+Te;for(;k.pendingPromptDispatches()>0&&!m.session().isStreaming&&Date.now()<d;)await new Promise(u=>setTimeout(u,25));if(m.session().isStreaming){const u=d-Date.now();if(u>0){let S;try{Tn(),await Promise.race([m.session().abort().then(()=>!0,()=>!1),new Promise(X=>{S=setTimeout(()=>X(!1),u)})])&&await ye(t,{event:"closed",end_reason:"teardown-aborted"})}finally{S!==void 0&&clearTimeout(S)}}}else(k.pendingPromptDispatches()>0||m.isAgentRunActive())&&await ye(t,{event:"interrupted"})}j(e)},"abortAndExit");if(b=n(e=>{Ee(e)},"signalTeardown"),M!==void 0){b(M);return}try{he(U)&&_e(U)}catch{}q=Ie(e=>{const o=v.create(e);e.on("data",u=>{let S;try{S=o.decoder.push(u)}catch(R){R instanceof On?(v.sendFrame(o,{type:"error",code:"frame_overflow",message:R.message}),v.dropClient(o,`frame overflow: ${R.message}`)):v.dropClient(o,`decoder error: ${String(R)}`);return}for(const R of S)try{yn(k,o,R)}catch{}});const d=n(()=>{v.removeClient(o)},"drop");e.on("close",d),e.on("error",()=>{})}),q.on("error",e=>{D||(E({level:"error",event:"broker.socket.failed",error:e}),j("socket-error",1))}),q.listen(U,async()=>{Promise.all([H(t,{op:"clear",link:"viewer\u2194broker"}),H(t,{op:"clear",link:"relay\u2194broker"})]).catch(o=>E({level:"error",event:"broker.daemon.operation.failed",node_id:t,error:o,fields:{operation:"broker_socket_bound_fault_clear"}}));let e;try{e=await V.recoverOnStartup()}catch(o){E({level:"error",event:"broker.daemon.operation.failed",node_id:t,error:o,fields:{operation:"recovery_startup"}}),j("recovery-startup-failed",1);return}if(!(D||Z)&&e!=="retry-armed"&&g.firstPrompt!==void 0&&g.firstPrompt!==""){const o=Cn(process.env[Mn]);o!==null&&An(g.firstPrompt,o);const d=process.env.CRTR_KICKOFF_MESSAGE_IDS;k.kickoff(g.firstPrompt,d?JSON.parse(d):[])}}),v.persistAttachState()}n(Lt,"runBroker");function $n(t){const i=new Set;for(const s of t)if(!(s.role!=="assistant"||!Array.isArray(s.content)))for(const p of s.content)p!==null&&typeof p=="object"&&p.type==="toolCall"&&typeof p.id=="string"&&i.add(p.id);return i}n($n,"toolCallIds");function Bn(t,i){const s=t.sessionManager,p=dn(s);return p!==void 0&&wn(p.map(({message:r})=>r)),p===void 0?void 0:ln(p,{boundaryReviewId:i,sessionEntries:s.getEntries?.()})}n(Bn,"snapshotMessages");function we(){const t=xe();if(t===void 0||t==="")throw new Error("broker launch is missing CRTR_NODE_ID");return t}n(we,"currentBrokerNodeId");async function Un(t,i){const s=en(i.model,Me(),i.modelExact===!0);if(s===void 0)return;const p=oe(t),r={cwd:Ae()??i.cwd,profileId:Pe()},a=on(s,p,r);if(a!==void 0)throw await H(we(),{op:"record",input:{link:"crtr\u2192pi",op:"model resolution at launch",kind:"model-not-found",retry:{disposition:"fatal"},message:`model '${a.request.spec}' is not registered in the serving model registry`}}),new Error(`[broker] FATAL: model '${a.request.spec}' is not registered in the serving model registry`);const c=nn(s,r.cwd,r.profileId),l=tn(s.spec);for(const f of c){const h=p.find(f.providerId,f.modelId);if(h===void 0)continue;const _=l?.providerId===f.providerId&&l.modelId===f.modelId?l.thinkingLevel??(f.thinkingLevel===void 0?void 0:"off"):f.thinkingLevel;return{model:h,thinkingLevel:_}}if(i.modelExact===!0){const f=c.map(h=>`'${h.providerId}/${h.modelId}' unregistered`).join("; ");throw await H(we(),{op:"record",input:{link:"crtr\u2192pi",op:"model resolution at launch",kind:"model-not-found",retry:{disposition:"fatal"},message:`exact-consult model '${i.model}' is unavailable \u2014 refusing to substitute (${f})`}}),new Error(`[broker] FATAL: exact-consult model '${i.model}' is unavailable`)}E({level:"warn",event:"broker.model.none_viable",fields:{rejected_candidates:c.map(f=>({provider:f.providerId,model:f.modelId,reason:"unregistered"})).slice(0,16)}})}n(Un,"resolveLaunchModel");function Gn(t){let i=!0;return{runtime:new Proxy(t,{get(p,r,a){return i&&r==="getAvailableSnapshot"?()=>[]:i&&r==="getAvailable"?async()=>[]:i&&r==="getModel"?()=>{}:Reflect.get(p,r,a)}}),reveal:n(()=>{i=!1},"reveal")}}n(Gn,"modelLessRegistry");async function jn(t,i){const s=ee(),p=n(async _=>{const g=await $e.create({credentials:new Qe,modelsPath:Se(_.agentDir,"models.json")});Ze(g);const y=await t.createAgentSessionServices({cwd:_.cwd,agentDir:_.agentDir,modelRuntime:g,resourceLoaderOptions:{additionalExtensionPaths:i.extensionPaths,appendSystemPrompt:i.appendSystemPromptPath!==void 0?[i.appendSystemPromptPath]:void 0,noContextFiles:!0,extensionsOverride:n(x=>({...x,extensions:x.extensions.filter(P=>!/[/\\]provider-rotation\.(?:ts|js)$/.test(P.path))}),"extensionsOverride")}}),b=y.resourceLoader.getExtensions();if(i.extensionPaths.some(x=>ne.includes(x))){const x=new Set(b.extensions.map(w=>w.path)),P=ne.filter(w=>!x.has(w));if(P.length>0){const w=b.errors.filter(N=>ne.includes(N.path)).map(N=>`${N.path}: ${N.error}`).join("; ");throw new Error(`[broker] FATAL: mandatory canvas extensions failed to load: ${P.join(", ")}${w===""?"":` (${w})`}`)}}y.settingsManager.getRetryEnabled=()=>!1;const M=await Un(y,i),K=M?.model,$=M?.thinkingLevel,A=M===void 0?Gn(y.modelRuntime):void 0,ie=A!==void 0?{...y,modelRuntime:A.runtime}:y,B=await t.createAgentSessionFromServices({services:ie,sessionManager:_.sessionManager,model:K,thinkingLevel:$,tools:i.tools,sessionStartEvent:_.sessionStartEvent});return bn(B.session),Je(B.session),A?.reveal(),{...B,services:y}},"buildForManager"),r=i.resumeSessionPath,a=i.forkFrom!==void 0&&i.forkFrom!=="";if(!a&&(r===void 0||r==="")&&i.resumeSessionId!==void 0&&i.resumeSessionId!=="")throw new Error(`[broker] resume requires a session .jsonl PATH; got only a bare id '${i.resumeSessionId}' (pi_session_file was never captured for this node)`);const c=!a&&r!==void 0&&r!=="",l=c&&i.newCycle===!0,f=c&&!l;let h;if(a)h=t.SessionManager.forkFrom(i.forkFrom,i.cwd);else if(f||l){if(h=t.SessionManager.open(r),l){const _=h.getLeafId();h.resetLeaf(),h.appendCustomEntry(an,{cycle:Number(process.env.CRTR_CYCLES),fromLeaf:_})}}else h=t.SessionManager.create(i.cwd);if(t.createAgentSessionRuntime!==void 0){const _=n(async y=>{const b=await p({cwd:y.cwd,agentDir:y.agentDir,sessionManager:y.sessionManager,sessionStartEvent:y.sessionStartEvent});return{...b,diagnostics:b.services.diagnostics??[]}},"factory"),g=await t.createAgentSessionRuntime(_,{cwd:i.cwd,agentDir:s,sessionManager:h});return{session:g.session,services:g.services,resuming:f,runtime:g}}const T=await p({cwd:i.cwd,agentDir:s,sessionManager:h});return{session:T.session,services:T.services,resuming:f,runtime:void 0}}n(jn,"buildBrokerSession");function Kn(t){const i=n((r,a,c,l)=>{if(l?.signal?.aborted)return Promise.resolve(r);const f=t.writable();return f.length===0?Promise.resolve(r):new Promise(h=>{let T;const _=n(()=>{T!==void 0&&clearTimeout(T),l?.signal?.removeEventListener("abort",g),t.pending.delete(a.id)},"cleanup"),g=n(()=>{_(),t.broadcast({type:"extension_ui_dismiss",id:a.id}),h(r)},"onAbort");l?.signal?.addEventListener("abort",g,{once:!0});const y=l?.timeout!==void 0?l.timeout:Fn;T=setTimeout(()=>{_(),t.broadcast({type:"extension_ui_dismiss",id:a.id}),h(r)},y),typeof T.unref=="function"&&T.unref(),t.pending.set(a.id,{request:a,resolve:n(b=>{_(),t.broadcast({type:"extension_ui_dismiss",id:a.id}),h(c(b))},"resolve")});for(const b of f)t.forward(b,a)})},"dialogPromise"),s=n(()=>{},"noop");return{[rn]:t.onKnownStreamWait??(r=>()=>{}),get theme(){const r=globalThis[Symbol.for("@earendil-works/pi-coding-agent:theme")];if(r==null)throw new Error("Theme not initialized. Call initTheme() first.");return r},select:n((r,a,c)=>i(void 0,{type:"extension_ui_request",id:C(),method:"select",title:r,options:a,timeout:c?.timeout},l=>"cancelled"in l&&l.cancelled?void 0:"value"in l?l.value:void 0,c),"select"),confirm:n((r,a,c)=>i(!1,{type:"extension_ui_request",id:C(),method:"confirm",title:r,message:a,timeout:c?.timeout},l=>"cancelled"in l&&l.cancelled?!1:"confirmed"in l?l.confirmed:!1,c),"confirm"),input:n((r,a,c)=>i(void 0,{type:"extension_ui_request",id:C(),method:"input",title:r,placeholder:a,timeout:c?.timeout},l=>"cancelled"in l&&l.cancelled?void 0:"value"in l?l.value:void 0,c),"input"),editor:n((r,a)=>i(void 0,{type:"extension_ui_request",id:C(),method:"editor",title:r,prefill:a},c=>"cancelled"in c&&c.cancelled?void 0:"value"in c?c.value:void 0),"editor"),setStatus:n((r,a)=>t.broadcast({type:"extension_ui_request",id:C(),method:"setStatus",statusKey:r,statusText:a}),"setStatus"),setWidget:n((r,a,c)=>{typeof a!="function"&&t.broadcast({type:"extension_ui_request",id:C(),method:"setWidget",widgetKey:r,widgetLines:a,widgetPlacement:c?.placement})},"setWidget"),setTitle:n(r=>t.broadcast({type:"extension_ui_request",id:C(),method:"setTitle",title:r}),"setTitle"),notify:n((r,a)=>{const c=a==="warn"?"warning":a;t.broadcast({type:"extension_ui_request",id:C(),method:"notify",message:r,notifyType:c})},"notify"),onTerminalInput:n(()=>s,"onTerminalInput"),setWorkingMessage:s,setWorkingVisible:s,setWorkingIndicator:s,setHiddenThinkingLabel:s,setFooter:s,setHeader:s,custom:n(()=>Promise.resolve(void 0),"custom"),pasteToEditor:s,setEditorText:s,getEditorText:n(()=>"","getEditorText"),addAutocompleteProvider:s,setEditorComponent:s,getEditorComponent:n(()=>{},"getEditorComponent"),getAllThemes:n(()=>[],"getAllThemes"),getTheme:n(()=>{},"getTheme"),setTheme:s,getToolsExpanded:n(()=>!1,"getToolsExpanded"),setToolsExpanded:s}}n(Kn,"makeBrokerUiContext");export{Gt as REVIEW_BOUNDARY_NAVIGATION_CODE,Ut as ReviewBoundaryNavigationError,jn as buildBrokerSession,Ln as disposeActiveSession,Kn as makeBrokerUiContext,Lt as runBroker,Bn as snapshotMessages};
@@ -12,6 +12,7 @@ export declare const CANVAS_BASH_VALVE_PATH: string;
12
12
  export declare const CANVAS_PREVIEW_RESULT_PATH: string;
13
13
  export declare const CANVAS_PROMPT_SCRUB_PATH: string;
14
14
  export declare const CANVAS_STAMP_PATH: string;
15
+ export declare const SYSTEM_PROMPT_ENTRY_PATH: string;
15
16
  /** The canvas extensions every node loads, in order. The inbox watcher commits
16
17
  * its cursor at agent_settled before the stophook checks it for idle release.
17
18
  * The review boundary must run before the stophook commits companion session
@@ -1 +1 @@
1
- var _=Object.defineProperty;var A=(e,s)=>_(e,"name",{value:s,configurable:!0});import{existsSync as x}from"node:fs";import{basename as T,dirname as S,extname as v,join as p}from"node:path";import{fileURLToPath as C}from"node:url";import{customExtensionPaths as m,isShippedCanvasExtension as P}from"../canvas/extensions.js";function t(e){const s=S(C(import.meta.url)),a=[p(s,"..","..","pi-extensions",`${e}.js`),p(s,"..","..","pi-extensions",`${e}.ts`)];return a.find(r=>x(r))??a[0]}A(t,"resolveExtension");const E=t("canvas-stophook"),f=t("canvas-inbox-watcher"),u=t("canvas-recap"),N=t("canvas-goal-capture"),V=t("canvas-passive-context"),d=t("canvas-review-boundary"),h=t("canvas-context-intro"),H=t("canvas-tool-guide"),l=t("canvas-doc-substrate"),O=t("canvas-structured-output"),R=t("canvas-bash-valve"),w=t("canvas-preview-result"),U=t("canvas-prompt-scrub"),g=t("canvas-stamp"),i=[f,d,E,u,N,V,h,H,l,O,R,w,U,g];function $(e){const s=i,a=new Set(s),r=[],n=new Set,c=Array.isArray(e)&&e.every(o=>typeof o=="string")?m(e):[];for(const o of c)a.has(o)||n.has(o)||(n.add(o),r.push(o));return[...s,...r]}A($,"mergeCanvasExtensions");function D(e){const s=new Set(i),a=new Map,r=new Set;for(const n of e){if(P(n)){const c=T(n.replaceAll("\\","/")),o=c.slice(0,c.length-v(c).length);if(r.has(o))throw new Error(`duplicate mandatory canvas extension basename ${o}`);r.add(o)}s.has(n)&&a.set(n,(a.get(n)??0)+1)}for(const n of i)if(a.get(n)!==1)throw new Error(`missing mandatory canvas extension ${n} (found ${a.get(n)??0} times)`)}A(D,"assertMandatoryCanvasExtensions");export{R as CANVAS_BASH_VALVE_PATH,h as CANVAS_CONTEXT_INTRO_PATH,l as CANVAS_DOC_SUBSTRATE_PATH,i as CANVAS_EXTENSIONS,N as CANVAS_GOAL_CAPTURE_PATH,f as CANVAS_INBOX_WATCHER_PATH,V as CANVAS_PASSIVE_CONTEXT_PATH,w as CANVAS_PREVIEW_RESULT_PATH,U as CANVAS_PROMPT_SCRUB_PATH,u as CANVAS_RECAP_PATH,d as CANVAS_REVIEW_BOUNDARY_PATH,g as CANVAS_STAMP_PATH,E as CANVAS_STOPHOOK_PATH,O as CANVAS_STRUCTURED_OUTPUT_PATH,H as CANVAS_TOOL_GUIDE_PATH,D as assertMandatoryCanvasExtensions,$ as mergeCanvasExtensions};
1
+ var _=Object.defineProperty;var A=(e,s)=>_(e,"name",{value:s,configurable:!0});import{existsSync as T}from"node:fs";import{basename as x,dirname as S,extname as P,join as p}from"node:path";import{fileURLToPath as m}from"node:url";import{customExtensionPaths as v,isShippedCanvasExtension as C}from"../canvas/extensions.js";function t(e){const s=S(m(import.meta.url)),a=[p(s,"..","..","pi-extensions",`${e}.js`),p(s,"..","..","pi-extensions",`${e}.ts`)];return a.find(r=>T(r))??a[0]}A(t,"resolveExtension");const E=t("canvas-stophook"),f=t("canvas-inbox-watcher"),u=t("canvas-recap"),N=t("canvas-goal-capture"),V=t("canvas-passive-context"),d=t("canvas-review-boundary"),h=t("canvas-context-intro"),H=t("canvas-tool-guide"),l=t("canvas-doc-substrate"),O=t("canvas-structured-output"),R=t("canvas-bash-valve"),w=t("canvas-preview-result"),y=t("canvas-prompt-scrub"),U=t("canvas-stamp"),g=t("system-prompt-entry"),i=[f,d,E,u,N,V,h,H,l,O,R,w,y,U,g];function $(e){const s=i,a=new Set(s),r=[],n=new Set,c=Array.isArray(e)&&e.every(o=>typeof o=="string")?v(e):[];for(const o of c)a.has(o)||n.has(o)||(n.add(o),r.push(o));return[...s,...r]}A($,"mergeCanvasExtensions");function D(e){const s=new Set(i),a=new Map,r=new Set;for(const n of e){if(C(n)){const c=x(n.replaceAll("\\","/")),o=c.slice(0,c.length-P(c).length);if(r.has(o))throw new Error(`duplicate mandatory canvas extension basename ${o}`);r.add(o)}s.has(n)&&a.set(n,(a.get(n)??0)+1)}for(const n of i)if(a.get(n)!==1)throw new Error(`missing mandatory canvas extension ${n} (found ${a.get(n)??0} times)`)}A(D,"assertMandatoryCanvasExtensions");export{R as CANVAS_BASH_VALVE_PATH,h as CANVAS_CONTEXT_INTRO_PATH,l as CANVAS_DOC_SUBSTRATE_PATH,i as CANVAS_EXTENSIONS,N as CANVAS_GOAL_CAPTURE_PATH,f as CANVAS_INBOX_WATCHER_PATH,V as CANVAS_PASSIVE_CONTEXT_PATH,w as CANVAS_PREVIEW_RESULT_PATH,y as CANVAS_PROMPT_SCRUB_PATH,u as CANVAS_RECAP_PATH,d as CANVAS_REVIEW_BOUNDARY_PATH,U as CANVAS_STAMP_PATH,E as CANVAS_STOPHOOK_PATH,O as CANVAS_STRUCTURED_OUTPUT_PATH,H as CANVAS_TOOL_GUIDE_PATH,g as SYSTEM_PROMPT_ENTRY_PATH,D as assertMandatoryCanvasExtensions,$ as mergeCanvasExtensions};
@@ -13,6 +13,11 @@ export interface CloseNodeResult {
13
13
  * subscribes to them. */
14
14
  spared: string[];
15
15
  }
16
+ /** The set of nodes to close: the root plus every descendant reachable down the
17
+ * subscriptions spine, all of whose managers are themselves in the set. Grown
18
+ * to a fixpoint — a node added this pass can qualify its own children next
19
+ * pass. Cycle-safe via the membership skip. */
20
+ export declare function closingSet(root: string): Set<string>;
16
21
  /** Close `rootId` and its exclusive subtree. Best-effort throughout: a tmux/db
17
22
  * failure on one node never aborts the cascade. Throws only on an unknown root
18
23
  * so the command can surface a clean not-found error.
@@ -27,6 +32,10 @@ export interface CloseNodeResult {
27
32
  export declare function closeNode(rootId: string, opts?: {
28
33
  rootEvent?: 'cancel' | 'finish';
29
34
  callerPid?: number;
35
+ /** App runs retain their root and child rows even when no assistant output exists. */
36
+ preserveEmpty?: boolean;
30
37
  /** Daemon-owned close work that must drain before this daemon exits. */
31
38
  registerDetached?: (work: Promise<void>) => void;
39
+ /** Reason recorded when an active turn or background job is stopped. */
40
+ stopReason?: string;
32
41
  }): CloseNodeResult;
@@ -1 +1 @@
1
- var b=Object.defineProperty;var a=(n,o)=>b(n,"name",{value:o,configurable:!0});import{getNode as u,subscriptionsOf as f,subscribersOf as w}from"../canvas/index.js";import{transition as _}from"./lifecycle.js";import{requestBrokerTeardown as D}from"./host.js";import{tearDownNode as $,reapIfEmpty as E}from"./placement.js";import{crtrHome as N,contextDir as x,jobDir as L,nodeDir as O,reportsDir as H}from"../canvas/paths.js";import{discoverLifecycleHookRegistry as S}from"../command-hooks/discovery.js";import{invokeLifecycleHooks as j}from"../command-hooks/transport/exec-lifecycle.js";import{emitEvent as h}from"../events/emit.js";import{enqueueNodeMail as g}from"../feed/messages.js";function q(n,o,t,s,l="normal"){for(const r of o)try{g(r.node_id,{senderNodeId:n,kind:"message",label:t,bodyJson:s,urgency:l,wake:r.active?1:0})}catch{}}a(q,"fanDoctrineWake");function T(n){const o=new Set([n]);let t=!0;for(;t;){t=!1;for(const s of[...o])for(const l of f(s)){const r=l.node_id;o.has(r)||w(r).every(d=>o.has(d.node_id))&&(o.add(r),t=!0)}}return o}a(T,"closingSet");function Y(n,o){const t=[],s=new Set([n]),l=[n];for(;l.length>0;){const r=l.shift();t.push(r);for(const d of f(r))o.has(d.node_id)&&!s.has(d.node_id)&&(s.add(d.node_id),l.push(d.node_id))}for(const r of o)s.has(r)||t.push(r);return t.reverse()}a(Y,"killOrder");function B(n,o){const t=n?"You were CLOSED by the user from the canvas":"You were CANCELED \u2014 an ancestor of yours was closed from the canvas";if(o.length===0)return`${t}. Your pi session is preserved; this resume reopened it.`;const s=o.slice(0,4).map(r=>{const d=u(r);return d!==null?`${d.name} (${r})`:r}),l=o.length>s.length?` +${o.length-s.length} more`:"";return`${t}. ${o.length} child node(s) you subscribe to were canceled with you and are no longer running: ${s.join(", ")}${l}. Resuming will NOT restore them \u2014 re-spawn if you still need that work.`}a(B,"cancellationLabel");function K(n,o={}){if(u(n)===null)throw new Error(`closeNode: unknown node ${n}`);const t=o.rootEvent??"cancel",s=T(n),l=Y(n,s),r=[];for(const e of s)for(const i of f(e))!s.has(i.node_id)&&!r.includes(i.node_id)&&r.push(i.node_id);const d=[];for(const e of l)try{const i=u(e);if(i===null)continue;const m=f(e).map(c=>c.node_id).filter(c=>s.has(c)),v=w(e).filter(c=>!s.has(c.node_id));let p;try{const c=S(i.cwd,i.profile_id).plans.get("node:close")??[];if(c.length>0){const k={node:{id:e,name:i.name,kind:i.kind,mode:i.mode,lifecycle:i.lifecycle,cwd:i.cwd,nodeDir:O(e),contextDir:x(e),jobDir:L(e),reportsDir:H(e)},runtime:{isBirth:!1,canvasHome:N(),profile:i.profile_id??null}};p=a(()=>j(c,k),"afterTeardown")}}catch(c){h({level:"error",event:"node.close_hook.discovery_failed",node_id:e,error:c})}const y=D(e,e===n?{excludePid:o.callerPid}:{},p);try{o.registerDetached?.(y.then(()=>{}))}catch(c){h({level:"error",event:"node.close_hook.detached_registration_failed",node_id:e,error:c})}if(!E(e,void 0,!1)){const c=i.final_report!==null&&i.final_report!==void 0;e===n&&t==="finish"||c?(i.status==="active"||i.status==="idle")&&_(e,"finish"):_(e,"cancel",{reason:"closed"}),$(e),g(e,{kind:"message",label:B(e===n,m),bodyJson:{reason:"user-close",cascade_root:n,canceled_children:m},urgency:"normal",wake:1})}q(e,v,`Child closed \u2014 ${i.name} (${e}) was closed from the canvas and is no longer running.`,{reason:"child-closed",child:e}),d.push(e)}catch(i){h({level:"error",event:"node.close.failed",node_id:e,error:i})}return{root:n,closed:d,spared:r}}a(K,"closeNode");export{K as closeNode,q as fanDoctrineWake};
1
+ var k=Object.defineProperty;var a=(r,o)=>k(r,"name",{value:o,configurable:!0});import{getNode as h,subscriptionsOf as f,subscribersOf as _}from"../canvas/index.js";import{transition as g}from"./lifecycle.js";import{stopNodeSandboxes as D}from"../spaces/stop.js";import{tearDownNode as $,reapIfEmpty as E}from"./placement.js";import{crtrHome as N,jobDir as x}from"../canvas/paths.js";import{contextDir as L,nodeAgentDir as S,reportsDir as O}from"../canvas/node-agent-paths.js";import{readLiveSession as H}from"../canvas/sessions.js";import{discoverLifecycleHookRegistry as j}from"../command-hooks/discovery.js";import{invokeLifecycleHooks as R}from"../command-hooks/transport/exec-lifecycle.js";import{emitEvent as m}from"../events/emit.js";import{enqueueNodeMail as v}from"../feed/messages.js";function Y(r,o,t,s,l="normal"){for(const i of o)try{v(i.node_id,{senderNodeId:r,kind:"message",label:t,bodyJson:s,urgency:l,wake:i.active?1:0})}catch{}}a(Y,"fanDoctrineWake");function q(r){const o=new Set([r]);let t=!0;for(;t;){t=!1;for(const s of[...o])for(const l of f(s)){const i=l.node_id;o.has(i)||_(i).every(d=>o.has(d.node_id))&&(o.add(i),t=!0)}}return o}a(q,"closingSet");function A(r,o){const t=[],s=new Set([r]),l=[r];for(;l.length>0;){const i=l.shift();t.push(i);for(const d of f(i))o.has(d.node_id)&&!s.has(d.node_id)&&(s.add(d.node_id),l.push(d.node_id))}for(const i of o)s.has(i)||t.push(i);return t.reverse()}a(A,"killOrder");function J(r,o){const t=r?"You were CLOSED by the user from the canvas":"You were CANCELED \u2014 an ancestor of yours was closed from the canvas";if(o.length===0)return`${t}. Your pi session is preserved; this resume reopened it.`;const s=o.slice(0,4).map(i=>{const d=h(i);return d!==null?`${d.name} (${i})`:i}),l=o.length>s.length?` +${o.length-s.length} more`:"";return`${t}. ${o.length} child node(s) you subscribe to were canceled with you and are no longer running: ${s.join(", ")}${l}. Resuming will NOT restore them \u2014 re-spawn if you still need that work.`}a(J,"cancellationLabel");function V(r,o={}){if(h(r)===null)throw new Error(`closeNode: unknown node ${r}`);const t=o.rootEvent??"cancel",s=q(r),l=A(r,s),i=[];for(const e of s)for(const n of f(e))!s.has(n.node_id)&&!i.includes(n.node_id)&&i.push(n.node_id);const d=[];for(const e of l)try{const n=h(e);if(n===null)continue;const p=f(e).map(c=>c.node_id).filter(c=>s.has(c)),w=_(e).filter(c=>!s.has(c.node_id));let u;try{const c=j(n.cwd,n.profile_id).plans.get("node:close")??[];if(c.length>0){const b={node:{id:e,name:n.name,kind:n.kind,mode:n.mode,lifecycle:n.lifecycle,cwd:n.cwd,nodeDir:S(e),contextDir:L(e),jobDir:x(e),reportsDir:O(e)},runtime:{isBirth:!1,canvasHome:N(),profile:n.profile_id??null}};u=a(()=>R(c,b),"afterTeardown")}}catch(c){m({level:"error",event:"node.close_hook.discovery_failed",node_id:e,error:c})}const y=D(e,o.stopReason??"node_closed",{...e===r?{excludePid:o.callerPid}:{},...u?{after:u}:{}});try{o.registerDetached?.(y.then(()=>{}))}catch(c){m({level:"error",event:"node.close_hook.detached_registration_failed",node_id:e,error:c})}if(o.preserveEmpty||n.run_id!==null&&n.pi_pid!==null&&H(e)?.sessionId!=null||!E(e,void 0,!1)){const c=n.final_report!==null&&n.final_report!==void 0;e===r&&t==="finish"||c?(n.status==="active"||n.status==="idle")&&g(e,"finish"):g(e,"cancel",{reason:"closed"}),$(e),v(e,{kind:"message",label:J(e===r,p),bodyJson:{reason:"user-close",cascade_root:r,canceled_children:p},urgency:"normal",wake:1})}Y(e,w,`Child closed \u2014 ${n.name} (${e}) was closed from the canvas and is no longer running.`,{reason:"child-closed",child:e}),d.push(e)}catch(n){m({level:"error",event:"node.close.failed",node_id:e,error:n})}return{root:r,closed:d,spared:i}}a(V,"closeNode");export{V as closeNode,q as closingSet,Y as fanDoctrineWake};
@@ -1 +1 @@
1
- var n=Object.defineProperty;var o=(e,t)=>n(e,"name",{value:t,configurable:!0});import{getNode as s}from"../canvas/index.js";import{oneShotControllerRequest as u}from"./broker-request.js";import{isBrokerLive as a}from"./model-swap.js";import{buildContextBearings as c,CONTEXT_INTRO_CUSTOM_TYPE as m}from"./bearings.js";import{renderPreferencesForNodeSubject as l}from"./broker-extension-render.js";import{assembleNodeSubject as f}from"../substrate/subject.js";import{exposureTarget as i,freezePreferenceSnapshot as p,loadContextExposureState as v,saveContextExposureState as d}from"../substrate/injected-store.js";import{formatCard as x}from"../../shared/generated-context.js";async function T(e,t){const r=s(e);if(r===null)throw new Error(`deliverCustomMessageLive: unknown node ${e}`);a(r)&&await u({nodeId:e,what:`the ${t.customType} delivery`,ackFor:"deliver_custom_message",frame:o(()=>({type:"deliver_custom_message",customType:t.customType,content:t.content,...t.deliverAs!==void 0?{deliverAs:t.deliverAs}:{},...t.details!==void 0?{details:t.details}:{}}),"frame"),result:o(()=>{},"result")})}o(T,"deliverCustomMessageLive");async function N(e){const t=v(e);await T(e,{customType:m,content:x("bearings",{},c(e,i(t,"transcript"))),details:{nodeId:e}});const r=f(e);if(r===null)throw new Error(`deliverBearingsLive: no document subject for ${e}`);p(t,l(e,r,i(t,"system"))),d(e,t)}o(N,"deliverBearingsLive");export{N as deliverBearingsLive,T as deliverCustomMessageLive};
1
+ var l=Object.defineProperty;var o=(e,r)=>l(e,"name",{value:r,configurable:!0});import{insertMemoryReads as u}from"../canvas/memory-reads.js";import{memoryEvents as f}from"../substrate/memory-events.js";import{getNode as n}from"../canvas/index.js";import{appForNode as m}from"../canvas/node-agent-paths.js";import{oneShotControllerRequest as p}from"./broker-request.js";import{isBrokerLive as v}from"./model-swap.js";import{buildContextBearings as y,CONTEXT_INTRO_CUSTOM_TYPE as T}from"./bearings.js";import{renderPreferencesForNodeSubject as x}from"./broker-extension-render.js";import{assembleNodeSubject as d}from"../substrate/subject.js";import{exposureTarget as a,freezePreferenceSnapshot as w,loadContextExposureState as C,saveContextExposureState as g}from"../substrate/injected-store.js";import{formatCard as E}from"../../shared/generated-context.js";import{automaticMemoryTarget as S}from"../spaces/permissions.js";async function b(e,r){const t=n(e);if(t===null)throw new Error(`deliverCustomMessageLive: unknown node ${e}`);v(t)&&await p({nodeId:e,what:`the ${r.customType} delivery`,ackFor:"deliver_custom_message",frame:o(()=>({type:"deliver_custom_message",customType:r.customType,content:r.content,...r.deliverAs!==void 0?{deliverAs:r.deliverAs}:{},...r.details!==void 0?{details:r.details}:{}}),"frame"),result:o(()=>{},"result")})}o(b,"deliverCustomMessageLive");async function R(e){const r=C(e),t=[];await b(e,{customType:T,content:E("bearings",{},y(e,a(r,"transcript",t))),details:{nodeId:e}});const i=d(e),s=n(e);if(i===null||s===null)throw new Error(`deliverBearingsLive: no document subject for ${e}`);w(r,x(e,i,a(r,"system",t),m(e),S({...s,grantee:m(e)}))),g(e,r);try{u(e,f(t,"loaded"))}catch(c){console.warn(`memory-read log insert failed for ${e}: ${String(c)}`)}}o(R,"deliverBearingsLive");export{R as deliverBearingsLive,b as deliverCustomMessageLive};
@@ -71,7 +71,7 @@ export interface FleetRegistry {
71
71
  * Removes the entry (freeing the capacity slot), then enqueues its
72
72
  * observation on the daemon's serial work lane — it never runs inline on
73
73
  * the Node event callback (design D-3). */
74
- onChildExit(nodeId: string, status: FleetExitStatus): void;
74
+ onChildExit(nodeId: string, status: FleetExitStatus, executionId?: string): void;
75
75
  /** Test seam — delivers a synthetic exit through the SAME path as
76
76
  * onChildExit, so fabricated-row tests drive policy without a process. */
77
77
  deliverExit(nodeId: string, status: FleetExitStatus): void;
@@ -1 +1 @@
1
- var m=Object.defineProperty;var r=(a,t)=>m(a,"name",{value:t,configurable:!0});import{CredentialSynchronizationError as d,LoginDialogComponent as l,OAuthSelectorComponent as p}from"@earendil-works/pi-coding-agent";import{execFile as f}from"node:child_process";import{join as g}from"node:path";import{setAuthCredential as w}from"../auth-file.js";import{dialogAuthInteraction as y}from"../auth-interaction.js";import{commitManagedLogin as I,isManagedProvider as L,readSubscriptionPool as b}from"../subscription-state.js";import{runSetupSettingsProcess as A}from"../../commands/sys/setup-settings-runner.js";import{buildProviderCatalog as P}from"../../commands/sys/panels/provider-panel.js";function x(a){const t=process.platform==="darwin"?"open":process.platform==="win32"?"cmd":"xdg-open",i=process.platform==="win32"?["/c","start","",a]:[a];f(t,i,{timeout:5e3},()=>{})}r(x,"openBrowser");class C{static{r(this,"FrontDoorLogin")}tui;runtime;agentDir;finish;component;dialog;settled=!1;constructor(t,i,s,o,c){this.tui=t,this.runtime=i,this.agentDir=s,this.finish=c,this.component=new p("login",o,n=>this.startLogin(o.find(u=>u.id===n)),()=>this.complete(!1))}get focused(){return this.component.focused}set focused(t){this.component.focused=t}handleInput(t){this.component.handleInput?.(t)}invalidate(){this.tui.requestRender()}render(t){return this.component.render(t)}dispose(){this.settled||this.dialog?.handleInput("\x1B")}complete(t){this.settled||(this.settled=!0,this.finish(t))}startLogin(t){if(!t){this.complete(!1);return}const i=new l(this.tui,t.id,e=>this.complete(e),t.name);this.dialog=i,this.component=i,this.tui.setFocus(this),this.tui.requestRender();const s=y(i,{openBrowser:x,onChange:r(()=>this.tui.requestRender(),"onChange"),isActive:r(()=>!this.settled&&!i.signal.aborted,"isActive")}),o=r(()=>{i.signal.aborted||this.complete(!1)},"fail");if(t.authType==="api_key"){i.showPrompt(`Enter API key for ${t.name}:`,"sk-...").then(async e=>{if(!e.trim()||this.settled){this.complete(!1);return}await w(t.id,{type:"api_key",key:e.trim()},g(this.agentDir,"auth.json")),this.complete(!0)}).catch(o);return}const c=this.runtime.getProvider(t.id)?.auth.oauth;if(!c){this.complete(!1);return}const n=t.id;if(!L(n)){this.runtime.login(n,"oauth",s).then(()=>this.complete(!0)).catch(e=>{if(e instanceof d){this.complete(!0);return}o()});return}const u=Math.max(0,...b(n).map(e=>e.lastRateLimitedAt));c.login(s).then(async e=>{if(this.settled||i.signal.aborted)return;const h=typeof e.accountId=="string"&&e.accountId.trim()?e.accountId.trim():void 0;await I(n,void 0,{access:e.access,refresh:e.refresh,expires:e.expires,...h?{accountId:h}:{},lastRateLimitedAt:u,autoLabel:!0}),this.complete(!0)}).catch(o)}}async function E(){return await A(({tui:t,agentDir:i,runtime:s,registry:o},c)=>new C(t,s,i,P(s,o).map(({providerId:n,name:u,authType:e})=>({id:n,name:u,authType:e})),c.submit))===!0}r(E,"runFrontDoorLogin");export{E as runFrontDoorLogin};
1
+ var h=Object.defineProperty;var r=(a,t)=>h(a,"name",{value:t,configurable:!0});import{CredentialSynchronizationError as u,LoginDialogComponent as l,OAuthSelectorComponent as d}from"@earendil-works/pi-coding-agent";import{execFile as p}from"node:child_process";import{join as f}from"node:path";import{setAuthCredential as g}from"../auth-file.js";import{secretsDir as w}from"../layout.js";import{dialogAuthInteraction as y}from"../auth-interaction.js";import{isManagedProvider as C}from"../subscription-state.js";import{daemonManagedLogin as b}from"../model-auth/daemon-login.js";import{cliClient as D}from"../../commands/api-client.js";import{runSetupSettingsProcess as I}from"../../commands/sys/setup-settings-runner.js";import{buildProviderCatalog as L}from"../../commands/sys/panels/provider-panel.js";function P(a){const t=process.platform==="darwin"?"open":process.platform==="win32"?"cmd":"xdg-open",e=process.platform==="win32"?["/c","start","",a]:[a];p(t,e,{timeout:5e3},()=>{})}r(P,"openBrowser");class A{static{r(this,"FrontDoorLogin")}tui;runtime;agentDir;finish;component;dialog;settled=!1;constructor(t,e,s,o,n){this.tui=t,this.runtime=e,this.agentDir=s,this.finish=n,this.component=new d("login",o,i=>this.startLogin(o.find(m=>m.id===i)),()=>this.complete(!1))}get focused(){return this.component.focused}set focused(t){this.component.focused=t}handleInput(t){this.component.handleInput?.(t)}invalidate(){this.tui.requestRender()}render(t){return this.component.render(t)}dispose(){this.settled||this.dialog?.handleInput("\x1B")}complete(t){this.settled||(this.settled=!0,this.finish(t))}startLogin(t){if(!t){this.complete(!1);return}const e=new l(this.tui,t.id,i=>this.complete(i),t.name);this.dialog=e,this.component=e,this.tui.setFocus(this),this.tui.requestRender();const s=y(e,{openBrowser:P,onChange:r(()=>this.tui.requestRender(),"onChange"),isActive:r(()=>!this.settled&&!e.signal.aborted,"isActive")}),o=r(()=>{e.signal.aborted||this.complete(!1)},"fail");if(t.authType==="api_key"){e.showPrompt(`Enter API key for ${t.name}:`,"sk-...").then(async i=>{if(!i.trim()||this.settled){this.complete(!1);return}await g(t.id,{type:"api_key",key:i.trim()},f(w(),"auth.json")),this.complete(!0)}).catch(o);return}const n=t.id;if(C(n)){b(D(),n,s).then(()=>{this.settled||e.signal.aborted||this.complete(!0)}).catch(o);return}if(!this.runtime.getProvider(n)?.auth.oauth){this.complete(!1);return}this.runtime.login(n,"oauth",s).then(()=>this.complete(!0)).catch(i=>{if(i instanceof u){this.complete(!0);return}o()})}}async function B(){return await I(({tui:t,agentDir:e,runtime:s,registry:o},n)=>new A(t,s,e,L(s,o).map(({providerId:i,name:m,authType:c})=>({id:i,name:m,authType:c})),n.submit))===!0}r(B,"runFrontDoorLogin");export{B as runFrontDoorLogin};
@@ -1,4 +1,4 @@
1
- var v=Object.defineProperty;var p=(r,i)=>v(r,"name",{value:i,configurable:!0});import{existsSync as w,statSync as I}from"node:fs";import{homedir as _}from"node:os";import{join as N,resolve as d}from"node:path";import{SUBTREE_NAMES as A}from"../../build-root.js";import{FRONT_DOOR_ENV as C}from"./front-door-env.js";import{frontDoorBootPrompt as L}from"./first-run-offer.js";function h(r){try{return w(r)&&I(r).isDirectory()}catch{return!1}}p(h,"isDir");const W=new Set(["--name","--kind","--profile","--pick-profile","--continue","-c","--resume","-r"]),g=N(_(),".crouter","setup-completed.json");async function b(){let r=!1;const i=p(()=>{r=!0},"onSigint");process.once("SIGINT",i);try{const{runSetup:t}=await import("../../commands/sys/setup-wizard.js"),e=await t();if(r){const l=new Error("Interrupted");throw l.name="AbortError",l}const[{atomicWriteJson:a},{crtrVersion:c}]=await Promise.all([import("../fs-utils.js"),import("../../shared/crtr-version.js")]);a(g,{packageVersion:c(),completedAt:new Date().toISOString(),outcome:e})}finally{process.removeListener("SIGINT",i)}}p(b,"runFirstSetup");function x(r){let i=process.cwd(),t,e,a,c=!1,l;const f=[];for(let n=0;n<r.length;n++){const o=r[n];o==="--name"?t=r[++n]:o==="--kind"?e=r[++n]:o==="--profile"?a=r[++n]:o==="--pick-profile"?c=!0:o==="--continue"||o==="-c"?l="continue":o==="--resume"||o==="-r"?l="pick":o.startsWith("--")||f.push(o)}f.length>0&&h(d(f[0]))&&(i=d(f.shift()));const m=f.length>0?f.join(" "):void 0;return{cwd:i,prompt:m,name:t,kind:e,profile:a,pickProfile:c,resume:l}}p(x,"parseRootArgs");import{FRONT_DOOR_ENV as z}from"./front-door-env.js";async function $(r){const i=r.slice(2),t=i[0];if(process.env[C]||t==="-h"||t==="--help"||t==="--version"||t==="-v"||t!==void 0&&A.includes(t))return!1;if(t!==void 0){const s=/\s/.test(t),u=!t.startsWith("-")&&h(d(t)),y=W.has(t);if(!s&&!u&&!y)return!1;if(u){const{buildRoot:E}=await import("../../build-root.js");if((await E()).subtrees.some(F=>F.name===t))return!1}}const e=x(i);if(e.profile!==void 0){const{resolveProfileOperand:s}=await import("../profiles/manifest.js");e.profile=s(e.profile).profileId}const a=process.stdin.isTTY&&process.stdout.isTTY;let c=!1;a&&!w(g)&&(await b(),c=!0);const{selectProfileForCwd:l,selectProfileForCwdReadOnly:f}=await import("../profiles/select.js");c&&e.profile===void 0&&process.stdout.write(`
1
+ var v=Object.defineProperty;var p=(r,i)=>v(r,"name",{value:i,configurable:!0});import{existsSync as w,statSync as I}from"node:fs";import{join as _,resolve as d}from"node:path";import{SUBTREE_NAMES as N}from"../../build-root.js";import{FRONT_DOOR_ENV as A}from"./front-door-env.js";import{frontDoorBootPrompt as C}from"./first-run-offer.js";import{runtimeRoot as L}from"../layout.js";function g(r){try{return w(r)&&I(r).isDirectory()}catch{return!1}}p(g,"isDir");const W=new Set(["--name","--kind","--profile","--pick-profile","--continue","-c","--resume","-r"]),h=_(L(),"setup-completed.json");async function b(){let r=!1;const i=p(()=>{r=!0},"onSigint");process.once("SIGINT",i);try{const{runSetup:t}=await import("../../commands/sys/setup-wizard.js"),e=await t();if(r){const l=new Error("Interrupted");throw l.name="AbortError",l}const[{atomicWriteJson:a},{crtrVersion:c}]=await Promise.all([import("../fs-utils.js"),import("../../shared/crtr-version.js")]);a(h,{packageVersion:c(),completedAt:new Date().toISOString(),outcome:e})}finally{process.removeListener("SIGINT",i)}}p(b,"runFirstSetup");function x(r){let i=process.cwd(),t,e,a,c=!1,l;const f=[];for(let n=0;n<r.length;n++){const o=r[n];o==="--name"?t=r[++n]:o==="--kind"?e=r[++n]:o==="--profile"?a=r[++n]:o==="--pick-profile"?c=!0:o==="--continue"||o==="-c"?l="continue":o==="--resume"||o==="-r"?l="pick":o.startsWith("--")||f.push(o)}f.length>0&&g(d(f[0]))&&(i=d(f.shift()));const m=f.length>0?f.join(" "):void 0;return{cwd:i,prompt:m,name:t,kind:e,profile:a,pickProfile:c,resume:l}}p(x,"parseRootArgs");import{FRONT_DOOR_ENV as z}from"./front-door-env.js";async function $(r){const i=r.slice(2),t=i[0];if(process.env[A]||t==="-h"||t==="--help"||t==="--version"||t==="-v"||t!==void 0&&N.includes(t))return!1;if(t!==void 0){const s=/\s/.test(t),u=!t.startsWith("-")&&g(d(t)),y=W.has(t);if(!s&&!u&&!y)return!1;if(u){const{buildRoot:E}=await import("../../build-root.js");if((await E()).subtrees.some(F=>F.name===t))return!1}}const e=x(i);if(e.profile!==void 0){const{resolveProfileOperand:s}=await import("../profiles/manifest.js");e.profile=s(e.profile).profileId}const a=process.stdin.isTTY&&process.stdout.isTTY;let c=!1;a&&!w(h)&&(await b(),c=!0);const{selectProfileForCwd:l,selectProfileForCwdReadOnly:f}=await import("../profiles/select.js");c&&e.profile===void 0&&process.stdout.write(`
2
2
  Choose a profile
3
3
  `);const m=e.profile??(a?await l(e.cwd,void 0,e.pickProfile):f(e.cwd)),{exitForMissingProviderCredential:n,hasConfiguredProviderCredential:o}=await import("./provider-credential-gate.js");if(!await o(m)){a||n();const{runFrontDoorLogin:s}=await import("./front-door-login.js");await s()||n()}const[{bootRoot:P},{resumeRoot:R},{rendererWarning:k,missingPackageWarning:S,piAgentDir:O}]=await Promise.all([import("./boot-root.js"),import("./resume-root.js"),import("./package-health.js")]);try{const s=S(O());s!==null&&process.stderr.write(`
4
4
  ${s}
@@ -6,4 +6,4 @@ ${s}
6
6
  `);const u=k();u!==null&&process.stderr.write(`
7
7
  ${u}
8
8
 
9
- `)}catch{}if(e.resume!==void 0&&await R(e.cwd,e.resume==="pick")==="aborted")return!0;const{prompt:D,initialWhip:T}=L({setupJustRan:c,userPrompt:e.prompt});return await P({...e,prompt:D,initialWhip:T,selectedProfileId:m}),!0}p($,"maybeBootRoot");export{z as FRONT_DOOR_ENV,$ as maybeBootRoot};
9
+ `)}catch{}if(e.resume!==void 0&&await R(e.cwd,e.resume==="pick")==="aborted")return!0;const{prompt:D,initialWhip:T}=C({setupJustRan:c,userPrompt:e.prompt});return await P({...e,prompt:D,initialWhip:T,selectedProfileId:m}),!0}p($,"maybeBootRoot");export{z as FRONT_DOOR_ENV,$ as maybeBootRoot};
@@ -1,4 +1,4 @@
1
- import type { ConstrainedSamplingConfig } from '@earendil-works/pi-ai';
1
+ import { type ConstrainedSamplingConfig } from '@earendil-works/pi-ai';
2
2
  import type { AgentMessage } from '@earendil-works/pi-agent-core';
3
3
  import type { TSchema } from 'typebox';
4
4
  export interface HeadlessTool {
@@ -1 +1 @@
1
- var A=Object.defineProperty;var d=(e,t)=>A(e,"name",{value:t,configurable:!0});import{envNodeCwd as j,envProfileId as F}from"../../shared/env.js";import{join as P}from"node:path";import{PoolCredentialStore as E}from"../pool-credential-store.js";import{modelRequestFromConfig as D,selectInitialModelRoute as L}from"../model-routes.js";function O(e){for(let t=e.length-1;t>=0;t--){const s=e[t];if(s?.role!=="assistant")continue;if(typeof s.content=="string")return s.content.trim();if(!Array.isArray(s.content))continue;const i=s.content.map(a=>{const o=a;return o.type==="text"&&typeof o.text=="string"?o.text:""}).join("").trim();if(i!=="")return i}return""}d(O,"lastAssistantText");async function c(e,t,s){let i,a=!1,o=!1,u;const f=d(n=>{i===void 0||a||(a=!0,n&&i.abort().catch(()=>{}),i.dispose())},"disposeSession"),T=new Promise(n=>{u=setTimeout(()=>{o=!0,f(!0),n(t)},e.timeoutMs)}),h=(async()=>{try{const[n,v]=await Promise.all([import("@earendil-works/pi-coding-agent"),import("../../builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.js")]);if(o)return t;const l=j()??process.cwd(),p=F(),m=n.getAgentDir(),I=await n.ModelRuntime.create({credentials:new E(P(m,"auth.json")),modelsPath:P(m,"models.json")});if(o)return t;const g=await n.createAgentSessionServices({cwd:l,agentDir:m,modelRuntime:I,settingsManager:n.SettingsManager.inMemory(),resourceLoaderOptions:{noExtensions:!0,noContextFiles:!0,noSkills:!0,noPromptTemplates:!0,noThemes:!0,systemPrompt:e.systemPrompt,extensionFactories:[v.createProviderRotationExtension({modelIntent:e.modelIntent,nodeCwd:l,profileId:p})]}});if(o)return t;const y=D(e.modelSpec,e.modelIntent,!1);if(y===void 0)return t;const x=L(y,new n.ModelRegistry(g.modelRuntime),{cwd:l,profileId:p}).selected;if(x===void 0)return t;let w;const r=e.tool,R=r===void 0?void 0:n.defineTool({name:r.name,label:r.label,description:r.description,parameters:r.parameters,...r.constrainedSampling===void 0?{}:{constrainedSampling:r.constrainedSampling},async execute(M,C){return w=C,{content:[{type:"text",text:"Recorded."}],details:{recorded:!0},terminate:!0}}}),S=n.SessionManager.inMemory(l,e.sessionId===void 0?void 0:{id:e.sessionId});for(const M of e.seedMessages??[])S.appendMessage(M);return{session:i}=await n.createAgentSessionFromServices({services:g,sessionManager:S,model:x.model,thinkingLevel:"off",...r===void 0?e.toolPolicy==="builtin"?{}:{noTools:"all"}:{tools:[r.name],customTools:[R]}}),o||(await i.bindExtensions({}),o)?t:(await i.prompt(e.userPrompt),o?t:s(i,w))}catch{return t}finally{f(!1)}})();try{return await Promise.race([h,T])}finally{clearTimeout(u)}}d(c,"runHeadless");function G(e){return c(e,null,(t,s)=>s)}d(G,"headlessToolCall");function J(e){return c(e,"",t=>O(t.messages))}d(J,"headlessText");function K(e){return c(e,"failed",()=>"completed")}d(K,"headlessTurn");export{J as headlessText,G as headlessToolCall,K as headlessTurn};
1
+ var j=Object.defineProperty;var a=(e,t)=>j(e,"name",{value:t,configurable:!0});import{envNodeCwd as F,envProfileId as D}from"../../shared/env.js";import{join as h}from"node:path";import{InMemoryCredentialStore as E}from"@earendil-works/pi-ai";import{PoolCredentialStore as L}from"../pool-credential-store.js";import{secretsDir as N}from"../layout.js";import{expandModelCandidates as O,modelRequestFromConfig as _,selectInitialModelRoute as B}from"../model-routes.js";import{configureBrokerModelRuntime as H}from"./broker/model-adapter.js";import{currentNodeToken as z}from"./broker/node-token.js";function G(e){for(let t=e.length-1;t>=0;t--){const i=e[t];if(i?.role!=="assistant")continue;if(typeof i.content=="string")return i.content.trim();if(!Array.isArray(i.content))continue;const r=i.content.map(l=>{const o=l;return o.type==="text"&&typeof o.text=="string"?o.text:""}).join("").trim();if(r!=="")return r}return""}a(G,"lastAssistantText");async function p(e,t,i){let r,l=!1,o=!1,g;const y=a(n=>{r===void 0||l||(l=!0,n&&r.abort().catch(()=>{}),r.dispose())},"disposeSession"),v=new Promise(n=>{g=setTimeout(()=>{o=!0,y(!0),n(t)},e.timeoutMs)}),R=(async()=>{try{const n=await import("@earendil-works/pi-coding-agent"),c=z()!==void 0;if(o)return t;const m=F()??process.cwd(),u=D(),x=n.getAgentDir(),w=await n.ModelRuntime.create({credentials:c?new E:new L(h(N(),"auth.json")),modelsPath:h(x,"models.json")});if(c&&H(w),o)return t;const M=await n.createAgentSessionServices({cwd:m,agentDir:x,modelRuntime:w,settingsManager:n.SettingsManager.inMemory(),resourceLoaderOptions:{noExtensions:!0,noContextFiles:!0,noSkills:!0,noPromptTemplates:!0,noThemes:!0,systemPrompt:e.systemPrompt,...c?{}:{extensionFactories:[(await import("../../builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.js")).createProviderRotationExtension({modelIntent:e.modelIntent,nodeCwd:m,profileId:u})]}}});if(o)return t;const f=_(e.modelSpec,e.modelIntent,!1);if(f===void 0)return t;const S=new n.ModelRegistry(M.modelRuntime),T=c?O(f,m,u).map(d=>S.find(d.providerId,d.modelId)).find(d=>d!==void 0):B(f,S,{cwd:m,profileId:u}).selected?.model;if(T===void 0)return t;let I;const s=e.tool,C=s===void 0?void 0:n.defineTool({name:s.name,label:s.label,description:s.description,parameters:s.parameters,...s.constrainedSampling===void 0?{}:{constrainedSampling:s.constrainedSampling},async execute(d,A){return I=A,{content:[{type:"text",text:"Recorded."}],details:{recorded:!0},terminate:!0}}}),P=n.SessionManager.inMemory(m,e.sessionId===void 0?void 0:{id:e.sessionId});for(const d of e.seedMessages??[])P.appendMessage(d);return{session:r}=await n.createAgentSessionFromServices({services:M,sessionManager:P,model:T,thinkingLevel:"off",...s===void 0?e.toolPolicy==="builtin"?{}:{noTools:"all"}:{tools:[s.name],customTools:[C]}}),o||(await r.bindExtensions({}),o)?t:(await r.prompt(e.userPrompt),o?t:i(r,I))}catch{return t}finally{y(!1)}})();try{return await Promise.race([R,v])}finally{clearTimeout(g)}}a(p,"runHeadless");function $(e){return p(e,null,(t,i)=>i)}a($,"headlessToolCall");function b(e){return p(e,"",t=>G(t.messages))}a(b,"headlessText");function k(e){return p(e,"failed",()=>"completed")}a(k,"headlessTurn");export{b as headlessText,$ as headlessToolCall,k as headlessTurn};
@@ -35,7 +35,7 @@ export interface TeardownResult {
35
35
  export interface Host {
36
36
  /** Bring a node's ENGINE into existence from its launch recipe; return a
37
37
  * supervisable handle. */
38
- launch(nodeId: string, inv: PiInvocation, opts: LaunchPlacement): HostHandle;
38
+ launch(nodeId: string, inv: PiInvocation, opts: LaunchPlacement): HostHandle | Promise<HostHandle>;
39
39
  /** Is this node's engine alive? PURE / non-mutating. `string | NodeRow` so
40
40
  * both call sites — the revive guard (passes the id) and the daemon (passes a
41
41
  * row) — share one selector. For the broker this IS isPidAlive(pi_pid). */
@@ -1 +1,3 @@
1
- var A=Object.defineProperty;var a=(e,t)=>A(e,"name",{value:t,configurable:!0});import{spawn as G}from"node:child_process";import{mkdirSync as R,writeFileSync as j,readFileSync as C,existsSync as k,unlinkSync as F,openSync as K,closeSync as T}from"node:fs";import{dirname as M,join as g,resolve as W,isAbsolute as q}from"node:path";import{fileURLToPath as O}from"node:url";import{connect as H}from"node:net";import{getNode as _}from"../canvas/index.js";import{crtrHome as U,nodeDir as J,jobDir as z,viewSocketPath as Q}from"../canvas/paths.js";import{encodeFrame as V}from"./broker-protocol.js";import{buildBrokerEnv as X}from"./spawn-env.js";import{hostExecPath as Y}from"./branded-host.js";import{isPidAlive as Z,killProcessTreePids as N,isAnyPidAlive as I,captureTeardownSnapshot as ee}from"../canvas/pid.js";import{assertMandatoryCanvasExtensions as re}from"./canvas-extensions.js";import{boundFleet as ne,brokerCapReached as te,brokerThresholdsForDaemon as oe}from"./fleet.js";import{emitEvent as m}from"../events/emit.js";import{bindBrokerEventSource as ie,eventSource as se}from"../events/source.js";import{envBrokerEngine as ce}from"../../shared/env.js";function x(){const e=M(O(import.meta.url));return g(e,"broker-cli.js")}a(x,"resolveBrokerEntry");const ae="@earendil-works/pi-coding-agent";function B(e){return e.env.CRTR_BROKER_ENGINE??ce()}a(B,"resolveEngineSpec");function D(e){return e.includes("/")||e.endsWith(".jsonl")}a(D,"isPlainLaunchSessionPath");function le(e,t){return q(e)?e:W(t,e)}a(le,"resolvePlainLaunchPath");function fe(e,t,r,n){if(r==="--session"&&!D(n))throw new Error(`[broker] refusing to launch ${e}: launch recipe passes bare --session id '${n}' \u2014 the broker fatally rejects bare ids; pass the .jsonl path instead.`);if(!D(n))return;const o=le(n,t);if(!k(o)){const u=r==="--session"?"session file":"fork source";throw new Error(`[broker] refusing to launch ${e}: launch recipe references missing ${u} '${n}' (${o})`)}}a(fe,"preflightLaunchSessionArg");function ue(e,t,r){const n=J(e);R(n,{recursive:!0});const o=g(n,"broker-launch.json");j(o,JSON.stringify(t));const u=C(o,"utf8"),l=JSON.parse(u);if(!Array.isArray(l.argv))throw new Error(`[broker] refusing to launch ${e}: broker-launch.json is missing the argv array`);const f=B(t);try{const s=import.meta.resolve(f);if(s.startsWith("file:")&&!k(O(s)))throw new Error(`resolved to missing file ${s}`)}catch(s){throw new Error(`[broker] refusing to launch ${e}: cannot resolve broker engine '${f}' from ${x()} \u2014 ${s.message}`)}const i=l.argv,c=[];for(let s=0;s<i.length;s++){const d=i[s];if(d==="-e"){const p=i[++s];p!==void 0&&c.push(p);continue}if(d!=="--session"&&d!=="--fork")continue;const v=i[++s];v!==void 0&&fe(e,r,d,v)}try{re(c)}catch(s){throw new Error(`[broker] refusing to launch ${e}: ${s.message}`)}}a(ue,"preflightBrokerLaunch");const de=2e3,he=2e3,me=150;async function S(e,t){const r=Date.now()+t;for(;I(e);){const n=r-Date.now();if(n<=0)return!1;await new Promise(o=>setTimeout(o,Math.min(me,n)))}return!0}a(S,"waitForTreeExit");async function pe(e,t,r){return e.length===0?{confirmed:!0}:r&&await S(e,de)?{confirmed:!0}:(N(e,"SIGTERM",t),await S(e,he)?{confirmed:!0}:(N(e,"SIGKILL",t),await S(e,5e3)?{confirmed:!0}:{confirmed:!1,error:new Error(`broker process tree for ${e.join(", ")} remained alive after SIGKILL`)}))}a(pe,"terminateBrokerTree");function $(e,t){const r=_(e),n=r?.pi_pid,o=n!=null?ee(n,r?.pi_pid_identity??null,t.excludePid):null;return o?.reused===!0&&m({level:"warn",event:"broker.teardown.pid_reuse_refused",node_id:e,fields:{recorded_pid:n,expected_identity:r?.pi_pid_identity??null}}),{tree:o?.tree??[],identities:o?.identities??null,sockPath:Q(e)}}a($,"prepareBrokerTeardown");async function L(e){return new Promise(t=>{let r=!1,n=!1;const o=a(i=>{n||(n=!0,t(i))},"settle"),u=a(()=>{try{k(e.sockPath)&&F(e.sockPath)}catch{}},"cleanupSocket"),l=a(i=>{pe(e.tree,e.identities,i).then(o,c=>o({confirmed:!1,error:c instanceof Error?c:new Error(String(c))}))},"finish"),f=H(e.sockPath);f.once("error",()=>{r||(u(),l(!1))}),f.once("connect",()=>{r=!0;try{f.write(V({type:"shutdown"}))}catch{}f.end(),u(),l(!0)})})}a(L,"runPreparedBrokerTeardown");const E=new Map;function $e(e,t={},r){const n=E.get(e);if(n!==void 0)return r!==void 0&&n.after.push(r),n.completion;let o;const u=new Promise(i=>{o=i}),l={completion:u,resolve:o,after:r===void 0?[]:[r]};E.set(e,l);let f;try{f=$(e,t)}catch(i){const c={confirmed:!1,error:i instanceof Error?i:new Error(String(i))};return E.delete(e),m({level:"error",event:"broker.teardown.unconfirmed",node_id:e,error:c.error}),l.resolve(c),u}return setImmediate(()=>{E.delete(e),L(f).then(async i=>{if(i.confirmed)for(const c of l.after)try{await c()}catch(s){m({level:"error",event:"broker.teardown.after_failed",node_id:e,error:s})}else m({level:"error",event:"broker.teardown.unconfirmed",node_id:e,error:i.error});l.resolve(i)},i=>{const c={confirmed:!1,error:i instanceof Error?i:new Error(String(i))};m({level:"error",event:"broker.teardown.unconfirmed",node_id:e,error:c.error}),l.resolve(c)})}),u}a($e,"requestBrokerTeardown");const Le={launch(e,t,r){ue(e,t,r.cwd);const n=ne();if(!n.reserveSlot(e))throw te(oe().automaticReviveCap,n.size());let o=null,u,l=!1;try{const f=z(e);R(f,{recursive:!0}),o=K(g(f,"broker.log"),"a");const i=B(t),c={...X(t),CRTR_BROKER_ENGINE:i};if(i!==ae){const w=t.env.NODE_OPTIONS??process.env.NODE_OPTIONS;w!==void 0&&(c.NODE_OPTIONS=w)}se()===void 0&&ie(e);const s=G(Y(),[x(),"--canvas-home",U(),"--epoch",n.epoch(),e],{cwd:r.cwd,detached:!0,stdio:["ignore",o,o],env:c});u=s,T(o),o=null;const d=Date.now(),v=new Promise(w=>{let y=!1;const b=a(h=>{y||(y=!0,w(h))},"finish");s.once("exit",(h,P)=>{m({level:h===0?"info":"warn",event:"broker.exited",node_id:e,fields:{code:h,signal:P,uptime_ms:Date.now()-d}}),b({code:h,signal:P})}),s.once("error",h=>{m({level:"error",event:"broker.launch.failed",node_id:e,error:h,fields:{uptime_ms:Date.now()-d}}),b({code:null,signal:null})})});s.unref();const p={pid:s.pid??null,exited:v};return p.pid!==null&&(n.register(e,p),l=!0,v.then(w=>n.onChildExit(e,w))),p}catch(f){if(!l&&u?.pid!=null)try{u.kill("SIGTERM")}catch{}throw f}finally{l||n.releaseReservation(e),o!==null&&T(o)}},isAlive(e){return Z((typeof e=="string"?_(e):e)?.pi_pid)},teardown(e,t={}){try{return L($(e,t))}catch(r){return Promise.resolve({confirmed:!1,error:r instanceof Error?r:new Error(String(r))})}},signal(e,t){const r=_(e)?.pi_pid;if(r!=null)try{process.kill(r,t)}catch{}}};export{Le as headlessBrokerHost,ue as preflightBrokerLaunch,$e as requestBrokerTeardown};
1
+ var Ee=Object.defineProperty;var f=(e,n)=>Ee(e,"name",{value:n,configurable:!0});import{spawn as ve}from"node:child_process";import{mkdirSync as oe,existsSync as B,unlinkSync as ie,openSync as C,closeSync as O,writeSync as ke,chmodSync as _e,lstatSync as Se}from"node:fs";import{ensureAppSpace as be}from"../spaces/space.js";import{compileLaunch as ye,launchStillGranted as Pe}from"../spaces/mounts.js";import{grantsGeneration as se}from"../grants/mirror.js";import{LAUNCHER_SOCKET as M}from"../../launcher/spec.js";import{launcherRequest as J}from"../../launcher/client.js";import{piAgentDir as Re}from"./package-health.js";import{existsBeneath as xe,readFileBeneath as Oe,readTextBeneathIfExists as Te,setModeBeneath as b,withDirBeneath as ce,writeFileBeneath as U}from"../spaces/open-beneath.js";import{dirname as H,join as h,resolve as De,isAbsolute as Ne}from"node:path";import{fileURLToPath as ae}from"node:url";import{connectViewSocket as Ae}from"./view-socket.js";import{appSpace as q}from"../layout.js";import{readConfig as $e,readMergedLaunchConfig as Be}from"../config.js";import{readRotationConfig as Ce}from"../subscription-state.js";import{getNode as y}from"../canvas/index.js";import{crtrHome as le,nodeRunDir as W,nodeRunJobDir as Le,jobDir as je,viewSocketPath as Fe,nodeAgentDir as Ge,contextDir as Ke}from"../canvas/paths.js";import{encodeFrame as Me}from"./broker-protocol.js";import{buildBrokerEnv as Je}from"./spawn-env.js";import{hostExecPath as Ue}from"./branded-host.js";import{isPidAlive as z,killProcessTreePids as ue,isAnyPidAlive as He,captureTeardownSnapshot as qe}from"../canvas/pid.js";import{assertMandatoryCanvasExtensions as We}from"./canvas-extensions.js";import{boundFleet as ze,brokerCapReached as Ve,brokerThresholdsForDaemon as Xe}from"./fleet.js";import{emitEvent as w}from"../events/emit.js";import{bindBrokerEventSource as Qe,eventSource as Ye}from"../events/source.js";import{envBrokerEngine as Ze}from"../../shared/env.js";import{conversationIdFromPath as Ie,conversationStore as er,ConversationNotFoundError as fe,storeAddress as rr}from"../conversation-store/index.js";import{takeNodeToken as nr}from"../canvas/node-tokens.js";function L(){const e=H(ae(import.meta.url));return h(e,"broker-cli.js")}f(L,"resolveBrokerEntry");const tr="@earendil-works/pi-coding-agent";function or(e,n){const t=h(Re(),"models.json"),r=h(n,"models.json"),o=Te(H(t),t);if(o===null)return;const l=JSON.parse(o),c=f(i=>Array.isArray(i)?i.map(c):i===null||typeof i!="object"?i:Object.fromEntries(Object.entries(i).filter(([s])=>!/^(apiKey|authorization|headers|token|secret)$/i.test(s)).map(([s,E])=>[s,c(E)])),"scrub"),a=`${JSON.stringify(c(l),null,2)}
2
+ `;if(t===r&&o!==a){if(JSON.stringify(l)!==JSON.stringify(c(l)))throw new Error("terminal models.json contains credentials; move them into daemon secrets");b(e,r,432);return}U(e,r,a,{atomic:!0,mode:432}),b(e,r,432)}f(or,"writeBrokerModels");function de(e){return e.env.CRTR_BROKER_ENGINE??Ze()}f(de,"resolveEngineSpec");function pe(e){return e.includes("/")||e.endsWith(".jsonl")}f(pe,"isPlainLaunchSessionPath");function ir(e,n){return Ne(e)?e:De(n,e)}f(ir,"resolvePlainLaunchPath");function sr(e,n,t,r){if(t==="--session"&&!pe(r))throw new Error(`[broker] refusing to launch ${e}: launch recipe passes bare --session id '${r}' \u2014 the broker fatally rejects bare ids; pass the .jsonl path instead.`);if(!pe(r))return;const o=ir(r,n),l=Ie(o);try{if(l===null)throw new fe(o);er().header(l)}catch(c){if(!(c instanceof fe))throw c;const a=t==="--session"?"session file":"fork source";throw new Error(`[broker] refusing to launch ${e}: launch recipe references missing ${a} '${r}' (${o})`)}}f(sr,"preflightLaunchSessionArg");function cr(e,n,t){const r=W(e);oe(r,{recursive:!0}),process.platform==="linux"&&B(M)&&Se(r).uid===process.getuid()&&_e(r,504);const o=h(r,"broker-launch.json"),l={user:$e("user"),launch:Be(t,n.env.CRTR_PROFILE_ID||null),rotation:Ce()};U(r,o,JSON.stringify({...n,configSnapshot:l}),{atomic:!0});const c=Oe(r,o).toString("utf8"),a=JSON.parse(c);if(!Array.isArray(a.argv))throw new Error(`[broker] refusing to launch ${e}: broker-launch.json is missing the argv array`);const i=de(n);try{const u=import.meta.resolve(i);if(u.startsWith("file:")&&!B(ae(u)))throw new Error(`resolved to missing file ${u}`)}catch(u){throw new Error(`[broker] refusing to launch ${e}: cannot resolve broker engine '${i}' from ${L()} \u2014 ${u.message}`)}const s=a.argv,E=[];for(let u=0;u<s.length;u++){const _=s[u];if(_==="-e"){const v=s[++u];v!==void 0&&E.push(v);continue}if(_!=="--session"&&_!=="--fork")continue;const P=s[++u];P!==void 0&&sr(e,t,_,P)}try{We(E)}catch(u){throw new Error(`[broker] refusing to launch ${e}: ${u.message}`)}}f(cr,"preflightBrokerLaunch");const ar=2e3,lr=2e3,ur=150;async function j(e,n){const t=Date.now()+n;for(;He(e);){const r=t-Date.now();if(r<=0)return!1;await new Promise(o=>setTimeout(o,Math.min(ur,r)))}return!0}f(j,"waitForTreeExit");async function fr(e,n,t){return e.length===0?{confirmed:!0}:t&&await j(e,ar)?{confirmed:!0}:(ue(e,"SIGTERM",n),await j(e,lr)?{confirmed:!0}:(ue(e,"SIGKILL",n),await j(e,5e3)?{confirmed:!0}:{confirmed:!1,error:new Error(`broker process tree for ${e.join(", ")} remained alive after SIGKILL`)}))}f(fr,"terminateBrokerTree");function me(e,n){const t=y(e),r=t?.pi_pid,o=r!=null?qe(r,t?.pi_pid_identity??null,n.excludePid):null;return o?.reused===!0&&w({level:"warn",event:"broker.teardown.pid_reuse_refused",node_id:e,fields:{recorded_pid:r,expected_identity:t?.pi_pid_identity??null}}),{tree:o?.tree??[],identities:o?.identities??null,nodeId:e,launcherPid:B(M)&&o?.tree.includes(r)?r:null}}f(me,"prepareBrokerTeardown");async function he(e){if(e.launcherPid!==null){try{await J({operation:"stop",pid:e.launcherPid})}catch(n){return z(e.launcherPid)?{confirmed:!1,error:n instanceof Error?n:new Error(String(n))}:{confirmed:!0}}return await j([e.launcherPid],5e3)?{confirmed:!0}:{confirmed:!1,error:new Error(`launcher pid ${e.launcherPid} remained alive`)}}return new Promise(n=>{let t=!1,r=!1;const o=f(i=>{r||(r=!0,n(i))},"settle"),l=f(()=>{try{ie(Fe(e.nodeId))}catch{}},"cleanupSocket"),c=f(i=>{fr(e.tree,e.identities,i).then(o,s=>o({confirmed:!1,error:s instanceof Error?s:new Error(String(s))}))},"finish"),a=Ae(e.nodeId);a.once("error",()=>{t||(l(),c(!1))}),a.once("connect",()=>{t=!0;try{a.write(Me({type:"shutdown"}))}catch{}a.end(),l(),c(!0)})})}f(he,"runPreparedBrokerTeardown");const F=new Map;function Mr(e,n={},t){const r=F.get(e);if(r!==void 0)return t!==void 0&&r.after.push(t),r.completion;let o;const l=new Promise(i=>{o=i}),c={completion:l,resolve:o,after:t===void 0?[]:[t]};F.set(e,c);let a;try{a=me(e,n)}catch(i){const s={confirmed:!1,error:i instanceof Error?i:new Error(String(i))};return F.delete(e),w({level:"error",event:"broker.teardown.unconfirmed",node_id:e,error:s.error}),c.resolve(s),l}return setImmediate(()=>{F.delete(e),he(a).then(async i=>{if(i.confirmed)for(const s of c.after)try{await s()}catch(E){w({level:"error",event:"broker.teardown.after_failed",node_id:e,error:E})}else w({level:"error",event:"broker.teardown.unconfirmed",node_id:e,error:i.error});c.resolve(i)},i=>{const s={confirmed:!1,error:i instanceof Error?i:new Error(String(i))};w({level:"error",event:"broker.teardown.unconfirmed",node_id:e,error:s.error}),c.resolve(s)})}),l}f(Mr,"requestBrokerTeardown");const Jr={async launch(e,n,t){cr(e,n,t.cwd);const r=ze();if(!r.reserveSlot(e))throw Ve(Xe().automaticReviveCap,r.size());let o=null,l,c=!1;try{const a=je(e);oe(a,{recursive:!0}),o=C(h(a,"broker.log"),"a");const i=de(n),s={...Je(n),CRTR_BROKER_ENGINE:i,CRTR_STORE_ADDRESS:rr()};if(i!==tr){const d=n.env.NODE_OPTIONS??process.env.NODE_OPTIONS;d!==void 0&&(s.NODE_OPTIONS=d)}Ye()===void 0&&Qe(e);const E=y(e)?.run_id;if(E){const d=y(E);if(!d||d.deleting_at)throw new Error("run is deleting")}const u=n.env.CRTR_EXECUTION_ID;if(!u)throw new Error("broker launch has no execution id");const _=nr(u),P=process.platform==="linux"&&B(M);if(process.platform==="linux"&&process.env.CRTR_LAUNCHER_SOCKET&&!P)throw new Error("root launcher socket is unavailable; refusing an unsandboxed broker");if(P){const d=y(e);if(!d)throw new Error(`missing node ${e}`);const g=d.grantee??"app:terminal",D=await be(g),m={uid:process.getuid(),gid:D.gid},k=W(e);for(const[p,S]of[[q(g).nodes,Ge(e,g)],[q(g).nodes,Ke(e,g)],[k,Le(e)]])ce(p,S,()=>{},!0),b(p,S,1528,m);b(k,h(k,"broker-launch.json"),416,m);const Q=h(k,"system-prompt.md");xe(k,Q)&&b(k,Q,432,m);const R=q(g).home,K=h(R,".pi","agent");ce(R,K,()=>{},!0),or(R,K);const Y=h(K,"settings.json"),we=h(H(L()),"../../builtin-pi-packages/pi-crtr-extensions");U(R,Y,`${JSON.stringify({packages:[we]})}
3
+ `,{atomic:!0,mode:432}),b(R,Y,432);const Z=h(W(e),`token-${u}`),N=C(Z,"wx+",384);ie(Z),ke(N,_);const I=[C(`/proc/self/fd/${N}`,"r"),C(`/proc/self/fd/${N}`,"r")];O(N);const ee={nodeId:e,app:g,sub:d.sub??"user:local",grantId:d.grant_id??null,scopes:d.scopes??null,command:[process.execPath,L(),"--canvas-home",le(),"--epoch",r.epoch(),e],env:Object.fromEntries(Object.entries(s).filter(p=>p[1]!==void 0)),auditMissing:f(p=>w({level:"warn",event:"broker.mount.missing",node_id:e,fields:{source:p}}),"auditMissing")};try{let p;for(const x of I){const A=se(),te=ye(ee),$=await J({operation:"launch",spec:te},[x]);if(!("pid"in $))throw new Error("launcher did not return a pid");if(se()===A||Pe(ee,te)){p=$.pid;break}w({level:"info",event:"broker.launch.regranted",node_id:e,fields:{pid:$.pid}}),await J({operation:"stop",pid:$.pid,signal:"SIGKILL"}).catch(()=>{})}if(p===void 0)throw new Error("grant changed during every launch attempt");const S=p,ge=Date.now(),re=new Promise(x=>{const A=setInterval(()=>{z(S)||(clearInterval(A),w({level:"info",event:"broker.exited",node_id:e,fields:{pid:S,uptime_ms:Date.now()-ge}}),x({code:null,signal:null}))},250);A.unref()});O(o),o=null;const ne={pid:S,exited:re};return r.register(e,ne),c=!0,re.then(x=>r.onChildExit(e,x,u)),ne}finally{for(const p of I)O(p)}}const v=ve(Ue(),[L(),"--canvas-home",le(),"--epoch",r.epoch(),e],{cwd:t.cwd,detached:!0,stdio:["ignore",o,o,"pipe"],env:s});l=v;const T=v.stdio[3];if(!T||!("end"in T))throw new Error("broker token pipe did not open");T.on("error",d=>w({event:"broker.token_pipe.failed",level:"error",node_id:e,error:d})),T.end(_),O(o),o=null;const V=Date.now(),X=new Promise(d=>{let g=!1;const D=f(m=>{g||(g=!0,d(m))},"finish");v.once("exit",(m,k)=>{w({level:m===0?"info":"warn",event:"broker.exited",node_id:e,fields:{code:m,signal:k,uptime_ms:Date.now()-V}}),D({code:m,signal:k})}),v.once("error",m=>{w({level:"error",event:"broker.launch.failed",node_id:e,error:m,fields:{uptime_ms:Date.now()-V}}),D({code:null,signal:null})})});v.unref();const G={pid:v.pid??null,exited:X};return G.pid!==null&&(r.register(e,G),c=!0,X.then(d=>r.onChildExit(e,d,u))),G}catch(a){if(!c&&l?.pid!=null)try{l.kill("SIGTERM")}catch{}throw a}finally{c||r.releaseReservation(e),o!==null&&O(o)}},isAlive(e){return z((typeof e=="string"?y(e):e)?.pi_pid)},teardown(e,n={}){try{return he(me(e,n))}catch(t){return Promise.resolve({confirmed:!1,error:t instanceof Error?t:new Error(String(t))})}},signal(e,n){const t=y(e)?.pi_pid;if(t!=null)try{process.kill(t,n)}catch{}}};export{Jr as headlessBrokerHost,cr as preflightBrokerLaunch,Mr as requestBrokerTeardown};
@@ -1,4 +1,7 @@
1
+ import type { BrokerConfigSnapshot } from '../config.js';
1
2
  export interface PiInvocation {
3
+ /** The daemon-resolved config used by a broker without access to runtime records. */
4
+ configSnapshot?: BrokerConfigSnapshot;
2
5
  /** argv after the `pi` binary. */
3
6
  argv: string[];
4
7
  /** env to merge into the process. */
@@ -34,6 +34,7 @@ export interface ReviveBearings {
34
34
  yieldMsg: string | null;
35
35
  /** Coalesced wake mail, held by the execution until the turn settles. */
36
36
  unreadDigest: string | null;
37
+ unreadMessageIds?: string[];
37
38
  /** Persona-transition framing to surface when the node's role changed while
38
39
  * it was away. The drift remains pending until context-intro completes. */
39
40
  driftGuidance: string | null;