@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
@@ -0,0 +1,88 @@
1
+ export declare const APP_UID_MIN = 200000;
2
+ export declare const APP_UID_MAX = 299999;
3
+ export declare const LAUNCHER_SOCKET = "/run/crtr/launcher.sock";
4
+ export interface LaunchSpec {
5
+ nodeId: string;
6
+ uid: number;
7
+ mounts: Array<{
8
+ source: string;
9
+ writable: boolean;
10
+ }>;
11
+ cwd: string;
12
+ env: Record<string, string>;
13
+ command: string[];
14
+ log: string;
15
+ /** Non-broker processes return bounded output and exit status through wait. */
16
+ capture?: {
17
+ stdoutBytes: number;
18
+ stderrBytes: number;
19
+ stderrTail?: boolean;
20
+ stdin?: string;
21
+ };
22
+ pluginRoot?: string;
23
+ token?: never;
24
+ }
25
+ export type LauncherRequest = {
26
+ operation: 'launch';
27
+ spec: LaunchSpec;
28
+ } | {
29
+ operation: 'stop';
30
+ pid: number;
31
+ signal?: 'SIGTERM' | 'SIGKILL';
32
+ nodeId?: string;
33
+ } | {
34
+ operation: 'wait';
35
+ pid: number;
36
+ } | {
37
+ operation: 'user.create';
38
+ app: string;
39
+ uid: number;
40
+ } | {
41
+ operation: 'user.delete';
42
+ uid: number;
43
+ } | {
44
+ operation: 'users.sync';
45
+ users: Array<{
46
+ app: string;
47
+ uid: number;
48
+ }>;
49
+ } | {
50
+ operation: 'daemon.handover';
51
+ }
52
+ /** Every live sandbox with the mounts it was launched with (runtime spec §15, R26 sweep). */
53
+ | {
54
+ operation: 'list';
55
+ };
56
+ export interface SandboxRecord {
57
+ pid: number;
58
+ uid: number;
59
+ nodeId: string;
60
+ mounts: LaunchSpec['mounts'];
61
+ }
62
+ export interface CapturedExit {
63
+ exitCode: number | null;
64
+ signal: NodeJS.Signals | null;
65
+ stdout: string;
66
+ stderr: string;
67
+ stdoutTruncated: boolean;
68
+ stderrTruncated: boolean;
69
+ stdoutSha256: string;
70
+ }
71
+ export type LauncherReply = {
72
+ pid: number;
73
+ } | {
74
+ sandboxes: SandboxRecord[];
75
+ } | {
76
+ result: CapturedExit;
77
+ } | {
78
+ uid: number;
79
+ } | {
80
+ ok: true;
81
+ } | {
82
+ refusal: LauncherRefusal;
83
+ };
84
+ export type LauncherRefusal = 'invalid_spec' | 'invalid_uid' | 'runtime_source' | 'run_source' | 'writable_source' | 'symlink_source' | 'source_missing' | 'source_type' | 'log_refused' | 'launch_failed';
85
+ export declare class LaunchRefused extends Error {
86
+ readonly refusal: LauncherRefusal;
87
+ constructor(refusal: LauncherRefusal, message: string);
88
+ }
@@ -0,0 +1 @@
1
+ var o=Object.defineProperty;var e=(s,r)=>o(s,"name",{value:r,configurable:!0});const n=2e5,u=299999,a="/run/crtr/launcher.sock";class p extends Error{static{e(this,"LaunchRefused")}refusal;constructor(r,t){super(t),this.refusal=r}}export{u as APP_UID_MAX,n as APP_UID_MIN,a as LAUNCHER_SOCKET,p as LaunchRefused};
@@ -0,0 +1,18 @@
1
+ export declare function systemIdentity(): {
2
+ daemonUid: number;
3
+ daemonGid: number;
4
+ dataGid: number;
5
+ };
6
+ export declare class AppUsers {
7
+ private readonly dataGid;
8
+ private users;
9
+ constructor(dataGid: number);
10
+ sync(rows: Array<{
11
+ app: string;
12
+ uid: number;
13
+ }>): void;
14
+ create(app: string, uid: number): number;
15
+ delete(uid: number): void;
16
+ has(uid: number): boolean;
17
+ private write;
18
+ }
@@ -0,0 +1,7 @@
1
+ var h=Object.defineProperty;var r=(i,t)=>h(i,"name",{value:t,configurable:!0});import{readFileSync as a,writeFileSync as l,renameSync as f,openSync as w,closeSync as m,fchmodSync as y,constants as d}from"node:fs";import{APP_UID_MAX as _,APP_UID_MIN as g,LaunchRefused as o}from"./spec.js";function I(){const i=a("/etc/passwd","utf8").split(`
2
+ `).map(s=>s.split(":")),t=a("/etc/group","utf8").split(`
3
+ `).map(s=>s.split(":")),e=i.find(s=>s[0]==="crtrd"),n=t.find(s=>s[0]==="nl-data");if(!e||!n)throw new Error("crtrd user and nl-data group must exist");return{daemonUid:Number(e[2]),daemonGid:Number(e[3]),dataGid:Number(n[2])}}r(I,"systemIdentity");const $=/^[a-z0-9][a-z0-9-]{0,62}$/;function u(i,t){if(!$.test(i)||!Number.isInteger(t)||t<g||t>_)throw new o("invalid_uid","invalid app or uid")}r(u,"check");class b{static{r(this,"AppUsers")}dataGid;users=new Map;constructor(t){this.dataGid=t}sync(t){const e=new Map,n=new Set;for(const s of t){if(u(s.app,s.uid),e.has(s.uid)||n.has(s.app))throw new o("invalid_uid","duplicate app or uid");e.set(s.uid,s.app),n.add(s.app)}this.users=e,this.write()}create(t,e){if(u(t,e),this.users.has(e)&&this.users.get(e)!==t||[...this.users.values()].includes(t)&&this.users.get(e)!==t)throw new o("invalid_uid","app uid conflict");return this.users.set(e,t),this.write(),e}delete(t){if(!this.users.has(t))throw new o("invalid_uid","unknown app uid");this.users.delete(t),this.write()}has(t){return this.users.has(t)}write(){const t=a("/etc/passwd","utf8").split(`
4
+ `).filter(n=>n&&!/^nl-app-[a-z0-9-]+:/.test(n)),e=a("/etc/group","utf8").split(`
5
+ `).filter(n=>n&&!/^nl-app-[a-z0-9-]+:/.test(n));for(const[n,s]of this.users)t.push(`nl-app-${s}:x:${n}:${this.dataGid}:Northlight app:/apps/${s}/home:/bin/sh`),e.push(`nl-app-${s}:x:${n}:`);for(const[n,s]of[["/etc/passwd",t],["/etc/group",e]]){const c=`${n}.launcher-${process.pid}`,p=w(c,d.O_WRONLY|d.O_CREAT|d.O_EXCL,420);try{l(p,`${s.join(`
6
+ `)}
7
+ `),y(p,420)}finally{m(p)}f(c,n)}}}export{b as AppUsers,I as systemIdentity};
@@ -0,0 +1,22 @@
1
+ import { type LaunchSpec } from './spec.js';
2
+ export interface PinnedMount {
3
+ source: string;
4
+ writable: boolean;
5
+ fd: number;
6
+ kind: number;
7
+ }
8
+ export declare class SourceValidator {
9
+ private readonly daemonGid;
10
+ private readonly socketDir;
11
+ private readonly rootFd;
12
+ private readonly runtimeDev;
13
+ private readonly runtimeIno;
14
+ private readonly runtimeFd;
15
+ readonly root: string;
16
+ readonly runtime: string;
17
+ constructor(root: string, daemonGid?: number, socketDir?: string);
18
+ close(): void;
19
+ openLog(nodeId: string): number;
20
+ private isRuntimeAncestor;
21
+ pin(spec: LaunchSpec): PinnedMount[];
22
+ }
@@ -0,0 +1 @@
1
+ var R=Object.defineProperty;var h=(n,t)=>R(n,"name",{value:t,configurable:!0});import{chownSync as P,chmodSync as $,closeSync as l,constants as _,lstatSync as w,mkdirSync as O,openSync as E,realpathSync as A}from"node:fs";import{isAbsolute as G,join as e,relative as T,resolve as j,sep as L}from"node:path";import{loadLinuxNative as q,O_PATH as x,RESOLVE_BENEATH as z,RESOLVE_NO_SYMLINKS as V}from"../native/linux.js";import{APP_UID_MAX as W,APP_UID_MIN as Z,LaunchRefused as s}from"./spec.js";import{systemIdentity as S}from"./users.js";const a=q(),v=x|_.O_NOFOLLOW,g=z|V,M=32768,b=16384,F=49152;function c(n,t){return n===t||n.startsWith(t==="/"?"/":`${t}${L}`)}h(c,"within");function I(n){if(!G(n)||j(n)!==n||n.includes("\0")||n.split(L).includes(".."))throw new s("invalid_spec",`non-canonical source: ${n}`)}h(I,"assertPath");class Q{static{h(this,"SourceValidator")}daemonGid;socketDir;rootFd;runtimeDev;runtimeIno;runtimeFd;root;runtime;constructor(t,d=S().daemonGid,u="/run/crtr"){if(this.daemonGid=d,this.socketDir=u,!a)throw new Error("Linux native addon is required by the root launcher");this.root=A(t),this.runtime=A(e(this.root,"runtime")),this.rootFd=E("/",v),this.runtimeFd=E(this.runtime,v);const r=a.fstat(this.runtimeFd);this.runtimeDev=r.dev,this.runtimeIno=r.ino}close(){l(this.rootFd),l(this.runtimeFd)}openLog(t){if(!a)throw new Error("Linux native addon is required");return a.openat2(this.runtimeFd,`nodes/${t}/job/broker.log`,_.O_WRONLY|_.O_APPEND|_.O_NOFOLLOW,g)}isRuntimeAncestor(t){if(!a)throw new Error("Linux native addon is required");const d=t.split("/").filter(Boolean);for(let u=1;u<=d.length;u++){let r;try{r=a.openat2(this.rootFd,d.slice(0,u).join("/"),v,g)}catch{return!1}try{const m=a.fstat(r);if(m.dev===this.runtimeDev&&m.ino===this.runtimeIno)return!0}finally{l(r)}}return!1}pin(t){if(!a)throw new Error("Linux native addon is required");if(!Number.isInteger(t.uid)||t.uid<Z||t.uid>W)throw new s("invalid_uid","uid outside app range");if(!/^[a-zA-Z0-9][a-zA-Z0-9-]{0,127}$/.test(t.nodeId)||!Array.isArray(t.mounts)||!Array.isArray(t.command)||!t.command.length||!t.command.every(i=>typeof i=="string"&&i.length>0&&!i.includes("\0"))||!t.env||Object.entries(t.env).some(([i,o])=>!/^[A-Za-z_][A-Za-z0-9_]*$/.test(i)||typeof o!="string"||o.includes("\0")))throw new s("invalid_spec","invalid node id, command, environment or mount list");const d=e(this.socketDir,"nodes",t.nodeId),u=e(this.socketDir,"nodes");if(O(u,{recursive:!0,mode:493}),w(u).uid!==0||w(u).gid!==this.daemonGid||!w(u).isDirectory()||(w(u).mode&511)!==504)throw new s("run_source","nodes directory is not root-and-daemon-controlled");O(d,{recursive:!0,mode:504});const r=w(d);if(!r.isDirectory())throw new s("run_source","run folder is not a directory");if(r.uid===0||r.uid===S().daemonUid&&r.gid===this.daemonGid&&(r.mode&511)===504)P(d,t.uid,this.daemonGid),$(d,504);else if(r.uid!==t.uid||r.gid!==this.daemonGid||(r.mode&511)!==504)throw new s("run_source","run folder has wrong owner or mode");const m=[];try{for(const i of t.mounts){if(!i||typeof i.source!="string"||typeof i.writable!="boolean")throw new s("invalid_spec","invalid mount");const o=i.source;I(o);const p=t.pluginRoot===o&&!i.writable&&c(o,e(this.runtime,"plugins"))&&o!==e(this.runtime,"plugins");if(!p&&(c(o,this.runtime)||this.isRuntimeAncestor(o)))throw new s("runtime_source",o);const k=o===e(this.socketDir,"api.sock")||o===e(this.socketDir,"store.sock")||c(o,e(this.socketDir,"bin"))||o===d;if(c(o,this.socketDir)&&!k)throw new s("run_source",o);if(i.writable&&!c(o,e(this.root,"user"))&&!c(o,e(this.root,"apps"))&&o!==d&&o!==e(this.socketDir,"api.sock")&&o!==e(this.socketDir,"store.sock"))throw new s("writable_source",o);if(!c(o,e(this.root,"user"))&&!c(o,e(this.root,"apps"))&&!c(o,this.socketDir)&&!U(o)&&!p)throw new s("invalid_spec",`unknown read-only source: ${o}`);let f;try{f=a.openat2(this.rootFd,T("/",o)||".",v,g)}catch(D){const N=D.code;throw new s(N==="ENOENT"?"source_missing":"symlink_source",`${o}: ${String(D)}`)}const y=a.fstat(f).mode&61440;if(![M,b,F].includes(y)||y===F&&!k)throw l(f),new s(y===40960?"symlink_source":"source_type",o);m.push({source:o,writable:i.writable,fd:f,kind:y})}if(I(t.cwd),!m.some(i=>i.kind===b&&c(t.cwd,i.source)))throw new s("invalid_spec","cwd is not mounted");return m}catch(i){for(const o of m)l(o.fd);throw i}}}function U(n){return["/usr","/bin","/lib","/lib64","/opt/crouter","/etc/passwd","/etc/group","/etc/resolv.conf","/etc/hosts","/etc/ssl","/etc/ca-certificates"].some(t=>c(n,t))}h(U,"isSystemSource");export{Q as SourceValidator};
@@ -1,3 +1,3 @@
1
- var q=Object.defineProperty;var a=(t,s)=>q(t,"name",{value:s,configurable:!0});import{envProfileId as z}from"../shared/env.js";import{readdirSync as H}from"node:fs";import{dirname as j,join as T}from"node:path";import{nodesRoot as C}from"../core/canvas/paths.js";import{atomicWriteText as L,listDirs as Q,pathExists as x,realpathOrSelf as R,removePath as O,walkFiles as V}from"../core/fs-utils.js";import{memoryStoresInPrecedence as X}from"../core/memory-resolver.js";import{descendantStoreRootsExhaustive as Z}from"../core/nested-stores.js";import{profileMemoryDir as oo}from"../core/profiles/manifest.js";import{listInstalledPlugins as eo,listInstalledPluginsInRoot as to}from"../core/resolver.js";import{memoryDir as so}from"../core/runtime/memory.js";import{NEUTRAL_PROJECT_MEMORY as D,pluginMemoryDir as no,projectScopeRoots as _,scopeRoot as ro}from"../core/scope.js";import{CRTR_DIR_NAME as B}from"../types.js";import{foldDocChange as io,loadStoreSnapshot as ao}from"./convergent.js";import{STATE_MIGRATIONS as co}from"./registry.js";function po(t){return(t instanceof Error?t.message:String(t)).split(`
2
- `)[0]??""}a(po,"firstLine");function fo(t){return`${t.profileId??"-"}:${t.nodeId??"-"}:${R(t.cwd)}`}a(fo,"targetId");function uo(t){const s=no(t);return{scope:t.scope,storeRoot:s,namespace:t.name,plugin:t.name,mountStatus:x(s)?"ready":"absent",projectMemory:D}}a(uo,"pluginStoreDescriptor");function lo(t){return{scope:"node",storeRoot:t,namespace:"",mountStatus:x(t)?"ready":"absent",projectMemory:D}}a(lo,"nodeStoreDescriptor");function mo(){const t=[];for(const s of Q(C())){const r=so(s);if(!x(r))continue;V(r,d=>d.endsWith(".md")&&d!=="SKILL.md",d=>d.startsWith(".")).length>0&&t.push({nodeId:s,storeRoot:r})}return t}a(mo,"nodeStoresWithDocs");async function Co(t){const s=R(t.cwd??process.cwd()),r=z()||null,c=t.explicitDirs??[],d=[],m=new Set,u=a(o=>{const e=`${o.reason}\0${R(o.root)}\0${o.detail??""}`;m.has(e)||(m.add(e),d.push(o))},"addRoot"),y=new Map,v=a((o,e,n)=>{const f=R(o);let p=y.get(f);p===void 0&&(p={root:o,reason:e,profileIds:[]},y.set(f,p)),p.profileIds.includes(n)||p.profileIds.push(n)},"addProjectRoot"),P=[{reason:"cwd-ancestor",profileId:r,roots:_(s,r)},...t.profiles.map(({profileId:o,manifest:e})=>({reason:"profile-project",profileId:o,detail:o,roots:[...new Set(e.projects.flatMap(n=>[T(n.path,B),..._(n.path,null)]))]})),...c.map(o=>({reason:"explicit-dir",profileId:r,detail:o,roots:[T(R(o),B)]}))],S=new Map,b=a(o=>{const e=o.map(f=>R(f)).sort().join(`
3
- `);let n=S.get(e);return n===void 0&&(n=Z([...o]),S.set(e,n)),n},"descendantsUnder"),$=a((o,e,n,f)=>{const p=f===void 0?{}:{detail:f};for(const h of o)u({reason:e,root:h,boundary:e==="explicit-dir"?"store":"ancestors",...p}),v(h,e,n);for(const h of b(o))u({reason:"descendant",root:h,boundary:"descendants",...p}),v(h,"descendant",n)},"expandRoots");for(const o of P)$(o.roots,o.reason,o.profileId,o.detail);const I=[],k=new Map,w=a((o,e,n)=>{const f=o.storeRoot;if(f===""||!x(f))return;const p=R(f);let h=k.get(p);if(h===void 0){h={key:p,descriptor:o,discovery:[],discoverySeen:new Set,targets:[],writable:o.scope!=="builtin"},k.set(p,h);try{H(p)}catch(J){I.push({kind:"inaccessible-root",message:`memory store cannot be listed (${po(J)}) \u2014 discovery cannot see its documents; fix the permissions and re-run`,storeRoot:p})}}const A=`${e.reason}\0${e.root}\0${e.targetId??""}`;h.discoverySeen.has(A)||(h.discoverySeen.add(A),h.discovery.push(e)),n!==void 0&&(h.targets.includes(n.id)||h.targets.push(n.id),n.storeKeys.includes(p)||n.storeKeys.push(p))},"register"),i=[],l=new Map,M=a((o,e,n)=>{const f=fo(n);if(l.has(f))return;const p={id:f,kind:o,origin:e,target:n,storeKeys:[]};l.set(f,p),i.push(p)},"addTarget");M("cwd",s,{cwd:s,profileId:r,nodeId:null});for(const{profileId:o,manifest:e}of t.profiles){const n=e.home!==null&&e.home!==""?e.home:null;M("profile",o,{cwd:n??e.projects[0]?.path??s,profileId:o,nodeId:null})}const g=a(()=>{for(const{root:o,profileIds:e}of[...y.values()])for(const n of[...e])M("project",j(o),{cwd:j(o),profileId:n,nodeId:null})},"addProjectTargets"),U=mo();x(C())&&u({reason:"node",root:C(),boundary:"nodes"});const Y=new Map(t.nodes.map(o=>[o.nodeId,o]));for(const{nodeId:o,storeRoot:e}of U){const n=Y.get(o);if(n===void 0||n.cwd===""){const f=n===void 0?"no row":"empty cwd";I.push({kind:"inaccessible-target",message:`node ${o} holds memory documents but canvas.db has no usable row for it (${f}) \u2014 the corpus cannot resolve its project or profile`,storeRoot:R(e)}),w(lo(e),{reason:"node",root:e});continue}M("node",o,{cwd:n.cwd,profileId:n.profileId,nodeId:o})}const G=a(o=>{for(const e of X(o.target)){if(e.plugin!==void 0){u({reason:"plugin",root:e.storeRoot,boundary:"store",detail:e.plugin}),w(e,{reason:"plugin",root:e.storeRoot,targetId:o.id},o);continue}if(e.scope==="project"){const f=j(e.storeRoot),p=y.get(R(f));p===void 0&&$([f],"cwd-ancestor",o.target.profileId,o.id),w(e,{reason:p?.reason??"cwd-ancestor",root:f,targetId:o.id},o);continue}const n=e.scope==="user"?"user":e.scope==="profile"?"profile":e.scope==="node"?"node":"builtin";u({reason:n,root:e.storeRoot,boundary:"store"}),w(e,{reason:n,root:e.storeRoot,targetId:o.id},o)}},"walkTarget"),E=new Set;for(;;){g();const o=i.filter(e=>!E.has(e.id));if(o.length===0)break;for(const e of o)E.add(e.id),G(e)}const K=ro("user");K!==null&&u({reason:"plugin",root:K,boundary:"plugins"});const W=[...eo("user")];for(const{root:o}of y.values())u({reason:"plugin",root:o,boundary:"plugins"}),W.push(...to("project",o));for(const o of W){const e=uo(o);u({reason:"plugin",root:e.storeRoot,boundary:"store",detail:o.name}),w(e,{reason:"plugin",root:e.storeRoot})}for(const{profileId:o}of t.profiles){const e=oo(o);u({reason:"profile",root:e,boundary:"store",detail:o}),w({scope:"profile",storeRoot:e,namespace:"",mountStatus:x(e)?"ready":"absent",projectMemory:D},{reason:"profile",root:e})}return{roots:d,stores:[...k.values()].map(o=>({key:o.key,descriptor:o.descriptor,discovery:o.discovery,targets:o.targets,writable:o.writable})),targets:i.map(o=>({id:o.id,kind:o.kind,origin:o.origin,target:o.target,storeKeys:o.storeKeys})),blockers:I}}a(Co,"discoverCorpus");function Do(t,s={}){const r=new Map,c=[];for(const d of t.stores){const m=s.preloaded?.get(d.key);if(m!==void 0){r.set(d.key,m);continue}const u=ao(d.descriptor.storeRoot);r.set(d.key,u.snapshot);for(const y of u.skipped)c.push({storeRoot:d.key,...y})}return{snapshots:r,skipped:c}}a(Do,"loadCorpusSnapshots");function Eo(t){return t.map(s=>({kind:"parse-failure",message:`${s.relPath}: frontmatter is not valid YAML (${s.error}) \u2014 the document's identity cannot be read; fix the file and re-run`,storeRoot:s.storeRoot,path:T(s.storeRoot,s.relPath)}))}a(Eo,"parseFailureBlockers");function F(t,s,r){const c=new Map(t.map(m=>[m.key,m])),d=new Map(s.map(m=>[m.id,m]));return{stores:t,targets:s,roots:r,store:a(m=>c.get(m),"store"),storesForTarget:a(m=>(d.get(m)?.storeKeys??[]).map(u=>c.get(u)).filter(u=>u!==void 0),"storesForTarget")}}a(F,"makeCorpusSnapshot");function Ko(t,s){const r=t.stores.map(c=>({...c,snapshot:s.get(c.key)??{root:c.descriptor.storeRoot,docs:[]}}));return F(r,t.targets,t.roots)}a(Ko,"buildCorpusSnapshot");function ho(t){const s=t.stores.map(r=>({...r,snapshot:{root:r.snapshot.root,docs:[...r.snapshot.docs]}}));return F(s,t.targets,t.roots)}a(ho,"cloneCorpus");function N(t,s,r=new Set){let c;for(const d of t.stores)s.path.startsWith(`${d.snapshot.root}/`)&&(c===void 0||d.snapshot.root.length>c.snapshot.root.length)&&(c=d);if(c===void 0){if(r.has(s.path))return;throw new Error(`corpus migration: planned change outside every discovered store: ${s.path}`)}io(c.snapshot,s)}a(N,"foldCorpusChange");function Wo(t,s={}){const r=(s.migrations??co).filter(i=>i.lane==="corpus"),c=[...s.blockers??[]],d=[],m=[],u=[],y=[],v=[],P=[],S=[],b=a((i,l)=>({migrations:r.length,blocked:c.length>0&&r.length>0,blockers:c,planned:d,repositories:m,storePrefixes:u,renames:y,references:v,wrote:l,verified:i}),"result"),$={consumers:[],identities:[]};if(r.length===0)return b(!1,$);const I=ho(t);for(const i of r){const l=i.plan(I);c.push(...l.blockers),m.push(...l.repositories),u.push(...l.storePrefixes),y.push(...l.renames),v.push(...l.references);for(const g of l.consumers)N(I,g);const M=new Set(l.repositories.map(g=>g.declarationPath));for(const g of l.identities)N(I,g,M);P.push(...l.consumers),S.push(...l.identities),d.push({migration:i.description,consumers:l.consumers.map(g=>g.path),identities:l.identities.map(g=>g.path)})}const k={consumers:P.map(i=>i.path),identities:S.map(i=>i.path)};if(c.length>0)return b(!1,$);if(s.dryRun===!0)return b(!1,k);for(const i of P)i.after===null?O(i.path):L(i.path,i.after);for(const i of S)i.after===null?O(i.path):L(i.path,i.after);if(s.rebuild===void 0)return b(!1,k);const w=s.rebuild();for(const i of r)for(const l of i.verify?.(w)??[])c.push({...l,kind:"verification"});return b(!0,k)}a(Wo,"runCorpusMigrations");export{Ko as buildCorpusSnapshot,Co as discoverCorpus,Do as loadCorpusSnapshots,Eo as parseFailureBlockers,Wo as runCorpusMigrations};
1
+ var z=Object.defineProperty;var c=(t,n)=>z(t,"name",{value:n,configurable:!0});import{envProfileId as H}from"../shared/env.js";import{readdirSync as Q}from"node:fs";import{dirname as C,join as x}from"node:path";import{appsRoot as T,appSpace as V}from"../core/layout.js";import{atomicWriteText as L,listDirs as O,pathExists as v,realpathOrSelf as R,removePath as _,walkFiles as X}from"../core/fs-utils.js";import{memoryStoresInPrecedence as Z}from"../core/memory-resolver.js";import{descendantStoreRootsExhaustive as oo}from"../core/nested-stores.js";import{profileMemoryDir as eo}from"../core/profiles/manifest.js";import{memoryDir as to}from"../core/runtime/memory.js";import{listInstalledPlugins as so,listInstalledPluginsInRoot as no}from"../core/resolver.js";import{NEUTRAL_PROJECT_MEMORY as D,pluginMemoryDir as ro,projectScopeRoots as B,scopeRoot as io}from"../core/scope.js";import{CRTR_DIR_NAME as F}from"../types.js";import{foldDocChange as ao,loadStoreSnapshot as co}from"./convergent.js";import{STATE_MIGRATIONS as po}from"./registry.js";function fo(t){return(t instanceof Error?t.message:String(t)).split(`
2
+ `)[0]??""}c(fo,"firstLine");function uo(t){return`${t.profileId??"-"}:${t.nodeId??"-"}:${R(t.cwd)}`}c(uo,"targetId");function lo(t){const n=ro(t);return{scope:t.scope,storeRoot:n,namespace:t.name,plugin:t.name,mountStatus:v(n)?"ready":"absent",projectMemory:D}}c(lo,"pluginStoreDescriptor");function mo(t){return{scope:"node",storeRoot:t,namespace:"",mountStatus:v(t)?"ready":"absent",projectMemory:D}}c(mo,"nodeStoreDescriptor");function ho(){const t=[];for(const n of O(T()))for(const r of O(x(T(),n,"memory","nodes"))){const i=x(T(),n,"memory","nodes",r);if(!v(i))continue;X(i,d=>d.endsWith(".md")&&d!=="SKILL.md",d=>d.startsWith(".")).length>0&&t.push({nodeId:r,storeRoot:i})}return t}c(ho,"nodeStoresWithDocs");async function Do(t){const n=R(t.cwd??process.cwd()),r=H()||null,i=t.explicitDirs??[],m=[],d=new Set,u=c(o=>{const e=`${o.reason}\0${R(o.root)}\0${o.detail??""}`;d.has(e)||(d.add(e),m.push(o))},"addRoot"),y=new Map,P=c((o,e,s)=>{const f=R(o);let p=y.get(f);p===void 0&&(p={root:o,reason:e,profileIds:[]},y.set(f,p)),p.profileIds.includes(s)||p.profileIds.push(s)},"addProjectRoot"),$=[{reason:"cwd-ancestor",profileId:r,roots:B(n,r)},...t.profiles.map(({profileId:o,manifest:e})=>({reason:"profile-project",profileId:o,detail:o,roots:[...new Set(e.projects.flatMap(s=>[x(s.path,F),...B(s.path,null)]))]})),...i.map(o=>({reason:"explicit-dir",profileId:r,detail:o,roots:[x(R(o),F)]}))],S=new Map,b=c(o=>{const e=o.map(f=>R(f)).sort().join(`
3
+ `);let s=S.get(e);return s===void 0&&(s=oo([...o]),S.set(e,s)),s},"descendantsUnder"),j=c((o,e,s,f)=>{const p=f===void 0?{}:{detail:f};for(const h of o)u({reason:e,root:h,boundary:e==="explicit-dir"?"store":"ancestors",...p}),P(h,e,s);for(const h of b(o))u({reason:"descendant",root:h,boundary:"descendants",...p}),P(h,"descendant",s)},"expandRoots");for(const o of $)j(o.roots,o.reason,o.profileId,o.detail);const I=[],k=new Map,w=c((o,e,s)=>{const f=o.storeRoot;if(f===""||!v(f))return;const p=R(f);let h=k.get(p);if(h===void 0){h={key:p,descriptor:o,discovery:[],discoverySeen:new Set,targets:[],writable:o.scope!=="builtin"},k.set(p,h);try{Q(p)}catch(q){I.push({kind:"inaccessible-root",message:`memory store cannot be listed (${fo(q)}) \u2014 discovery cannot see its documents; fix the permissions and re-run`,storeRoot:p})}}const A=`${e.reason}\0${e.root}\0${e.targetId??""}`;h.discoverySeen.has(A)||(h.discoverySeen.add(A),h.discovery.push(e)),s!==void 0&&(h.targets.includes(s.id)||h.targets.push(s.id),s.storeKeys.includes(p)||s.storeKeys.push(p))},"register"),a=[],l=new Map,M=c((o,e,s)=>{const f=uo(s);if(l.has(f))return;const p={id:f,kind:o,origin:e,target:s,storeKeys:[]};l.set(f,p),a.push(p)},"addTarget");M("cwd",n,{cwd:n,profileId:r,nodeId:null});for(const{profileId:o,manifest:e}of t.profiles)M("profile",o,{cwd:e.projects[0]?.path??n,profileId:o,nodeId:null});const g=c(()=>{for(const{root:o,profileIds:e}of[...y.values()])for(const s of[...e])M("project",C(o),{cwd:C(o),profileId:s,nodeId:null})},"addProjectTargets"),Y=ho();v(T())&&u({reason:"node",root:T(),boundary:"nodes"});const G=new Map(t.nodes.map(o=>[o.nodeId,o]));for(const{nodeId:o,storeRoot:e}of Y){const s=G.get(o);if(s===void 0||s.cwd===""||to(o,s.grantee)!==e){const f=s===void 0?"no row":s.cwd===""?"empty cwd":"app assignment differs from folder";I.push({kind:"inaccessible-target",message:`node ${o} holds memory documents but canvas.db has no matching app assignment and usable row for it (${f}) \u2014 the corpus cannot resolve its project or profile`,storeRoot:R(e)}),w(mo(e),{reason:"node",root:e});continue}M("node",o,{cwd:s.cwd,profileId:s.profileId,nodeId:o,grantee:s.grantee})}const J=c(o=>{for(const e of Z(o.target)){if(e.plugin!==void 0){u({reason:"plugin",root:e.storeRoot,boundary:"store",detail:e.plugin}),w(e,{reason:"plugin",root:e.storeRoot,targetId:o.id},o);continue}if(e.scope==="project"){const f=C(e.storeRoot),p=y.get(R(f));p===void 0&&j([f],"cwd-ancestor",o.target.profileId,o.id),w(e,{reason:p?.reason??"cwd-ancestor",root:f,targetId:o.id},o);continue}const s=e.scope==="user"?"user":e.scope==="profile"?"profile":e.scope==="node"?"node":"builtin";u({reason:s,root:e.storeRoot,boundary:"store"}),w(e,{reason:s,root:e.storeRoot,targetId:o.id},o)}},"walkTarget"),E=new Set;for(;;){g();const o=a.filter(e=>!E.has(e.id));if(o.length===0)break;for(const e of o)E.add(e.id),J(e)}const K=io("user");K!==null&&u({reason:"plugin",root:K,boundary:"plugins"});const W=[...so("user")];for(const{root:o}of y.values())u({reason:"plugin",root:o,boundary:"plugins"}),W.push(...no("project",o));for(const o of W){const e=lo(o);u({reason:"plugin",root:e.storeRoot,boundary:"store",detail:o.name}),w(e,{reason:"plugin",root:e.storeRoot})}for(const{profileId:o,manifest:e}of t.profiles){const s=e.grantee?.startsWith("app:")?x(V(e.grantee).memory,"profiles",o):eo(o);u({reason:"profile",root:s,boundary:"store",detail:o}),w({scope:"profile",storeRoot:s,namespace:"",mountStatus:v(s)?"ready":"absent",projectMemory:D},{reason:"profile",root:s})}return{roots:m,stores:[...k.values()].map(o=>({key:o.key,descriptor:o.descriptor,discovery:o.discovery,targets:o.targets,writable:o.writable})),targets:a.map(o=>({id:o.id,kind:o.kind,origin:o.origin,target:o.target,storeKeys:o.storeKeys})),blockers:I}}c(Do,"discoverCorpus");function Eo(t,n={}){const r=new Map,i=[];for(const m of t.stores){const d=n.preloaded?.get(m.key);if(d!==void 0){r.set(m.key,d);continue}const u=co(m.descriptor.storeRoot);r.set(m.key,u.snapshot);for(const y of u.skipped)i.push({storeRoot:m.key,...y})}return{snapshots:r,skipped:i}}c(Eo,"loadCorpusSnapshots");function Ko(t){return t.map(n=>({kind:"parse-failure",message:`${n.relPath}: frontmatter is not valid YAML (${n.error}) \u2014 the document's identity cannot be read; fix the file and re-run`,storeRoot:n.storeRoot,path:x(n.storeRoot,n.relPath)}))}c(Ko,"parseFailureBlockers");function N(t,n,r){const i=new Map(t.map(d=>[d.key,d])),m=new Map(n.map(d=>[d.id,d]));return{stores:t,targets:n,roots:r,store:c(d=>i.get(d),"store"),storesForTarget:c(d=>(m.get(d)?.storeKeys??[]).map(u=>i.get(u)).filter(u=>u!==void 0),"storesForTarget")}}c(N,"makeCorpusSnapshot");function Wo(t,n){const r=t.stores.map(i=>({...i,snapshot:n.get(i.key)??{root:i.descriptor.storeRoot,docs:[]}}));return N(r,t.targets,t.roots)}c(Wo,"buildCorpusSnapshot");function go(t){const n=t.stores.map(r=>({...r,snapshot:{root:r.snapshot.root,docs:[...r.snapshot.docs]}}));return N(n,t.targets,t.roots)}c(go,"cloneCorpus");function U(t,n,r=new Set){let i;for(const m of t.stores)n.path.startsWith(`${m.snapshot.root}/`)&&(i===void 0||m.snapshot.root.length>i.snapshot.root.length)&&(i=m);if(i===void 0){if(r.has(n.path))return;throw new Error(`corpus migration: planned change outside every discovered store: ${n.path}`)}ao(i.snapshot,n)}c(U,"foldCorpusChange");function Ao(t,n={}){const r=(n.migrations??po).filter(a=>a.lane==="corpus"),i=[...n.blockers??[]],m=[],d=[],u=[],y=[],P=[],$=[],S=[],b=c((a,l)=>({migrations:r.length,blocked:i.length>0&&r.length>0,blockers:i,planned:m,repositories:d,storePrefixes:u,renames:y,references:P,wrote:l,verified:a}),"result"),j={consumers:[],identities:[]};if(r.length===0)return b(!1,j);const I=go(t);for(const a of r){const l=a.plan(I);i.push(...l.blockers),d.push(...l.repositories),u.push(...l.storePrefixes),y.push(...l.renames),P.push(...l.references);for(const g of l.consumers)U(I,g);const M=new Set(l.repositories.map(g=>g.declarationPath));for(const g of l.identities)U(I,g,M);$.push(...l.consumers),S.push(...l.identities),m.push({migration:a.description,consumers:l.consumers.map(g=>g.path),identities:l.identities.map(g=>g.path)})}const k={consumers:$.map(a=>a.path),identities:S.map(a=>a.path)};if(i.length>0)return b(!1,j);if(n.dryRun===!0)return b(!1,k);for(const a of $)a.after===null?_(a.path):L(a.path,a.after);for(const a of S)a.after===null?_(a.path):L(a.path,a.after);if(n.rebuild===void 0)return b(!1,k);const w=n.rebuild();for(const a of r)for(const l of a.verify?.(w)??[])i.push({...l,kind:"verification"});return b(!0,k)}c(Ao,"runCorpusMigrations");export{Wo as buildCorpusSnapshot,Do as discoverCorpus,Eo as loadCorpusSnapshots,Ko as parseFailureBlockers,Ao as runCorpusMigrations};
@@ -1 +1 @@
1
- var R=Object.defineProperty;var h=(n,s)=>R(n,"name",{value:s,configurable:!0});import{profilesRoot as v,withProfileManifestLock as y}from"../core/profiles/manifest.js";import{resetScopeCache as P}from"../core/scope.js";import{buildCorpusSnapshot as w,discoverCorpus as C,loadCorpusSnapshots as b,parseFailureBlockers as x,runCorpusMigrations as S}from"./corpus.js";import{runConvergentMigrations as D}from"./convergent.js";import{runProfileManifestMigrations as $}from"./profile-manifests.js";async function J(n){const s=n.dryRun===!0,t=[],f=[],p=v(),a=$(p,{dryRun:s,withLock:y}),u=[];for(const e of a.applied)t.push({store:p,lane:"profile-manifest",migration:e.migration,files:[e.path]});for(const e of a.skipped){const r=`${e.profileId}/profile.json`;f.push({store:p,relPath:r,error:e.error}),u.push({kind:"parse-failure",message:`${e.path}: profile manifest is not valid JSON (${e.error}) \u2014 its projects cannot be discovered; fix the file and re-run \`crtr sys migrate\``,storeRoot:p,path:e.path})}P();const i=await C({profiles:a.snapshots,explicitDirs:n.explicitDirs,nodes:n.nodes}),c=[],m=new Map;for(const e of i.stores){if(!e.writable)continue;const r=D(e.descriptor.storeRoot,{dryRun:s});m.set(e.key,r.snapshot);for(const l of r.applied)t.push({store:e.key,lane:"convergent",migration:l.migration,files:l.files});for(const l of r.skipped)c.push({storeRoot:e.key,...l})}const d=b(i,{preloaded:m});c.push(...d.skipped);for(const e of c)f.push({store:e.storeRoot,relPath:e.relPath,error:e.error});const o=S(w(i,d.snapshots),{dryRun:s,blockers:[...u,...i.blockers,...x(c)],rebuild:h(()=>w(i,b(i).snapshots),"rebuild")}),g=o.wrote.consumers.length>0||o.wrote.identities.length>0;if(g)for(const e of o.planned){const r=[...e.consumers,...e.identities];r.length>0&&t.push({store:"corpus",lane:"corpus",migration:e.migration,files:r})}const M=s?"planned":g?"written":"not-started",k=u.length>0||o.blocked;return{profiles:a.profiles,discovery:i,snapshots:d.snapshots,changed:t.reduce((e,r)=>e+r.files.length,0),applied:t,skipped:f,blocked:k,blockers:o.blockers,corpusPhase:M,wrote:{profileManifests:t.filter(e=>e.lane==="profile-manifest").flatMap(e=>e.files),documents:t.filter(e=>e.lane==="convergent").flatMap(e=>e.files),corpusConsumers:o.wrote.consumers,corpusIdentities:o.wrote.identities},repositories:o.repositories,storePrefixes:o.storePrefixes,renames:o.renames,references:o.references,finalVerificationSucceeded:o.verified&&!k,dryRun:s}}h(J,"runOnDiskMigrations");export{J as runOnDiskMigrations};
1
+ var b=Object.defineProperty;var l=(n,t)=>b(n,"name",{value:t,configurable:!0});import{profileSpace as y}from"../core/layout.js";import{listStoredProfiles as C}from"../core/scoped-state/profiles.js";import{resetScopeCache as R,userScopeRoot as S}from"../core/scope.js";import{buildCorpusSnapshot as g,discoverCorpus as v,loadCorpusSnapshots as k,parseFailureBlockers as M,runCorpusMigrations as P}from"./corpus.js";import{runConvergentMigrations as x}from"./convergent.js";async function j(n){const t=n.dryRun===!0,i=[],u=[],f=C(S()).map(({profileId:e,manifest:r})=>({profileId:e,manifest:r,path:y(r.grantee??"app:terminal",e).memory}));R();const s=await v({profiles:f,explicitDirs:n.explicitDirs,nodes:n.nodes}),p=[],d=new Map;for(const e of s.stores){if(!e.writable)continue;const r=x(e.descriptor.storeRoot,{dryRun:t});d.set(e.key,r.snapshot);for(const c of r.applied)i.push({store:e.key,lane:"convergent",migration:c.migration,files:c.files});for(const c of r.skipped)p.push({storeRoot:e.key,...c})}const a=k(s,{preloaded:d});p.push(...a.skipped);for(const e of p)u.push({store:e.storeRoot,relPath:e.relPath,error:e.error});const o=P(g(s,a.snapshots),{dryRun:t,blockers:[...s.blockers,...M(p)],rebuild:l(()=>g(s,k(s).snapshots),"rebuild")}),m=o.wrote.consumers.length>0||o.wrote.identities.length>0;if(m)for(const e of o.planned){const r=[...e.consumers,...e.identities];r.length>0&&i.push({store:"corpus",lane:"corpus",migration:e.migration,files:r})}const w=t?"planned":m?"written":"not-started",h=o.blocked;return{profiles:f.length,discovery:s,snapshots:a.snapshots,changed:i.reduce((e,r)=>e+r.files.length,0),applied:i,skipped:u,blocked:h,blockers:o.blockers,corpusPhase:w,wrote:{profileManifests:[],documents:i.filter(e=>e.lane==="convergent").flatMap(e=>e.files),corpusConsumers:o.wrote.consumers,corpusIdentities:o.wrote.identities},repositories:o.repositories,storePrefixes:o.storePrefixes,renames:o.renames,references:o.references,finalVerificationSucceeded:o.verified&&!h,dryRun:t}}l(j,"runOnDiskMigrations");export{j as runOnDiskMigrations};
Binary file
@@ -0,0 +1,29 @@
1
+ import type { Socket } from 'node:net';
2
+ export interface LinuxNative {
3
+ peerCred(fd: number): {
4
+ pid: number;
5
+ uid: number;
6
+ gid: number;
7
+ };
8
+ openat2(dirfd: number, path: string, flags: number, resolve: number): number;
9
+ fdPath(fd: number): string;
10
+ fstat(fd: number): {
11
+ uid: number;
12
+ gid: number;
13
+ mode: number;
14
+ nlink: number;
15
+ dev: bigint;
16
+ ino: bigint;
17
+ };
18
+ sendFds(socketFd: number, data: string, fds: number[]): void;
19
+ recvFds(socketFd: number): {
20
+ data: string;
21
+ fds: number[];
22
+ };
23
+ }
24
+ export declare const O_PATH = 2097152;
25
+ export declare const O_CLOEXEC = 524288;
26
+ export declare const RESOLVE_NO_SYMLINKS = 4;
27
+ export declare const RESOLVE_BENEATH = 8;
28
+ export declare function loadLinuxNative(): LinuxNative | undefined;
29
+ export declare function peerUid(socket: Socket): number;
@@ -0,0 +1 @@
1
+ var o=Object.defineProperty;var n=(r,e)=>o(r,"name",{value:e,configurable:!0});import{createRequire as i}from"node:module";const x=2097152,p=524288,c=4,f=8;function u(){if(process.platform==="linux")return i(import.meta.url)("./linux/addon.node")}n(u,"loadLinuxNative");function l(r){const e=r._handle?.fd;if(e===void 0||e<0)throw new Error("unix socket peer fd is unavailable");const t=u();if(!t)throw new Error("Linux peer credentials are unavailable");return t.peerCred(e).uid}n(l,"peerUid");export{p as O_CLOEXEC,x as O_PATH,f as RESOLVE_BENEATH,c as RESOLVE_NO_SYMLINKS,u as loadLinuxNative,l as peerUid};
@@ -1,2 +1,2 @@
1
- var l=Object.defineProperty;var r=(e,t)=>l(e,"name",{value:t,configurable:!0});import{envHomeOverride as h}from"../shared/env.js";import{existsSync as d,mkdirSync as b,readFileSync as p,writeFileSync as y}from"node:fs";import{homedir as N}from"node:os";import{join as c}from"node:path";import{CRTR_DIR_NAME as v}from"../types.js";import{brokerExtensionState as x,commitBrokerGeneratedName as f}from"../core/runtime/broker/daemon-ops.js";import{publishNodeNamed as L}from"../core/runtime/broker/node-named.js";import{headlessName as S,headlessNameFromConversation as k,sanitizeSessionName as F,sanitizeSessionTitle as R,slugFromPrompt as A,titleFromPrompt as C}from"../core/runtime/naming.js";function s(e){if(e===""||e==="."||e===".."||/[\\/\0]/u.test(e))throw new TypeError("node_id must be a non-empty path segment");const t=h()?.trim()||c(N(),v,"canvas");return c(t,"nodes",e,"context")}r(s,"contextDir");function P(e,t){const o=s(e),n=c(o,"initial-prompt.md");if(d(n)&&p(n,"utf8").trim()!=="")return!1;const i=t.trim();return i===""?!1:(b(o,{recursive:!0}),y(n,`${i}
2
- `,"utf8"),!0)}r(P,"captureGoalIfAbsent");function j(e){const t=c(s(e),"roadmap.md");return d(t)?p(t,"utf8"):null}r(j,"readRoadmap");function u(e,t){return{description:F(t.name)||A(e),title:R(t.title)||C(e),icon:t.icon}}r(u,"generatedLabel");function B(e,t,o){const n=t.trim();n!==""&&x(e).then(i=>{if((i.node.description??"").trim()==="")return S(n).then(m=>f(e,{kind:"initial",...u(n,m)}))}).then(i=>{!i?.applied||i.editorLabel===void 0||(L({description:i.description??"",title:i.title??"",icon:i.icon??"",editorLabel:i.editorLabel}),o?.(i.editorLabel))}).catch(()=>{})}r(B,"generateAndCommitInitialName");function M(e,t,o,n,i){const m=t.trim();m!==""&&k(m).then(a=>{if(n())return f(e,{kind:"recap",...u(m,a),expected:o})}).then(a=>{a?.applied&&a.editorLabel!==void 0&&i?.(a.editorLabel)}).catch(()=>{})}r(M,"generateAndCommitRecapName");export{P as captureGoalIfAbsent,B as generateAndCommitInitialName,M as generateAndCommitRecapName,j as readRoadmap};
1
+ var s=Object.defineProperty;var o=(i,e)=>s(i,"name",{value:e,configurable:!0});import{existsSync as d,mkdirSync as b,readFileSync as c,writeFileSync as h}from"node:fs";import{join as p}from"node:path";import{contextDir as f}from"../core/canvas/paths.js";import{brokerExtensionState as N,commitBrokerGeneratedName as u}from"../core/runtime/broker/daemon-ops.js";import{publishNodeNamed as x}from"../core/runtime/broker/node-named.js";import{headlessName as y,headlessNameFromConversation as L,sanitizeSessionName as S,sanitizeSessionTitle as k,slugFromPrompt as F,titleFromPrompt as v}from"../core/runtime/naming.js";function j(i,e){const r=f(i),n=p(r,"initial-prompt.md");if(d(n)&&c(n,"utf8").trim()!=="")return!1;const t=e.trim();return t===""?!1:(b(r,{recursive:!0}),h(n,`${t}
2
+ `,"utf8"),!0)}o(j,"captureGoalIfAbsent");function w(i){const e=p(f(i),"roadmap.md");return d(e)?c(e,"utf8"):null}o(w,"readRoadmap");function l(i,e){return{description:S(e.name)||F(i),title:k(e.title)||v(i),icon:e.icon}}o(l,"generatedLabel");function B(i,e,r){const n=e.trim();n!==""&&N(i).then(t=>{if((t.node.description??"").trim()==="")return y(n).then(a=>u(i,{kind:"initial",...l(n,a)}))}).then(t=>{!t?.applied||t.editorLabel===void 0||(x({description:t.description??"",title:t.title??"",icon:t.icon??"",editorLabel:t.editorLabel}),r?.(t.editorLabel))}).catch(()=>{})}o(B,"generateAndCommitInitialName");function D(i,e,r,n,t){const a=e.trim();a!==""&&L(a).then(m=>{if(n())return u(i,{kind:"recap",...l(a,m),expected:r})}).then(m=>{m?.applied&&m.editorLabel!==void 0&&t?.(m.editorLabel)}).catch(()=>{})}o(D,"generateAndCommitRecapName");export{j as captureGoalIfAbsent,B as generateAndCommitInitialName,D as generateAndCommitRecapName,w as readRoadmap};
@@ -1,7 +1,6 @@
1
+ export { MAX_BACKGROUND_BASH_LOG_BYTES, BACKGROUND_BASH_LOG_TRUNCATION_MARKER } from '../core/bash-job-supervisor.js';
1
2
  import { createBashToolDefinition, type BashOperations } from '@earendil-works/pi-coding-agent';
2
3
  import type { ExtensionAPI } from '@earendil-works/pi-coding-agent';
3
- export declare const MAX_BACKGROUND_BASH_LOG_BYTES: number;
4
- export declare const BACKGROUND_BASH_LOG_TRUNCATION_MARKER = "\n[background bash job output truncated at 10 MiB; remaining output discarded]\n";
5
4
  /** The valve's BashOperations backend. Each tool execution closes over its own
6
5
  * `takePurpose` and its own preview-result path, so concurrent calls cannot
7
6
  * exchange labels or result mirrors. The purpose is consumed even when the
@@ -15,4 +14,3 @@ type BashToolDefinition = ReturnType<typeof createBashToolDefinition>;
15
14
  * the model receives pi's upstream bash schema verbatim. */
16
15
  export declare function createValveToolDefinition(nodeId: string, contextDir: string, cwd: string, exposePurpose: boolean): BashToolDefinition;
17
16
  export default function (pi: ExtensionAPI): void;
18
- export {};
@@ -1,7 +1,4 @@
1
- var ne=Object.defineProperty;var t=(n,r)=>ne(n,"name",{value:r,configurable:!0});import{envBashAutoBgDeadlineMs as re,envBashValveMs as te,envNodeId as oe}from"../shared/env.js";import{spawn as ie}from"node:child_process";import{closeSync as se,existsSync as S,mkdirSync as U,openSync as ae,readFileSync as ce,readSync as de,rmSync as F,statSync as G,writeFileSync as g}from"node:fs";import{homedir as ue}from"node:os";import{dirname as fe}from"node:path";import{performance as _}from"node:perf_hooks";import{backgroundBashJob as H,bashJobPaths as le,cancelBashJobProcessTree as V,formatBashElapsed as K,newBashJobId as pe,normalizeBashJobPurpose as be,readBashNiceness as he,writeJobDeadlineMs as me}from"../core/bash-jobs.js";import{bashCommandRefusal as ge}from"../core/bash-guard.js";import{capturePidIdentities as $e}from"../core/canvas/pid.js";import{readConfig as we}from"../core/config.js";import{PREVIEW_RESULT_PATH_ENV as Se,previewResultPath as ye}from"../core/preview-result-path.js";import{resolveAdmittedHostCommand as Ee}from"../core/runtime/spawn-env.js";import{Type as C}from"typebox";import{createBashToolDefinition as z}from"@earendil-works/pi-coding-agent";const ve=200;function Ie(){return te()}t(Ie,"resolveValveMs");const je=10*1024*1024,ke=`
2
- [background bash job output truncated at 10 MiB; remaining output discarded]
3
- `,xe=['const fs = require("node:fs");',`const cap = ${je};`,`const marker = Buffer.from(${JSON.stringify(ke)});`,"const prefixCap = cap - marker.length;",'const fd = fs.openSync(process.argv[1], "w");',"let written = 0;","let truncated = false;",'process.stdin.on("data", (chunk) => {'," if (truncated) return;"," const available = prefixCap - written;"," if (available > 0) {"," const prefix = chunk.subarray(0, available);"," fs.writeSync(fd, prefix);"," written += prefix.length;"," if (prefix.length === chunk.length) return;"," }"," fs.writeSync(fd, marker);"," truncated = true;","});",'process.stdin.on("end", () => fs.closeSync(fd));'].join(" "),Be=["SECONDS=0","n=$(command -v nice)",'${n:+"$n" -n "${10}"} "${9}" "$1" 2>&1 | "${11}" -e '+JSON.stringify(xe)+' "$2"',"ec=${PIPESTATUS[0]}","d=$SECONDS",'echo "$ec" > "$3"','if [ "$d" -lt 60 ]; then',' el="${d}s"','elif [ "$d" -lt 3600 ]; then',' el="$((d / 60))m $(printf "%02d" "$((d % 60))")s"',"else",' el="$((d / 3600))h $(printf "%02d" "$((d / 60 % 60))")m"',"fi",'if mv "$4" "$5" 2>/dev/null; then'," :",'elif [ -f "$6" ]; then',' crtr node message send "Background bash job $7 finished (exit $ec) after $el. Log: $2 Command: $1" --to "$8" --tier urgent || true',"fi"].join(`
4
- `);function Le(n){return le(n,pe())}t(Le,"makeJobPaths");const j=new Set;let q=!1;function W(){for(const n of[...j])try{H(n),j.delete(n)}catch(r){process.stderr.write(`crtr: failed to background bash job ${n.jobId} during broker termination: ${r.message}
5
- `)}}t(W,"backgroundLiveJobsForTermination");function Re(){q||(q=!0,process.prependListener("SIGTERM",W),process.platform!=="win32"&&process.prependListener("SIGHUP",W))}t(Re,"installTerminationHandoff");const _e=64*1024;function T(n,r,o){let i;try{i=G(n)}catch{return r}if(i.size<=r)return r;const c=ae(n,"r");try{for(;r<i.size;){const h=Math.min(_e,i.size-r),u=Buffer.allocUnsafe(h),a=de(c,u,0,h,r);if(a===0)break;o(u.subarray(0,a)),r+=a}return r}finally{se(c)}}t(T,"tailOnce");function $(n){try{F(n,{recursive:!0,force:!0})}catch{}}t($,"cleanupJobDir");function Ce(n){try{const r=ce(n,"utf8").trim(),o=Number(r);return Number.isFinite(o)?o:null}catch{return null}}t(Ce,"readExitCode");function Te(n){try{if(G(n).isDirectory())return{cwd:n}}catch{}const r=ue();return{cwd:r,warning:`[working directory no longer exists: ${n}; running from ${r}]
6
- `}}t(Te,"resolveExecutionCwd");function X(n,r,o=()=>null,i){return{exec:t((c,h,{onData:u,signal:a,timeout:l,env:k})=>new Promise((y,f)=>{const E=o();if(a?.aborted){f(new Error("aborted"));return}const x=ge(c,h);if(x!==null){f(new Error(x));return}const e=Le(r);U(e.dir,{recursive:!0}),g(e.cmdSh,c),g(e.jobLog,""),g(e.jobRun,""),E!==null&&g(e.jobPurpose,E);let m=0,O=!1,d,p;const P=_.now(),Y=Ie();let B;const Q=t(()=>{B&&clearInterval(B),a&&a.removeEventListener("abort",N),j.delete(e)},"teardown"),b=t(s=>{O||(O=!0,Q(),s())},"finish");function L(s=!1){const w=K(_.now()-P);let D="";if(s){const J=re();me(e,Date.now()+J),D=`It will be CANCELED in ${K(J)} unless you claim it: crtr node bash extend ${e.jobId} --for <duration> (or --keep to run to completion). `}const ee=`
7
- [backgrounded as job ${e.jobId} after ${w} in the foreground${s?" (auto)":""}. `+D+`It will interrupt you with a message when it exits. Watch: tail -f ${e.jobLog} ; stop: crtr node bash kill ${e.jobId}]`;u(Buffer.from(ee)),b(()=>y({exitCode:0}))}t(L,"finishBackground");function A(){m=T(e.jobLog,m,u);const s=Ce(e.jobExit);b(()=>y({exitCode:s})),$(e.dir)}t(A,"finishForeground");function Z(s=!1){const w=H(e);if(w==="backgrounded"||w==="already-backgrounded"){L(s);return}if(w==="finished"){A();return}b(()=>f(new Error(`bash job ${e.jobId} disappeared before it could be backgrounded`))),$(e.dir)}t(Z,"requestBackground");function N(){if(m=T(e.jobLog,m,u),S(e.jobBg)){L();return}S(e.jobExit)||(d!==void 0&&p!==void 0&&V(d,p),b(()=>f(new Error("aborted"))),$(e.dir))}t(N,"onAbort"),a&&a.addEventListener("abort",N,{once:!0});const v=Te(h);v.warning&&u(Buffer.from(v.warning));let I=k??process.env;i!==void 0&&(U(fe(i),{recursive:!0}),F(i,{force:!0}),I={...I,[Se]:i});const M=Ee("bash",I,v.cwd),R=ie(M,["-c",Be,"--",e.cmdSh,e.jobLog,e.jobExit,e.jobRun,e.jobDone,e.jobBg,e.jobId,n,M,String(he(r)),process.execPath],{cwd:v.cwd,detached:!0,stdio:"ignore",env:I});if(R.on("error",s=>{b(()=>f(s)),$(e.dir)}),d=R.pid,d!==void 0){if(p=$e([d])?.get(d),p===void 0){try{process.kill(-d,"SIGKILL")}catch{}b(()=>f(new Error(`bash job ${e.jobId} started without a process identity`))),$(e.dir);return}g(e.jobPgid,String(d)),g(e.jobPgidIdentity,p),j.add(e)}R.unref(),B=setInterval(()=>{if(m=T(e.jobLog,m,u),S(e.jobDone)){A();return}if(S(e.jobBg)){L();return}if(S(e.jobExit))return;const s=_.now()-P;if(l!==void 0&&l>0){s>=l*1e3&&(d!==void 0&&p!==void 0&&V(d,p),b(()=>f(new Error(`timeout:${l}`))),$(e.dir));return}s>=Y&&Z(!0)},ve)}),"exec")}}t(X,"createValveOperations");const Oe=["One short clause naming what this step is FOR, in the words of the person you",'are working for \u2014 "Reading the Acme thread", not "Fetching emails" and never','"Running GMAIL_FETCH_EMAILS". A person reads this while the command runs; it',"is the only thing they see of this step. Under about eight words. Omit it for","steps that only touch your own scratch work."].join(" ");function Pe(n){return{...n,parameters:C.Object({purpose:C.Optional(C.String({description:Oe})),...n.parameters.properties})}}t(Pe,"withPurpose");function Ae(n,r,o,i){const c=z(o,{operations:X(n,r)});return{...i?Pe(c):c,execute:t((a,l,k,y,f)=>{const E=i?be(l.purpose):null;return z(o,{operations:X(n,r,()=>E,ye(a))}).execute(a,l,k,y,f)},"execute")}}t(Ae,"createValveToolDefinition");function Ne(n){const r=oe();if(r===void 0||r.trim()==="")return;const o=process.env.CRTR_CONTEXT_DIR;o===void 0||o.trim()===""||(Re(),n.on("session_start",(i,c)=>{n.registerTool(Ae(r,o,c.cwd,we("user").bash_tool_purpose))}))}t(Ne,"default");export{ke as BACKGROUND_BASH_LOG_TRUNCATION_MARKER,je as MAX_BACKGROUND_BASH_LOG_BYTES,X as createValveOperations,Ae as createValveToolDefinition,Ne as default};
1
+ var te=Object.defineProperty;var o=(r,n)=>te(r,"name",{value:n,configurable:!0});import{envBashAutoBgDeadlineMs as oe,envBashValveMs as ie,envNodeId as se}from"../shared/env.js";import{spawn as de}from"node:child_process";import{closeSync as ae,existsSync as B,mkdirSync as G,openSync as ce,readFileSync as ue,readSync as fe,rmSync as V,statSync as K,writeFileSync as y}from"node:fs";import{homedir as le}from"node:os";import{dirname as be}from"node:path";import{performance as O}from"node:perf_hooks";import{backgroundBashJob as z,bashJobPaths as pe,cancelBashJobProcessTree as he,formatBashElapsed as q,newBashJobId as me,normalizeBashJobPurpose as ge,readBashNiceness as we,writeJobDeadlineMs as ye}from"../core/bash-jobs.js";import{BASH_JOB_SUPERVISOR_SCRIPT as Se}from"../core/bash-job-supervisor.js";import{MAX_BACKGROUND_BASH_LOG_BYTES as ir,BACKGROUND_BASH_LOG_TRUNCATION_MARKER as sr}from"../core/bash-job-supervisor.js";import{startBrokerBashJob as Ee,stopBrokerBashJob as ve}from"../core/runtime/broker/daemon-ops.js";import{bashCommandRefusal as Be}from"../core/bash-guard.js";import{capturePidIdentities as Ie}from"../core/canvas/pid.js";import{readConfig as je}from"../core/config.js";import{PREVIEW_RESULT_PATH_ENV as _e,previewResultPath as Re}from"../core/preview-result-path.js";import{resolveAdmittedHostCommand as ke}from"../core/runtime/spawn-env.js";import{Type as P}from"typebox";import{createBashToolDefinition as W}from"@earendil-works/pi-coding-agent";const Le=200;function xe(){return ie()}o(xe,"resolveValveMs");function Te(r){return pe(r,me())}o(Te,"makeJobPaths");const I=new Set;let X=!1;function Y(){for(const r of[...I])try{z(r),I.delete(r)}catch(n){process.stderr.write(`crtr: failed to background bash job ${r.jobId} during broker termination: ${n.message}
2
+ `)}}o(Y,"backgroundLiveJobsForTermination");function Ae(){X||(X=!0,process.prependListener("SIGTERM",Y),process.platform!=="win32"&&process.prependListener("SIGHUP",Y))}o(Ae,"installTerminationHandoff");const Oe=64*1024;function C(r,n,i){let s;try{s=K(r)}catch{return n}if(s.size<=n)return n;const c=ce(r,"r");try{for(;n<s.size;){const m=Math.min(Oe,s.size-n),f=Buffer.allocUnsafe(m),d=fe(c,f,0,m,n);if(d===0)break;i(f.subarray(0,d)),n+=d}return n}finally{ae(c)}}o(C,"tailOnce");function h(r){try{V(r,{recursive:!0,force:!0})}catch{}}o(h,"cleanupJobDir");function Pe(r){try{const n=ue(r,"utf8").trim(),i=Number(n);return Number.isFinite(i)?i:null}catch{return null}}o(Pe,"readExitCode");function Ce(r){try{if(K(r).isDirectory())return{cwd:r}}catch{}const n=le();return{cwd:n,warning:`[working directory no longer exists: ${r}; running from ${n}]
3
+ `}}o(Ce,"resolveExecutionCwd");function Q(r,n,i=()=>null,s){return{exec:o((c,m,{onData:f,signal:d,timeout:p,env:k})=>new Promise((j,a)=>{const _=i();if(d?.aborted){a(new Error("aborted"));return}const L=Be(c,m);if(L!==null){a(new Error(L));return}const e=Te(n);G(e.dir,{recursive:!0}),y(e.cmdSh,c),y(e.jobLog,""),y(e.jobRun,""),_!==null&&y(e.jobPurpose,_);let g=0,x=!1,u,w,S,$=!1;const J=process.platform==="linux",M=O.now(),Z=xe();let T;const ee=o(()=>{T&&clearInterval(T),d&&d.removeEventListener("abort",D),I.delete(e)},"teardown"),l=o(t=>{x||(x=!0,ee(),t())},"finish");function A(t=!1){const b=q(O.now()-M);let U="";if(t){const F=oe();ye(e,Date.now()+F),U=`It will be CANCELED in ${q(F)} unless you claim it: crtr node bash extend ${e.jobId} --for <duration> (or --keep to run to completion). `}const ne=`
4
+ [backgrounded as job ${e.jobId} after ${b} in the foreground${t?" (auto)":""}. `+U+`It will interrupt you with a message when it exits. Watch: tail -f ${e.jobLog} ; stop: crtr node bash kill ${e.jobId}]`;f(Buffer.from(ne)),l(()=>j({exitCode:0}))}o(A,"finishBackground");function N(){g=C(e.jobLog,g,f);const t=Pe(e.jobExit);l(()=>j({exitCode:t})),h(e.dir)}o(N,"finishForeground");function re(t=!1){const b=z(e);if(b==="backgrounded"||b==="already-backgrounded"){A(t);return}if(b==="finished"){N();return}l(()=>a(new Error(`bash job ${e.jobId} disappeared before it could be backgrounded`))),h(e.dir)}o(re,"requestBackground");function R(t){if(!(x||$)){if(g=C(e.jobLog,g,f),B(e.jobBg)){A();return}if(!B(e.jobExit)){if(u===void 0){S??=t;return}if(J){$=!0,ve(r,e.jobId).then(()=>{l(()=>a(t)),h(e.dir)},b=>l(()=>a(b)));return}u!==void 0&&w!==void 0&&he(u,w),l(()=>a(t)),h(e.dir)}}}o(R,"requestStop");function D(){R(new Error("aborted"))}o(D,"onAbort"),d&&d.addEventListener("abort",D,{once:!0});const E=Ce(m);E.warning&&f(Buffer.from(E.warning));let v=k??process.env;s!==void 0&&(G(be(s),{recursive:!0}),V(s,{force:!0}),v={...v,[_e]:s});const H=ke("bash",v,E.cwd);if(J)Ee(r,{job_id:e.jobId,cwd:E.cwd,env:v}).then(({pid:t})=>{u=t,w=`launcher:${t}`,I.add(e),S!==void 0&&R(S)},t=>{l(()=>a(t)),h(e.dir)});else{const t=de(H,["-c",Se,"--",e.cmdSh,e.jobLog,e.jobExit,e.jobRun,e.jobDone,e.jobBg,e.jobId,r,H,String(we(n)),process.execPath,"direct"],{cwd:E.cwd,detached:!0,stdio:"ignore",env:v});if(t.on("error",b=>{l(()=>a(b)),h(e.dir)}),u=t.pid,u!==void 0){if(w=Ie([u])?.get(u),w===void 0){try{process.kill(-u,"SIGKILL")}catch{}l(()=>a(new Error(`bash job ${e.jobId} started without a process identity`))),h(e.dir);return}y(e.jobPgid,String(u)),y(e.jobPgidIdentity,w),I.add(e),S!==void 0&&R(S)}t.unref()}T=setInterval(()=>{if(g=C(e.jobLog,g,f),B(e.jobDone)){N();return}if(B(e.jobBg)){A();return}if(B(e.jobExit))return;const t=O.now()-M;if(p!==void 0&&p>0){t>=p*1e3&&R(new Error(`timeout:${p}`));return}t>=Z&&re(!0)},Le)}),"exec")}}o(Q,"createValveOperations");const $e=["One short clause naming what this step is FOR, in the words of the person you",'are working for \u2014 "Reading the Acme thread", not "Fetching emails" and never','"Running GMAIL_FETCH_EMAILS". A person reads this while the command runs; it',"is the only thing they see of this step. Under about eight words. Omit it for","steps that only touch your own scratch work."].join(" ");function Je(r){return{...r,parameters:P.Object({purpose:P.Optional(P.String({description:$e})),...r.parameters.properties})}}o(Je,"withPurpose");function Me(r,n,i,s){const c=W(i,{operations:Q(r,n)});return{...s?Je(c):c,execute:o((d,p,k,j,a)=>{const _=s?ge(p.purpose):null;return W(i,{operations:Q(r,n,()=>_,Re(d))}).execute(d,p,k,j,a)},"execute")}}o(Me,"createValveToolDefinition");function Ne(r){const n=se();if(n===void 0||n.trim()==="")return;const i=process.env.CRTR_CONTEXT_DIR;i===void 0||i.trim()===""||(Ae(),r.on("session_start",(s,c)=>{r.registerTool(Me(n,i,c.cwd,je("user").bash_tool_purpose))}))}o(Ne,"default");export{sr as BACKGROUND_BASH_LOG_TRUNCATION_MARKER,ir as MAX_BACKGROUND_BASH_LOG_BYTES,Q as createValveOperations,Me as createValveToolDefinition,Ne as default};
@@ -1,5 +1,4 @@
1
1
  import { CONTEXT_INTRO_CUSTOM_TYPE } from '../shared/generated-context.js';
2
- import { type ExposureTarget } from '../core/substrate/injected-store.js';
3
2
  /** The `customType` stamped on the injected session message. Used both to write
4
3
  * the entry and to detect it on resume (the idempotency guard). Defined beside
5
4
  * the block builder in `core/runtime/bearings.ts` because the warm-pool claim's
@@ -47,7 +46,7 @@ interface PiLike {
47
46
  }
48
47
  /** Build the full bearings baseline for a conversation without inherited
49
48
  * crouter context. Exported for testing. */
50
- export declare function buildContextIntro(nodeId: string, target?: ExposureTarget): Promise<string>;
49
+ export declare function buildContextIntro(nodeId: string): Promise<string>;
51
50
  /** Build the compact node-scoped update for a fork whose copied branch already
52
51
  * carries a full crouter baseline. Exported for testing. */
53
52
  export declare function buildForkContextIntro(nodeId: string): Promise<string>;
@@ -1,2 +1,2 @@
1
- var h=Object.defineProperty;var a=(t,o)=>h(t,"name",{value:o,configurable:!0});import{envNodeId as b}from"../shared/env.js";import{CONTEXT_INTRO_CUSTOM_TYPE as c,formatCard as v}from"../shared/generated-context.js";import{brokerExtensionState as u}from"../core/runtime/broker/daemon-ops.js";import{buildContextBearingsFromState as g,buildForkBearingsFromState as E,buildProjectContextBlockForBroker as S,renderPreferencesFromState as B}from"../core/runtime/broker-extension-render.js";import{acknowledgePersonaBaseline as _}from"../core/runtime/broker-persona-guidance.js";import{situationalContextEnvelope as p}from"../core/runtime/situational-context.js";import{clearContextExposureState as k,cloneTranscriptExposureState as F,emptyContextExposureState as I,exposureTarget as y,freezePreferenceSnapshot as P,hasTranscriptExposure as M,loadContextExposureState as N,replaceContextExposureState as O,saveContextExposureState as j,sharedContextExposureState as z}from"../core/substrate/injected-store.js";import{clearSessionCache as A}from"../core/substrate/session-cache.js";async function Q(t,o){const n=await u(t);return g(n,S(n.node.cwd),p(t)??"",o)}a(Q,"buildContextIntro");async function V(t){const o=await u(t);return E(o,p(t)??"")}a(V,"buildForkContextIntro");function w(t){const o=t.content;return typeof o=="string"?o:Array.isArray(o)?o.filter(n=>typeof n?.text=="string").map(n=>n.text).join(`
2
- `):""}a(w,"entryText");function R(t){t.on("session_start",async(o,n)=>{const e=b();if(e===void 0||e.trim()==="")return;const m=o?.reason,s=await u(e);if(s.warm_spare||m==="new"&&s.node.parent===null)return;m==="new"&&(k(e),A());const d=n.sessionManager.getBranch().filter(r=>r.type==="custom_message"&&r.customType===c);if(d.some(r=>r.details?.nodeId===e||w(r).includes(e)))return;const x=N(e),f=d.length>0&&M(x),i=f?F(x):I(),T=f?E(s,p(e)??""):g(s,S(s.node.cwd),p(e)??"",y(i,"transcript"));P(i,B(s,y(i,"system")));const l=v("bearings",{},T);if(t.sendMessage({customType:c,content:l,display:!0,details:{nodeId:e}}),!n.sessionManager.getBranch().some(r=>r.type==="custom_message"&&r.customType===c&&r.details?.nodeId===e&&w(r)===l))throw new Error(`Pi did not materialize the context baseline for ${e}`);const C=z(e);O(C,i),j(e,C),await _(s)})}a(R,"registerCanvasContextIntro");var W=R;export{c as CONTEXT_INTRO_CUSTOM_TYPE,Q as buildContextIntro,V as buildForkContextIntro,W as default,R as registerCanvasContextIntro};
1
+ var C=Object.defineProperty;var s=(t,n)=>C(t,"name",{value:n,configurable:!0});import{envNodeId as y}from"../shared/env.js";import{CONTEXT_INTRO_CUSTOM_TYPE as c,formatCard as b}from"../shared/generated-context.js";import{brokerContext as p,brokerExtensionState as f,commitBrokerContext as T}from"../core/runtime/broker/daemon-ops.js";import{buildForkBearingsFromState as l}from"../core/runtime/broker-extension-render.js";import{acknowledgePersonaBaseline as h}from"../core/runtime/broker-persona-guidance.js";import{situationalContextEnvelope as x}from"../core/runtime/situational-context.js";import{clearSessionCache as I}from"../core/substrate/session-cache.js";async function A(t){return(await p(t,"baseline")).content}s(A,"buildContextIntro");async function j(t){const n=await f(t);return l(n,x(t)??"")}s(j,"buildForkContextIntro");function g(t){const n=t.content;return typeof n=="string"?n:Array.isArray(n)?n.filter(r=>typeof r?.text=="string").map(r=>r.text).join(`
2
+ `):""}s(g,"entryText");function _(t){t.on("session_start",async(n,r)=>{const e=y();if(e===void 0||e.trim()==="")return;const m=n?.reason,a=await f(e);if(a.warm_spare||m==="new"&&a.node.parent===null)return;m==="new"&&I();const d=r.sessionManager.getBranch().filter(o=>o.type==="custom_message"&&o.customType===c);if(d.some(o=>o.details?.nodeId===e||g(o).includes(e)))return;const i=await p(e,d.length>0?"compact":"baseline"),w=i.compact?l(a,x(e)??""):i.content,u=b("bearings",{},w);if(t.sendMessage({customType:c,content:u,display:!0,details:{nodeId:e}}),!r.sessionManager.getBranch().some(o=>o.type==="custom_message"&&o.customType===c&&o.details?.nodeId===e&&g(o)===u))throw new Error(`Pi did not materialize the context baseline for ${e}`);await T(e,i.snapshot,i.loads),await h(a)})}s(_,"registerCanvasContextIntro");var z=_;export{c as CONTEXT_INTRO_CUSTOM_TYPE,A as buildContextIntro,j as buildForkContextIntro,z as default,_ as registerCanvasContextIntro};
@@ -1,9 +1,9 @@
1
- var P=Object.defineProperty;var d=(o,e)=>P(o,"name",{value:e,configurable:!0});import{envNodeId as _}from"../shared/env.js";import{homedir as j}from"node:os";import{join as L,resolve as N}from"node:path";import{brokerExtensionState as x}from"../core/runtime/broker/daemon-ops.js";import{renderPreferencesFromState as H}from"../core/runtime/broker-extension-render.js";import{corpusHasCommandSurfaceForCommand as T,corpusHasPreCommandSurfaceForCommand as D,demotePreCommandExposures as F,renderOnCommandDocsForSubject as k,renderOnReadDocsForSubject as I,renderPreCommandDocsForSubject as R}from"../core/substrate/on-read.js";import{clearSessionCache as $}from"../core/substrate/session-cache.js";import{cloneContextExposureState as y,exposureTarget as b,freezePreferenceSnapshot as A,loadContextExposureState as l,mergeContextExposureState as f,replaceContextExposureState as S,saveContextExposureState as p,sharedContextExposureState as W}from"../core/substrate/injected-store.js";import{autoLoadedContextInner as G,mergeAutoLoadedContext as Y}from"./envelope-merge.js";const z=`
1
+ var E=Object.defineProperty;var l=(n,e)=>E(n,"name",{value:e,configurable:!0});import{envNodeId as g}from"../shared/env.js";import{homedir as C}from"node:os";import{join as S,resolve as _}from"node:path";import{brokerContext as O,brokerContextEvent as f,commitBrokerContext as p}from"../core/runtime/broker/daemon-ops.js";import{clearSessionCache as L}from"../core/substrate/session-cache.js";import{contextExposureStatesEqual as N,mergeContextExposureState as k,replaceContextExposureState as x,restoreContextExposure as h,sharedContextExposureState as P,snapshotContextExposure as T}from"../core/substrate/injected-store.js";import{autoLoadedContextInner as $,mergeAutoLoadedContext as H}from"./envelope-merge.js";const I=`
2
2
 
3
- Guidelines:`;function B(o){const e=o?.command;return typeof e=="string"&&e.trim()!==""?e:null}d(B,"bashCommandOf");function q(o){return["HELD \u2014 nothing ran.","","Your bash command was NOT executed. It matched memory you had not yet read, and that memory is below.","","Read it, then re-issue your WHOLE command unchanged \u2014 every clause of it, including any heredoc, redirect, or `$(\u2026)` that built its input, because none of that ran either. The re-issue executes: this memory is now in your transcript, so there is nothing left to deliver and nothing left to hold.","",o].join(`
4
- `)}d(q,"heldReason");const J=["HELD \u2014 nothing ran.","","Your bash command was NOT executed. Another command in this same message was held against memory you had not read, and that memory was returned with it.","","Read it, then re-issue your WHOLE command unchanged. The re-issue executes."].join(`
5
- `);function K(o){const e=_();if(e===void 0||e.trim()==="")return;const n=W(e);o.on("session_start",()=>{$()}),o.on("before_agent_start",async t=>{f(n,l(e));let r=n.preferenceSnapshot;if(r===null){const s=await x(e),a=y(n);r=A(a,H(s,b(a,"system"))),p(e,a),S(n,a)}if(r==="")return;const i=t.systemPrompt.indexOf(z);return i===-1?{systemPrompt:`${t.systemPrompt}
3
+ Guidelines:`;function R(n){const e=n?.command;return typeof e=="string"&&e.trim()!==""?e:null}l(R,"bashCommandOf");function j(n){return["HELD \u2014 nothing ran.","","Your bash command was NOT executed. It matched memory you had not yet read, and that memory is below.","","Read it, then re-issue your WHOLE command unchanged \u2014 every clause of it, including any heredoc, redirect, or `$(\u2026)` that built its input, because none of that ran either. The re-issue executes: this memory is now in your transcript, so there is nothing left to deliver and nothing left to hold.","",n].join(`
4
+ `)}l(j,"heldReason");const A=["HELD \u2014 nothing ran.","","Your bash command was NOT executed. Another command in this same message was held against memory you had not read, and that memory was returned with it.","","Read it, then re-issue your WHOLE command unchanged. The re-issue executes."].join(`
5
+ `);function D(n){const e=g();if(e===void 0||e.trim()==="")return;const s=P(e);n.on("session_start",()=>{L()}),n.on("before_agent_start",async t=>{const a=s.preferenceSnapshot===null,o=await O(e,"preferences"),i=h(o.snapshot);k(s,i);const r=s.preferenceSnapshot;if(r===null)throw new Error(`daemon returned no preference snapshot for ${e}`);if((a||!N(s,i))&&await p(e,T(s),o.loads),r==="")return;const c=t.systemPrompt.indexOf(I);return c===-1?{systemPrompt:`${t.systemPrompt}
6
6
 
7
- ${r}`}:{systemPrompt:`${t.systemPrompt.slice(0,i)}
7
+ ${r}`}:{systemPrompt:`${t.systemPrompt.slice(0,c)}
8
8
 
9
- ${r}${t.systemPrompt.slice(i)}`}});let u=!1;o.on("turn_end",()=>{u=!1}),o.on("session_compact",()=>{f(n,l(e)),F(n),p(e,n),u=!1}),o.on("tool_call",async t=>{if(t.toolName!=="bash")return;const r=B(t.input);if(r===null)return;if(u)return{block:!0,reason:J};if(!D(r))return;const i=await x(e);f(n,l(e));const s=y(n),a=R(i.subject,r,b(s,"transcript"));if(a!=="")return u=!0,p(e,s),S(n,s),{block:!0,reason:q(a)}}),o.on("tool_result",async(t,r)=>{if(t.isError===!0)return;let i=null,s=null;if(t.toolName==="read"){const c=t.input,m=c?.path??c?.file_path;if(m===void 0||m==="")return;const E=typeof r?.cwd=="string"&&r.cwd!==""?r.cwd:process.cwd(),O=m.startsWith("~")?L(j(),m.slice(1)):m;i=N(E,O)}else if(t.toolName==="bash"){const c=t.input;if(typeof c?.command!="string"||c.command.trim()==="")return;s=c.command}else return;if(s!==null&&!T(s))return;const a=await x(e);f(n,l(e));const h=y(n),C=b(h,"transcript"),g=i!==null?I(a.subject,i,C):k(a.subject,s,C);if(g==="")return;const w=G(g);if(w===null)throw new Error("substrate renderer returned an invalid auto-loaded context block");return p(e,h),S(n,h),{content:Y([w],t.content)}})}d(K,"registerCanvasDocSubstrate");var re=K;export{re as default,K as registerCanvasDocSubstrate};
9
+ ${r}${t.systemPrompt.slice(c)}`}});let u=!1;n.on("turn_end",()=>{u=!1}),n.on("session_compact",async()=>{const t=await f(e,"compact");await p(e,t.snapshot,t.loads),x(s,h(t.snapshot)),u=!1}),n.on("tool_call",async t=>{if(t.toolName!=="bash")return;const a=R(t.input);if(a===null)return;if(u)return{block:!0,reason:A};const o=await f(e,"pre-command",a),i=o.content;if(i!=="")return u=!0,await p(e,o.snapshot,o.loads),x(s,h(o.snapshot)),{block:!0,reason:j(i)}}),n.on("tool_result",async(t,a)=>{if(t.isError===!0)return;let o=null,i=null;if(t.toolName==="read"){const d=t.input,m=d?.path??d?.file_path;if(m===void 0||m==="")return;const w=typeof a?.cwd=="string"&&a.cwd!==""?a.cwd:process.cwd(),b=m.startsWith("~")?S(C(),m.slice(1)):m;o=_(w,b)}else if(t.toolName==="bash"){const d=t.input;if(typeof d?.command!="string"||d.command.trim()==="")return;i=d.command}else return;const r=await f(e,o!==null?"read":"command",o??i),c=r.content;if(c==="")return;const y=$(c);if(y===null)throw new Error("substrate renderer returned an invalid auto-loaded context block");return await p(e,r.snapshot,r.loads),x(s,h(r.snapshot)),{content:H([y],t.content)}})}l(D,"registerCanvasDocSubstrate");var K=D;export{K as default,D as registerCanvasDocSubstrate};
@@ -1,9 +1,10 @@
1
- type PiEvents = 'session_start' | 'turn_end' | 'agent_start' | 'agent_end' | 'agent_settled' | 'session_shutdown';
1
+ type PiEvents = 'session_start' | 'turn_end' | 'agent_start' | 'agent_end' | 'agent_settled' | 'message_end' | 'session_shutdown';
2
2
  interface PiLike {
3
3
  on: (event: PiEvents, handler: (event: any, ctx: any) => void | Promise<void>) => void;
4
4
  sendUserMessage: (content: string, options?: {
5
5
  deliverAs?: 'steer' | 'followUp';
6
6
  }) => void;
7
+ appendEntry: (type: string, data: unknown) => void;
7
8
  sendMessage: (message: {
8
9
  customType: string;
9
10
  content: string;
@@ -1 +1,2 @@
1
- var S=Object.defineProperty;var f=(s,t)=>S(s,"name",{value:t,configurable:!0});import{envNodeId as A,envProfileId as O,envWatcherDebounceMs as P,envWatcherTickMs as H}from"../shared/env.js";import{coalesceBrokerInbox as T,entryCards as D,reportRefNodeId as U}from"../core/runtime/broker/inbox.js";import{acknowledgeBrokerMail as q,claimBrokerMail as B,brokerExtensionState as J}from"../core/runtime/broker/daemon-ops.js";import{wasTurnRefused as $}from"../core/runtime/broker/extension-abort.js";import{isDaemonTransportApiError as k}from"../api/errors.js";import{announceMessageOrigin as W}from"../core/runtime/stamp/channel.js";import{captureGoalIfAbsent as G,generateAndCommitInitialName as X}from"./broker-local.js";import{emitEvent as L}from"../core/events/emit.js";import{errorClassFromError as V}from"../core/events/errors.js";import{operationIdContext as u}from"../core/events/operation-id.js";import{situationalContextEnvelope as j,SITUATIONAL_CONTEXT_CUSTOM_TYPE as w}from"../core/runtime/situational-context.js";import{isProfilePaused as z}from"../core/profiles/manifest.js";import{brokerIdleTurnStart as Y,HELD_DEFERRED_INBOX_PROMPT_JOIN as K}from"../core/runtime/broker/held-deferred-inbox.js";const g=64,F=16;let p,Q=0;class M extends Error{static{f(this,"WatcherFatalError")}constructor(t,e){super(t,{cause:e}),this.name="WatcherFatalError"}}function Z(){return{tickMs:H(),debounceMs:P()}}f(Z,"resolveCadence");function m(){const s=A();return s===void 0||s.trim()===""?void 0:s}f(m,"currentNodeId");function R(){const s=O();return s!==void 0&&s!==""&&z(s)}f(R,"profilePaused");function b(s){try{return V(s)}catch{return{class:"unknown"}}}f(b,"safeErrorClass");function v(s){try{L(s)}catch{}}f(v,"emitBestEffort");function _(s){try{u.fresh(t=>{v({...s,operation_id:t})})}catch{}}f(_,"emitFreshBestEffort");function I(s,t){try{u.run(s,()=>{v({...t,operation_id:s})})}catch{}}f(I,"emitStoredBestEffort");function ee(s){return s.kind==="human"?{type:"human"}:{type:"runtime",kind:"inbox",entries:s.entries.map(t=>({...t.from===null?{}:{from:t.from},...t.from_name===void 0?{}:{fromName:t.from_name},kind:t.kind,tier:t.tier,...t.ref===void 0?{}:{ref:t.ref}}))}}f(ee,"deliveryOrigin");function E(s,t){if(s.length===0)throw new Error(`cannot create an empty ${t} delivery`);const e=[...new Set(s.map(r=>r.operation_id))].sort(),i=e.length-F;return{channel:t,entryIds:s.map(r=>r.entry_id),throughEntryId:s.at(-1).entry_id,sourceOperationIds:e.slice(0,F),...i>0?{sourceOperationIdsOmitted:i}:{}}}f(E,"deliveryFacts");function y(s){return{channel:s.channel,entry_ids:s.entryIds,through_entry_id:s.throughEntryId,source_operation_ids:s.sourceOperationIds,...s.sourceOperationIdsOmitted===void 0?{}:{source_operation_ids_omitted:s.sourceOperationIdsOmitted}}}f(y,"deliveryFields");function te(s){I(s.operationId,{level:"info",event:"inbox.delivery.completed",outcome:"succeeded",fields:y(s)})}f(te,"emitDeliveryCompleted");function C(s,t,e,i){I(s,{level:"error",event:"inbox.delivery.failed",outcome:"failed",error:i,error_class:b(i),fields:{stage:e,...y(t)}})}f(C,"emitDeliveryFailure");function x(s,t){I(s.operationId,{level:"error",event:"inbox.delivery.failed",outcome:"failed",error_class:{class:"unknown"},fields:{stage:"abandoned",reason:t,...y(s)}})}f(x,"emitDeliveryAbandoned");function N(s){return s==="quit"||s==="reload"||s==="new"||s==="resume"||s==="fork"}f(N,"isSessionShutdownReason");function ie(s){switch(s){case"quit":return"shutdown";case"reload":case"new":case"resume":case"fork":return"reload";default:return s}}f(ie,"disposalReasonForShutdown");function re(s){return typeof s=="string"?s.slice(0,128):s===null?"null":s===void 0?"undefined":typeof s=="number"||typeof s=="boolean"||typeof s=="bigint"?String(s).slice(0,128):typeof s}f(re,"boundedRuntimeReason");class ne{static{f(this,"CanvasInboxWatcher")}pi;cadence;generation;timer;armed=!1;lastCtx;streaming=!1;nodeId;claims=new Map;tickInFlight;buffer=[];lastArrival=0;pendingHandoffs=[];pendingCommit;promptJoinInFlight=!1;replayUnseenInherited=!1;seeded=!1;disposed=!1;disposalReason;fatalError;fatalEscaped=!1;reportNodes=new Map;reportNodesAsked=new Set;reportNodesRefreshing=!1;constructor(t,e,i){this.pi=t,this.cadence=e,this.generation=i}start(){const t=f((e,i)=>{this.canMutate()&&this.captureCtx(e,i)},"capture");this.pi.on("session_start",(e,i)=>{this.canMutate()&&(this.captureCtx(e,i),this.arm(),this.refreshReportNodes(m()))}),this.pi.on("turn_end",t),this.pi.on("agent_start",(e,i)=>{this.canMutate()&&(this.captureCtx(e,i),this.streaming=!0)}),this.pi.on("agent_end",(e,i)=>{this.canMutate()&&(this.captureCtx(e,i),this.streaming=!1)}),this.pi.on("agent_settled",async(e,i)=>{if(!this.canMutate())return;this.captureCtx(e,i);const r=m();if(r!==void 0)try{this.assertNodeOwnership(r,"settle"),await this.tickInFlight,this.seeded||await this.claimMail(r),await this.settle(r,i,!1,!0)==="refresh_held"&&this.dispose("refresh",!1)}catch(n){this.dispose("shutdown",!1,void 0,{error:n,stage:"settle"})}}),this.pi.on("session_shutdown",async e=>{if(!this.canMutate())return;let i;try{i=e?.reason}catch{i=void 0}const r=N(i)?ie(i):"reload";N(i)||_({level:"warn",event:"inbox.lifecycle.unknown_shutdown_reason",outcome:"failed",fields:{reason:re(i)}});try{await this.disposeAtSettlement(r,this.lastCtx)}catch(n){this.dispose(r,!1,void 0,{error:n,stage:"settle"})}})}async refreshReportNodes(t){if(t!==void 0){this.reportNodesRefreshing=!0;try{const e=await J(t);if(!this.canMutate())return;this.reportNodes=new Map(e.report_nodes.map(i=>[i.node_id,i]))}catch{}finally{this.reportNodesRefreshing=!1}}}refreshForUnknownReportRefs(){const t=[];for(const e of this.buffer){const i=U(e.ref);i!==void 0&&(this.reportNodes.has(i)||this.reportNodesAsked.has(i)||t.push(i))}if(t.length===0)return!1;for(const e of t)this.reportNodesAsked.add(e);return this.refreshReportNodes(m()),this.reportNodesRefreshing}arm(){this.armed||(this.armed=!0,this.timer=setInterval(()=>this.runTick(),this.cadence.tickMs),typeof this.timer.unref=="function"&&this.timer.unref(),this.runTick("schedule"))}async disposeAtSettlement(t,e){const i=m();if(i===void 0){this.dispose(t,!1);return}try{this.assertNodeOwnership(i,"settle");const r=await this.settle(i,e,t!=="refresh");this.dispose(r==="refresh_held"?"refresh":t,!1)}catch(r){this.dispose(t,!1,void 0,{error:r,stage:"settle"})}}dispose(t,e,i,r){if(this.disposed)return;this.disposed=!0,this.disposalReason=t,this.clearTimer();const n=r;{const o=[...this.pendingCommit?.handoffs??[],...this.pendingHandoffs.splice(0)];this.buffer.length=0,this.claims.clear(),this.reportNodes.clear(),this.reportNodesAsked.clear(),this.pendingCommit=void 0,this.promptJoinInFlight=!1,this.replayUnseenInherited=!1,this.nodeId=void 0,this.lastCtx=void 0,this.lastArrival=0,this.streaming=!1,this.seeded=!1,this.ownsCurrentGeneration()&&(p=void 0);for(const a of o)x(a,t)}if(n!==void 0){this.scheduleHandlerFatal(n.error,n.stage);return}}ownsCurrentGeneration(){return p===this&&p.generation===this.generation}canMutate(){return this.ownsCurrentGeneration()&&!this.disposed&&this.fatalError===void 0}captureCtx(t,e){e!==void 0&&(this.lastCtx=e)}clearTimer(){this.timer!==void 0&&(clearInterval(this.timer),this.timer=void 0)}isIdle(){try{if(typeof this.lastCtx?.isIdle=="function")return this.lastCtx.isIdle()===!0}catch{}return!this.streaming}assertNodeOwnership(t,e){!this.seeded||this.nodeId===void 0||this.nodeId===t||this.raiseReadFatal(e,new Error(`watcher node changed from ${this.nodeId} to ${t}`))}raiseFatal(t,e,i,r){throw this.fatalError===void 0&&(this.fatalError=new M(e,i),this.clearTimer(),_({level:"error",event:t,outcome:"failed",error:i,error_class:b(i),fields:r})),this.fatalError}raiseReadFatal(t,e){return this.raiseFatal("inbox.read.failed",`inbox ${t} state is corrupt`,e,{stage:t})}raiseSituationalFatal(t,e){return this.raiseFatal("inbox.situational_context.missing","situational context marker has no readable sidecar",e,{entry_id:t})}escapeFatal(t,e){if(!this.fatalEscaped){if(this.fatalEscaped=!0,e==="throw")throw t;queueMicrotask(()=>{throw t})}}scheduleHandlerFatal(t,e){let i;if(t instanceof M)i=t;else try{this.raiseReadFatal(e,t)}catch(r){i=r}this.escapeFatal(i,"schedule")}runTick(t="throw"){if(!this.canMutate()||this.tickInFlight!==void 0)return;const e=this.tick().catch(i=>{if(this.canMutate()){if(k(i)){_({level:"warn",event:"inbox.read.failed",outcome:"failed",error:i,error_class:b(i),fields:{stage:"poll"}});return}this.scheduleHandlerFatal(i,"poll")}}).finally(()=>{this.tickInFlight===e&&(this.tickInFlight=void 0)});this.tickInFlight=e}async claimMail(t){this.assertNodeOwnership(t,"poll");let e;try{e=await B(t,"wake")}catch(o){throw k(o)&&(this.replayUnseenInherited=!0),o}if(!this.canMutate()||e.action==="hold")return!1;const i=this.replayUnseenInherited;this.replayUnseenInherited=!1,this.nodeId=t,this.seeded=!0;const r=new Set(e.deliveries.map(o=>o.entry.entry_id)),n=this.buffer.filter(o=>!r.has(o.entry_id));for(const o of n)this.claims.delete(o.entry_id);this.buffer.splice(0,this.buffer.length,...this.buffer.filter(o=>r.has(o.entry_id)));for(const o of e.deliveries){const a=o.entry.entry_id;this.claims.has(a)||(this.claims.set(a,o),o.handoff==="inherited"&&!i?u.fresh(d=>{this.pendingHandoffs.push({...E([o.entry],"visible"),operationId:d,settleAtAgentSettled:!0})}):(this.buffer.push(o.entry),this.lastArrival=Date.now()))}return!0}async tick(){const t=m();if(t!==void 0){if(this.pendingCommit!==void 0){await this.retryPendingCommit(t)==="refresh_held"&&this.canMutate()&&this.dispose("refresh",!1);return}if(!(this.promptJoinInFlight||R())&&!(this.pendingHandoffs.length>=g)&&await this.claimMail(t)&&this.buffer.length>0&&Date.now()-this.lastArrival>=this.cadence.debounceMs){if(this.refreshForUnknownReportRefs())return;this.flushOrdinary(t)}}}missingChannelEntries(t){const e=t.filter(n=>this.claims.has(n.entry_id)),i=this.coveredEntryIds("hidden"),r=this.coveredEntryIds("visible");return{hiddenEntries:e.filter(n=>(n.data?.situational===!0||n.data?.situationalOnly===!0)&&!i.has(n.entry_id)),visibleEntries:e.filter(n=>n.data?.situationalOnly!==!0&&!r.has(n.entry_id))}}visibleRoute(t){return t.length===0?"none":this.isIdle()?"idle":t.some(e=>e.tier==="critical")?"critical":t.some(e=>e.tier==="urgent"||e.kind==="final")?"steer":"followUp"}buildPlan(t){const{hiddenEntries:e,visibleEntries:i}=this.missingChannelEntries(t),r=new Set(e.map(c=>c.entry_id)),n=new Set(i.map(c=>c.entry_id)),o=t.filter(c=>r.has(c.entry_id)||n.has(c.entry_id)),a=this.isIdle()&&o.length>0&&o.every(c=>c.tier==="deferred"),d=this.visibleRoute(i)==="critical",h=!a&&!d&&e.length>0,l=!a&&!d&&i.length>0;return{hiddenEntries:e,visibleEntries:i,deferredHold:a,sendCount:Number(h)+Number(l)}}ordinaryPlan(){return this.buildPlan(this.buffer)}contextCards(t,e){const i=[];if(e.some(r=>r.data?.situational===!0)){const r=e.at(-1).entry_id;let n;try{n=j(t)}catch(o){this.raiseSituationalFatal(r,o)}n===null&&this.raiseSituationalFatal(r,new Error(`missing situational context for entry ${r}`)),i.push(n)}for(const r of e)r.data?.situationalOnly===!0&&i.push(...D(r));return i}digest(t,e){try{return T(t,this.reportNodes)}catch(i){this.raiseReadFatal(e,i)}}sendDelivery(t,e,i,r){this.pendingHandoffs.length>=g&&this.raiseReadFatal(r,new Error(`pending handoff capacity exceeded before ${t} send`));let n;try{n=E(e,t)}catch(d){this.raiseReadFatal(r,d)}let o;try{u.fresh(d=>{o=d,v({level:"info",event:"inbox.delivery.started",operation_id:d,fields:y(n)}),i()})}catch(d){return o===void 0&&this.raiseReadFatal(r,d),C(o,n,"send",d),"failed"}o===void 0&&this.raiseReadFatal(r,new Error(`${t} delivery returned without an operation id`));const a={operationId:o,...n};return this.canMutate()?(this.pendingHandoffs.push(a),"handed-off"):(this.disposed&&this.disposalReason!==void 0&&x(a,this.disposalReason),"inactive")}sendContext(t,e,i,r,n,o){return this.sendDelivery("hidden",e,()=>{const a=r==="steer"||r==="followUp"?r:this.isIdle()?void 0:"followUp";i.forEach((d,h)=>{const l=n&&h===i.length-1;this.pi.sendMessage({customType:w,content:d,display:!0,details:{nodeId:t}},a!==void 0?{deliverAs:a}:l?{deliverAs:"followUp",triggerTurn:!0}:{})})},o)}sendVisible(t,e,i,r,n,o){return this.sendDelivery("visible",t,()=>{if(n!=="idle"&&n!=="steer"&&n!=="followUp")throw new Error(`visible send requested for non-send route ${n}`);for(const a of e)this.pi.sendMessage({customType:w,content:a,display:!0},n==="idle"?{}:{deliverAs:n});if(W(i,r),n==="idle"){const a=Y();if(a===void 0)throw new Error("broker idle-turn admission is unavailable");a(i)}else this.pi.sendUserMessage(i,{deliverAs:n})},o)}abortCritical(){try{this.lastCtx?.abort?.()}catch{}}requeueFromBatch(t,e){if(e.size===0)return;const i=t.filter(o=>e.has(o.entry_id)),r=new Set(i.map(o=>o.entry_id)),n=this.buffer.filter(o=>!r.has(o.entry_id));this.buffer.splice(0,this.buffer.length,...i,...n)}executePlan(t,e,i){const r=new Set,n=this.visibleRoute(e.visibleEntries);if(n==="critical"){if(this.abortCritical(),!this.canMutate())return{inactive:!0,requeueEntryIds:r};for(const h of e.visibleEntries)r.add(h.entry_id);for(const h of e.hiddenEntries)r.add(h.entry_id);return{inactive:!1,requeueEntryIds:r}}const o=e.visibleEntries.length>0?this.digest(e.visibleEntries,i):[],[a,...d]=o;for(const h of d)for(const l of h.entries)r.add(l.entry_id);if(e.hiddenEntries.length>0){const h=this.contextCards(t,e.hiddenEntries),l=this.sendContext(t,e.hiddenEntries,h,n,a===void 0,i);if(l==="inactive")return{inactive:!0,requeueEntryIds:r};if(l==="failed")for(const c of e.hiddenEntries)r.add(c.entry_id)}if(!this.canMutate())return{inactive:!0,requeueEntryIds:r};if(a!==void 0){const h=this.sendVisible(a.entries,a.cards,a.text,ee(a),n,i);if(h==="inactive")return{inactive:!0,requeueEntryIds:r};if(h==="failed")for(const l of a.entries)r.add(l.entry_id);else a.kind==="human"&&(G(t,a.text),X(t,a.text))}return{inactive:!1,requeueEntryIds:r}}flushOrdinary(t){if(this.buffer.length===0)return"empty";const e=this.ordinaryPlan();if(e.deferredHold)return"held";if(this.pendingHandoffs.length+e.sendCount>g)return"capacity-blocked";const i=[...this.buffer],r=this.executePlan(t,e,"poll");return r.inactive||(this.buffer.splice(0,i.length),this.requeueFromBatch(i,r.requeueEntryIds)),"attempted"}async prependHeldDeferredInbox(t){if(!this.canMutate()||this.nodeId===void 0||R())return;const e=this.ordinaryPlan();if(!e.deferredHold)return;const i=e.visibleEntries.length===0?[]:this.digest(e.visibleEntries,"poll"),r=+(e.hiddenEntries.length>0)+i.length;if(this.pendingHandoffs.length+r>g)return;const n=[...this.buffer];this.promptJoinInFlight=!0;try{e.hiddenEntries.length>0&&await this.sendPromptJoinDelivery(t,"hidden",e.hiddenEntries,this.contextCards(this.nodeId,e.hiddenEntries));for(const o of i)await this.sendPromptJoinDelivery(t,"visible",o.entries,[...o.cards,o.text]);if(!this.canMutate())return;this.buffer.splice(0,n.length)}finally{this.promptJoinInFlight=!1}}async sendPromptJoinDelivery(t,e,i,r){let n;try{n=E(i,e)}catch(d){this.raiseReadFatal("poll",d)}let o;try{await u.fresh(async d=>{o=d,v({level:"info",event:"inbox.delivery.started",operation_id:d,fields:y(n)});for(const h of r)await t.sendCustomMessage({customType:w,content:h,display:!0})})}catch(d){throw o===void 0&&this.raiseReadFatal("poll",d),C(o,n,"send",d),d}o===void 0&&this.raiseReadFatal("poll",new Error(`${e} prompt-join delivery returned without an operation id`));const a={operationId:o,...n,settleAtAgentSettled:!0};if(!this.canMutate()){this.disposed&&this.disposalReason!==void 0&&x(a,this.disposalReason);return}this.pendingHandoffs.push(a)}coveredEntryIds(t){const e=new Set;for(const i of this.pendingHandoffs)if(i.channel===t)for(const r of i.entryIds)e.add(r);return e}retryPendingCommit(t){const e=this.pendingCommit;if(e===void 0)return Promise.resolve("settled");if(e.attempt!==void 0)return e.attempt;const i=this.attemptPendingCommit(t,e).finally(()=>{e.attempt===i&&(e.attempt=void 0)});return e.attempt=i,i}async attemptPendingCommit(t,e){let i=!1;try{const n=await q(t,e.receipts);if(n.action==="hold")return"refresh_held";for(const o of e.receipts){const a=n.results.find(d=>d.delivery_id===o.delivery_id);if(a?.outcome!==o.disposition&&a?.outcome!=="stale")throw new Error("daemon returned no terminal mail settlement outcome")}i=n.results.every(o=>o.outcome==="acknowledged")}catch(n){if(this.pendingCommit===e)for(const o of e.handoffs)C(o.operationId,o,"receipt_commit",n);return"held"}if(this.pendingCommit!==e)return"settled";for(const n of e.entryIds)this.claims.delete(n);if(e.receipts.some(n=>n.disposition==="released")){const n=new Set(e.entryIds);this.buffer.splice(0,this.buffer.length,...this.buffer.filter(o=>!n.has(o.entry_id)))}this.pendingCommit=void 0;const r=this.detachPending(n=>n.entryIds.every(o=>!this.claims.has(o)));for(const n of r)i&&te(n);return"settled"}async settle(t,e,i,r=!1){if(i)try{if(e?.hasPendingMessages?.()===!0)return"held"}catch{}if(this.pendingCommit!==void 0)return this.retryPendingCommit(t);const n=$(),o=new Set(this.buffer.map(l=>l.entry_id)),a=this.pendingHandoffs.filter(l=>r||l.settleAtAgentSettled!==!0),d=new Set(a.flatMap(l=>[...l.entryIds])),h=[...this.claims.keys()].filter(l=>n||d.has(l)&&!o.has(l));return h.length===0?"settled":(this.pendingCommit={handoffs:a,entryIds:h,receipts:h.map(l=>{const c=this.claims.get(l);return{delivery_id:c.delivery_id,attempts:c.attempts,disposition:n?"released":"acknowledged"}})},this.retryPendingCommit(t))}detachPending(t){const e=[];for(let i=this.pendingHandoffs.length-1;i>=0;i-=1){const r=this.pendingHandoffs[i];t(r)&&e.push(...this.pendingHandoffs.splice(i,1))}return e.reverse(),e}}function se(s,t){p?.dispose("reload",!1);const e=new ne(s,t,++Q);p=e;const i=f(r=>e.prependHeldDeferredInbox(r),"promptJoin");globalThis[K]=i;try{e.start()}catch(r){throw e.dispose("reload",!1),r}return e}f(se,"installWatcher");function oe(s){const t=se(s,Z());return()=>t.dispose("shutdown",!1)}f(oe,"registerCanvasInboxWatcher");var _e=oe;export{_e as default,oe as registerCanvasInboxWatcher};
1
+ var A=Object.defineProperty;var l=(s,t)=>A(s,"name",{value:t,configurable:!0});import{envNodeId as D,envProfileId as H,envWatcherDebounceMs as T,envWatcherTickMs as q}from"../shared/env.js";import{coalesceBrokerInbox as U,entryCards as B}from"../core/runtime/broker/inbox.js";import{acknowledgeBrokerMail as J,claimBrokerMail as $,brokerExtensionState as W}from"../core/runtime/broker/daemon-ops.js";import{wasTurnRefused as G}from"../core/runtime/broker/extension-abort.js";import{isDaemonTransportApiError as R}from"../api/errors.js";import{announceMessageOrigin as X,messageSignature as b}from"../core/runtime/stamp/channel.js";import{captureGoalIfAbsent as j,generateAndCommitInitialName as L}from"./broker-local.js";import{emitEvent as V}from"../core/events/emit.js";import{errorClassFromError as z}from"../core/events/errors.js";import{operationIdContext as p}from"../core/events/operation-id.js";import{situationalContextEnvelope as Q,SITUATIONAL_CONTEXT_CUSTOM_TYPE as _}from"../core/runtime/situational-context.js";import{isProfilePaused as Y}from"../core/profiles/manifest.js";import{brokerIdleTurnStart as K,brokerRunTurnBusy as Z,HELD_DEFERRED_INBOX_PROMPT_JOIN as ee}from"../core/runtime/broker/held-deferred-inbox.js";const v=64,S=16;let m,te=0;class O extends Error{static{l(this,"WatcherFatalError")}constructor(t,e){super(t,{cause:e}),this.name="WatcherFatalError"}}function ie(){return{tickMs:q(),debounceMs:T()}}l(ie,"resolveCadence");function I(){const s=D();return s===void 0||s.trim()===""?void 0:s}l(I,"currentNodeId");function P(){const s=H();return s!==void 0&&s!==""&&Y(s)}l(P,"profilePaused");function E(s){try{return z(s)}catch{return{class:"unknown"}}}l(E,"safeErrorClass");function w(s){try{V(s)}catch{}}l(w,"emitBestEffort");function C(s){try{p.fresh(t=>{w({...s,operation_id:t})})}catch{}}l(C,"emitFreshBestEffort");function x(s,t){try{p.run(s,()=>{w({...t,operation_id:s})})}catch{}}l(x,"emitStoredBestEffort");function ne(s){return s.kind==="human"?{type:"human"}:{type:"runtime",kind:"inbox",entries:s.entries.map(t=>({...t.from===null?{}:{from:t.from},...t.from_name===void 0?{}:{fromName:t.from_name},kind:t.kind,tier:t.tier,...t.ref===void 0?{}:{ref:t.ref}}))}}l(ne,"deliveryOrigin");function F(s,t){if(s.length===0)throw new Error(`cannot create an empty ${t} delivery`);const e=[...new Set(s.map(n=>n.operation_id))].sort(),i=e.length-S;return{channel:t,entryIds:s.map(n=>n.entry_id),throughEntryId:s.at(-1).entry_id,sourceOperationIds:e.slice(0,S),...i>0?{sourceOperationIdsOmitted:i}:{}}}l(F,"deliveryFacts");function y(s){return{channel:s.channel,entry_ids:s.entryIds,through_entry_id:s.throughEntryId,source_operation_ids:s.sourceOperationIds,...s.sourceOperationIdsOmitted===void 0?{}:{source_operation_ids_omitted:s.sourceOperationIdsOmitted}}}l(y,"deliveryFields");function re(s){x(s.operationId,{level:"info",event:"inbox.delivery.completed",outcome:"succeeded",fields:y(s)})}l(re,"emitDeliveryCompleted");function M(s,t,e,i){x(s,{level:"error",event:"inbox.delivery.failed",outcome:"failed",error:i,error_class:E(i),fields:{stage:e,...y(t)}})}l(M,"emitDeliveryFailure");function k(s,t){x(s.operationId,{level:"error",event:"inbox.delivery.failed",outcome:"failed",error_class:{class:"unknown"},fields:{stage:"abandoned",reason:t,...y(s)}})}l(k,"emitDeliveryAbandoned");function se(s){return typeof s=="string"?s:Array.isArray(s)?s.filter(t=>typeof t=="object"&&t!==null&&typeof t.text=="string").map(t=>t.text).join(`
2
+ `):""}l(se,"messageText");function N(s){return s==="quit"||s==="reload"||s==="new"||s==="resume"||s==="fork"}l(N,"isSessionShutdownReason");function ae(s){switch(s){case"quit":return"shutdown";case"reload":case"new":case"resume":case"fork":return"reload";default:return s}}l(ae,"disposalReasonForShutdown");function de(s){return typeof s=="string"?s.slice(0,128):s===null?"null":s===void 0?"undefined":typeof s=="number"||typeof s=="boolean"||typeof s=="bigint"?String(s).slice(0,128):typeof s}l(de,"boundedRuntimeReason");class oe{static{l(this,"CanvasInboxWatcher")}pi;cadence;generation;timer;armed=!1;lastCtx;streaming=!1;runNode=!!process.env.CRTR_RUN_ID;nodeId;claims=new Map;tickInFlight;buffer=[];lastArrival=0;pendingHandoffs=[];pendingCommit;promptJoinInFlight=!1;replayUnseenInherited=!1;seeded=!1;disposed=!1;disposalReason;fatalError;fatalEscaped=!1;constructor(t,e,i){this.pi=t,this.cadence=e,this.generation=i}start(){const t=l((e,i)=>{this.canMutate()&&this.captureCtx(e,i)},"capture");this.pi.on("session_start",(e,i)=>{this.canMutate()&&(this.captureCtx(e,i),this.arm())}),this.pi.on("turn_end",t),this.pi.on("agent_start",(e,i)=>{this.canMutate()&&(this.captureCtx(e,i),this.streaming=!0)}),this.pi.on("agent_end",(e,i)=>{this.canMutate()&&(this.captureCtx(e,i),this.streaming=!1)}),this.pi.on("message_end",e=>{if(!this.canMutate())return;const i=e?.message;if(i?.role!=="user"&&i?.role!=="custom"||!this.pendingHandoffs.some(a=>a.awaitingDequeue!==void 0))return;const n=b(se(i.content)),r=this.pendingHandoffs.find(a=>a.awaitingDequeue===n);r!==void 0&&delete r.awaitingDequeue}),this.pi.on("agent_settled",async(e,i)=>{if(!this.canMutate())return;this.captureCtx(e,i);const n=I();if(n!==void 0)try{this.assertNodeOwnership(n,"settle"),await this.tickInFlight,this.seeded||await this.claimMail(n);const r=await this.settle(n,i,!1,!0);r==="refresh_held"&&this.dispose("refresh",!1),this.runNode&&r==="settled"&&this.canMutate()&&this.buffer.length>0&&this.flushOrdinary(n)}catch(r){this.dispose("shutdown",!1,void 0,{error:r,stage:"settle"})}}),this.pi.on("session_shutdown",async e=>{if(!this.canMutate())return;let i;try{i=e?.reason}catch{i=void 0}const n=N(i)?ae(i):"reload";N(i)||C({level:"warn",event:"inbox.lifecycle.unknown_shutdown_reason",outcome:"failed",fields:{reason:de(i)}});try{await this.disposeAtSettlement(n,this.lastCtx)}catch(r){this.dispose(n,!1,void 0,{error:r,stage:"settle"})}})}arm(){this.armed||(this.armed=!0,this.timer=setInterval(()=>this.runTick(),this.cadence.tickMs),typeof this.timer.unref=="function"&&this.timer.unref(),this.runTick("schedule"))}async disposeAtSettlement(t,e){const i=I();if(i===void 0){this.dispose(t,!1);return}try{this.assertNodeOwnership(i,"settle");const n=await this.settle(i,e,t!=="refresh");this.dispose(n==="refresh_held"?"refresh":t,!1)}catch(n){this.dispose(t,!1,void 0,{error:n,stage:"settle"})}}dispose(t,e,i,n){if(this.disposed)return;this.disposed=!0,this.disposalReason=t,this.clearTimer();const r=n;{const a=[...new Set([...this.pendingCommit?.handoffs??[],...this.pendingHandoffs.splice(0)])];this.buffer.length=0,this.claims.clear(),this.pendingCommit=void 0,this.promptJoinInFlight=!1,this.replayUnseenInherited=!1,this.nodeId=void 0,this.lastCtx=void 0,this.lastArrival=0,this.streaming=!1,this.seeded=!1,this.ownsCurrentGeneration()&&(m=void 0);for(const d of a)k(d,t)}if(r!==void 0){this.scheduleHandlerFatal(r.error,r.stage);return}}ownsCurrentGeneration(){return m===this&&m.generation===this.generation}canMutate(){return this.ownsCurrentGeneration()&&!this.disposed&&this.fatalError===void 0}captureCtx(t,e){e!==void 0&&(this.lastCtx=e)}clearTimer(){this.timer!==void 0&&(clearInterval(this.timer),this.timer=void 0)}isIdle(){if(this.runNode&&Z())return!1;try{if(typeof this.lastCtx?.isIdle=="function")return this.lastCtx.isIdle()===!0}catch{}return!this.streaming}assertNodeOwnership(t,e){!this.seeded||this.nodeId===void 0||this.nodeId===t||this.raiseReadFatal(e,new Error(`watcher node changed from ${this.nodeId} to ${t}`))}raiseFatal(t,e,i,n){throw this.fatalError===void 0&&(this.fatalError=new O(e,i),this.clearTimer(),C({level:"error",event:t,outcome:"failed",error:i,error_class:E(i),fields:n})),this.fatalError}raiseReadFatal(t,e){return this.raiseFatal("inbox.read.failed",`inbox ${t} state is corrupt`,e,{stage:t})}raiseSituationalFatal(t,e){return this.raiseFatal("inbox.situational_context.missing","situational context marker has no readable sidecar",e,{entry_id:t})}escapeFatal(t,e){if(!this.fatalEscaped){if(this.fatalEscaped=!0,e==="throw")throw t;queueMicrotask(()=>{throw t})}}scheduleHandlerFatal(t,e){let i;if(t instanceof O)i=t;else try{this.raiseReadFatal(e,t)}catch(n){i=n}this.escapeFatal(i,"schedule")}runTick(t="throw"){if(!this.canMutate()||this.tickInFlight!==void 0)return;const e=this.tick().catch(i=>{if(this.canMutate()){if(R(i)){C({level:"warn",event:"inbox.read.failed",outcome:"failed",error:i,error_class:E(i),fields:{stage:"poll"}});return}this.scheduleHandlerFatal(i,"poll")}}).finally(()=>{this.tickInFlight===e&&(this.tickInFlight=void 0)});this.tickInFlight=e}async claimMail(t){this.assertNodeOwnership(t,"poll");let e;try{e=await $(t,"wake")}catch(a){throw R(a)&&(this.replayUnseenInherited=!0),a}if(!this.canMutate()||e.action==="hold")return!1;const i=this.replayUnseenInherited;this.replayUnseenInherited=!1,this.nodeId=t,this.seeded=!0;const n=new Set(e.deliveries.map(a=>a.entry.entry_id)),r=this.buffer.filter(a=>!n.has(a.entry_id));for(const a of r)this.claims.delete(a.entry_id);this.buffer.splice(0,this.buffer.length,...this.buffer.filter(a=>n.has(a.entry_id)));for(const a of e.deliveries){const d=a.entry.entry_id;this.claims.has(d)||(this.claims.set(d,a),a.handoff==="inherited"&&!i?p.fresh(f=>{this.pendingHandoffs.push({...F([a.entry],"visible"),operationId:f,settleAtAgentSettled:!0})}):(this.buffer.push(a.entry),this.lastArrival=Date.now()))}return!0}async tick(){const t=I();if(t!==void 0){if(this.pendingCommit!==void 0){await this.retryPendingCommit(t)==="refresh_held"&&this.canMutate()&&this.dispose("refresh",!1);return}this.promptJoinInFlight||P()||this.pendingHandoffs.length>=v||await this.claimMail(t)&&this.buffer.length>0&&(!this.runNode||this.isIdle()||this.buffer.some(e=>e.tier==="critical"))&&Date.now()-this.lastArrival>=this.cadence.debounceMs&&this.flushOrdinary(t)}}missingChannelEntries(t){const e=t.filter(r=>this.claims.has(r.entry_id)),i=this.coveredEntryIds("hidden"),n=this.coveredEntryIds("visible");return{hiddenEntries:e.filter(r=>(r.data?.situational===!0||r.data?.situationalOnly===!0)&&!i.has(r.entry_id)),visibleEntries:e.filter(r=>r.data?.situationalOnly!==!0&&!n.has(r.entry_id))}}visibleRoute(t){return t.length===0?"none":this.isIdle()?"idle":this.runNode?t.some(e=>e.tier==="critical")?"critical":"none":t.some(e=>e.tier==="critical")?"critical":t.some(e=>e.tier==="urgent"||e.kind==="final")?"steer":"followUp"}buildPlan(t){const{hiddenEntries:e,visibleEntries:i}=this.missingChannelEntries(t),n=new Set(e.map(u=>u.entry_id)),r=new Set(i.map(u=>u.entry_id)),a=t.filter(u=>n.has(u.entry_id)||r.has(u.entry_id)),d=this.isIdle()&&a.length>0&&a.every(u=>u.tier==="deferred"),f=this.visibleRoute(i)==="critical",o=!d&&!f&&e.length>0,c=!d&&!f&&i.length>0;return{hiddenEntries:e,visibleEntries:i,deferredHold:d,sendCount:Number(o)+Number(c)}}ordinaryPlan(){return this.buildPlan(this.buffer)}contextCards(t,e){const i=[];if(e.some(n=>n.data?.situational===!0)){const n=e.at(-1).entry_id;let r;try{r=Q(t)}catch(a){this.raiseSituationalFatal(n,a)}r===null&&this.raiseSituationalFatal(n,new Error(`missing situational context for entry ${n}`)),i.push(r)}for(const n of e)n.data?.situationalOnly===!0&&i.push(...B(n));return i}digest(t,e){try{return U(t)}catch(i){this.raiseReadFatal(e,i)}}sendDelivery(t,e,i,n,r){this.pendingHandoffs.length>=v&&this.raiseReadFatal(n,new Error(`pending handoff capacity exceeded before ${t} send`));let a;try{a=F(e,t)}catch(o){this.raiseReadFatal(n,o)}let d;try{p.fresh(o=>{d=o,w({level:"info",event:"inbox.delivery.started",operation_id:o,fields:y(a)}),i()})}catch(o){return d===void 0&&this.raiseReadFatal(n,o),M(d,a,"send",o),"failed"}d===void 0&&this.raiseReadFatal(n,new Error(`${t} delivery returned without an operation id`));const f={operationId:d,...a,...r===void 0?{}:{awaitingDequeue:r}};return this.canMutate()?(this.pendingHandoffs.push(f),"handed-off"):(this.disposed&&this.disposalReason!==void 0&&k(f,this.disposalReason),"inactive")}sendContext(t,e,i,n,r,a){const d=n==="steer"||n==="followUp"?n:this.isIdle()?void 0:"followUp",f=d===void 0||i.length===0?void 0:b(i.at(-1));return this.sendDelivery("hidden",e,()=>{this.runNode&&r&&this.pi.appendEntry("crtr-turn-input",{message_ids:e.map(o=>o.entry_id)}),i.forEach((o,c)=>{const u=r&&c===i.length-1;this.pi.sendMessage({customType:_,content:o,display:!0,details:{nodeId:t}},d!==void 0?{deliverAs:d}:u?{deliverAs:"followUp",triggerTurn:!0}:{})})},a,f)}sendVisible(t,e,i,n,r,a){return this.sendDelivery("visible",t,()=>{if(r!=="idle"&&r!=="steer"&&r!=="followUp")throw new Error(`visible send requested for non-send route ${r}`);for(const d of e)this.pi.sendMessage({customType:_,content:d,display:!0},r==="idle"?{}:{deliverAs:r});if(X(i,n),r==="idle"){const d=K();if(d===void 0)throw new Error("broker idle-turn admission is unavailable");d(i,this.runNode?t.map(f=>f.entry_id):[])}else this.pi.sendUserMessage(i,{deliverAs:r})},a,r==="steer"||r==="followUp"?b(i):void 0)}abortCritical(){try{this.lastCtx?.abort?.()}catch{}}requeueFromBatch(t,e){if(e.size===0)return;const i=t.filter(a=>e.has(a.entry_id)),n=new Set(i.map(a=>a.entry_id)),r=this.buffer.filter(a=>!n.has(a.entry_id));this.buffer.splice(0,this.buffer.length,...i,...r)}executePlan(t,e,i){const n=new Set,r=this.visibleRoute(e.visibleEntries);if(r==="critical"){if(this.abortCritical(),!this.canMutate())return{inactive:!0,requeueEntryIds:n};for(const o of e.visibleEntries)n.add(o.entry_id);for(const o of e.hiddenEntries)n.add(o.entry_id);return{inactive:!1,requeueEntryIds:n}}if(this.runNode&&r==="none")return{inactive:!1,requeueEntryIds:new Set([...e.hiddenEntries,...e.visibleEntries].map(o=>o.entry_id))};const a=e.visibleEntries.length>0?this.digest(e.visibleEntries,i):[],[d,...f]=a;for(const o of f)for(const c of o.entries)n.add(c.entry_id);if(e.hiddenEntries.length>0){const o=this.contextCards(t,e.hiddenEntries),c=this.sendContext(t,e.hiddenEntries,o,r,d===void 0,i);if(c==="inactive")return{inactive:!0,requeueEntryIds:n};if(c==="failed")for(const u of e.hiddenEntries)n.add(u.entry_id)}if(!this.canMutate())return{inactive:!0,requeueEntryIds:n};if(d!==void 0){const o=this.sendVisible(d.entries,d.cards,d.text,ne(d),r,i);if(o==="inactive")return{inactive:!0,requeueEntryIds:n};if(o==="failed")for(const c of d.entries)n.add(c.entry_id);else d.kind==="human"&&(j(t,d.text),L(t,d.text))}return{inactive:!1,requeueEntryIds:n}}flushOrdinary(t){if(this.buffer.length===0)return"empty";const e=this.ordinaryPlan();if(e.deferredHold)return"held";if(this.pendingHandoffs.length+e.sendCount>v)return"capacity-blocked";const i=[...this.buffer],n=this.executePlan(t,e,"poll");return n.inactive||(this.buffer.splice(0,i.length),this.requeueFromBatch(i,n.requeueEntryIds)),"attempted"}async prependHeldDeferredInbox(t){if(!this.canMutate()||this.nodeId===void 0||P())return;const e=this.ordinaryPlan();if(!e.deferredHold)return;const i=e.visibleEntries.length===0?[]:this.digest(e.visibleEntries,"poll"),n=+(e.hiddenEntries.length>0)+i.length;if(this.pendingHandoffs.length+n>v)return;const r=[...this.buffer];this.promptJoinInFlight=!0;try{this.runNode&&this.pi.appendEntry("crtr-turn-input",{message_ids:[...e.hiddenEntries,...e.visibleEntries].map(a=>a.entry_id)}),e.hiddenEntries.length>0&&await this.sendPromptJoinDelivery(t,"hidden",e.hiddenEntries,this.contextCards(this.nodeId,e.hiddenEntries));for(const a of i)await this.sendPromptJoinDelivery(t,"visible",a.entries,[...a.cards,a.text]);if(!this.canMutate())return;this.buffer.splice(0,r.length)}finally{this.promptJoinInFlight=!1}}async sendPromptJoinDelivery(t,e,i,n){let r;try{r=F(i,e)}catch(f){this.raiseReadFatal("poll",f)}let a;try{await p.fresh(async f=>{a=f,w({level:"info",event:"inbox.delivery.started",operation_id:f,fields:y(r)});for(const o of n)await t.sendCustomMessage({customType:_,content:o,display:!0})})}catch(f){throw a===void 0&&this.raiseReadFatal("poll",f),M(a,r,"send",f),f}a===void 0&&this.raiseReadFatal("poll",new Error(`${e} prompt-join delivery returned without an operation id`));const d={operationId:a,...r,settleAtAgentSettled:!0};if(!this.canMutate()){this.disposed&&this.disposalReason!==void 0&&k(d,this.disposalReason);return}this.pendingHandoffs.push(d)}coveredEntryIds(t){const e=new Set;for(const i of this.pendingHandoffs)if(i.channel===t)for(const n of i.entryIds)e.add(n);return e}retryPendingCommit(t){const e=this.pendingCommit;if(e===void 0)return Promise.resolve("settled");if(e.attempt!==void 0)return e.attempt;const i=this.attemptPendingCommit(t,e).finally(()=>{e.attempt===i&&(e.attempt=void 0)});return e.attempt=i,i}async attemptPendingCommit(t,e){let i=!1;try{const r=await J(t,e.receipts);if(r.action==="hold")return"refresh_held";for(const a of e.receipts){const d=r.results.find(f=>f.delivery_id===a.delivery_id);if(d?.outcome!==a.disposition&&d?.outcome!=="stale")throw new Error("daemon returned no terminal mail settlement outcome")}i=r.results.every(a=>a.outcome==="acknowledged")}catch(r){if(this.pendingCommit===e)for(const a of e.handoffs)M(a.operationId,a,"receipt_commit",r);return"held"}if(this.pendingCommit!==e)return"settled";for(const r of e.entryIds)this.claims.delete(r);if(e.receipts.some(r=>r.disposition==="released")){const r=new Set(e.entryIds);this.buffer.splice(0,this.buffer.length,...this.buffer.filter(a=>!r.has(a.entry_id)))}this.pendingCommit=void 0;const n=this.detachPending(r=>r.entryIds.every(a=>!this.claims.has(a)));for(const r of n)i&&re(r);return"settled"}async settle(t,e,i,n=!1){if(i)try{if(e?.hasPendingMessages?.()===!0)return"held"}catch{}if(this.pendingCommit!==void 0)return this.retryPendingCommit(t);const r=G(),a=!r&&this.pendingHandoffs.some(h=>h.awaitingDequeue!==void 0)&&await this.nodeRefreshing(t);if(this.pendingCommit!==void 0)return this.retryPendingCommit(t);const d=new Set(this.buffer.map(h=>h.entry_id)),f=new Set(a?this.pendingHandoffs.filter(h=>h.awaitingDequeue!==void 0).flatMap(h=>[...h.entryIds]):[]),o=this.pendingHandoffs.filter(h=>(n||h.settleAtAgentSettled!==!0)&&h.entryIds.every(g=>!f.has(g))),c=new Set(o.flatMap(h=>[...h.entryIds])),u=[...this.claims.keys()].filter(h=>r||c.has(h)&&!d.has(h));return u.length===0?"settled":(this.pendingCommit={handoffs:o,entryIds:u,receipts:u.map(h=>{const g=this.claims.get(h);return{delivery_id:g.delivery_id,attempts:g.attempts,disposition:r?"released":"acknowledged"}})},this.retryPendingCommit(t))}async nodeRefreshing(t){try{return(await W(t)).node.intent==="refresh"}catch{return!0}}detachPending(t){const e=[];for(let i=this.pendingHandoffs.length-1;i>=0;i-=1){const n=this.pendingHandoffs[i];t(n)&&e.push(...this.pendingHandoffs.splice(i,1))}return e.reverse(),e}}function fe(s,t){m?.dispose("reload",!1);const e=new oe(s,t,++te);m=e;const i=l(n=>e.prependHeldDeferredInbox(n),"promptJoin");globalThis[ee]=i;try{e.start()}catch(n){throw e.dispose("reload",!1),n}return e}l(fe,"installWatcher");function le(s){const t=fe(s,ie());return()=>t.dispose("shutdown",!1)}l(le,"registerCanvasInboxWatcher");var xe=le;export{xe as default,le as registerCanvasInboxWatcher};
@@ -23,7 +23,7 @@ interface PiLike {
23
23
  * Render drained passive entries (oldest first) into one XML pre-text block.
24
24
  * Each accumulated message is its own timestamped `<update>` element.
25
25
  */
26
- export declare function formatPassive(entries: BrokerPassiveEntry[], reportNodes?: ReadonlyMap<string, unknown>): string;
26
+ export declare function formatPassive(entries: BrokerPassiveEntry[], nodeId?: string): Promise<string>;
27
27
  /**
28
28
  * Place the backlog block on a message without displacing a runtime card.
29
29
  *