@north-light/crouter 0.3.349 → 0.3.351

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (629) hide show
  1. package/bin/crtr-launcher +4 -0
  2. package/bin/runtime-generation-manifest.mjs +12 -2
  3. package/dist/api/client.d.ts +50 -7
  4. package/dist/api/client.js +2 -2
  5. package/dist/api/dto/analytics.d.ts +184 -0
  6. package/dist/api/dto/analytics.js +0 -0
  7. package/dist/api/dto/broker-ops.d.ts +43 -1
  8. package/dist/api/dto/config.d.ts +11 -0
  9. package/dist/api/dto/grants.d.ts +14 -0
  10. package/dist/api/dto/grants.js +0 -0
  11. package/dist/api/dto/human-requests.d.ts +14 -0
  12. package/dist/api/dto/memory.d.ts +6 -0
  13. package/dist/api/dto/modelauth.d.ts +35 -0
  14. package/dist/api/dto/node-records.d.ts +35 -0
  15. package/dist/api/dto/node-records.js +0 -0
  16. package/dist/api/dto/nodes.d.ts +5 -0
  17. package/dist/api/dto/profiles.d.ts +38 -3
  18. package/dist/api/dto/worktree.d.ts +11 -0
  19. package/dist/api/errors.d.ts +23 -1
  20. package/dist/api/errors.js +1 -1
  21. package/dist/api/index.d.ts +2 -0
  22. package/dist/api/index.js +1 -1
  23. package/dist/api/node-transport.js +1 -1
  24. package/dist/api/routes.d.ts +22 -0
  25. package/dist/api/routes.js +1 -1
  26. package/dist/build-root.d.ts +6 -1
  27. package/dist/build-root.js +1 -1
  28. package/dist/builtin-memory/crouter-sdk/client.md +34 -0
  29. package/dist/builtin-memory/crouter-sdk/errors.md +2 -0
  30. package/dist/builtin-memory/crouter-sdk/memory.md +2 -2
  31. package/dist/builtin-memory/crouter-sdk/streaming.md +21 -0
  32. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/claude-plugin-commands.ts +8 -4
  33. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/memory-slash-commands.ts +39 -118
  34. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.d.ts +6 -1
  35. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.js +41 -27
  36. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.ts +52 -29
  37. package/dist/cli.js +9 -8
  38. package/dist/clients/attach/chrome/inbox-strip.js +1 -1
  39. package/dist/clients/attach/chrome/roster.js +1 -1
  40. package/dist/clients/attach/config.js +1 -1
  41. package/dist/clients/attach/overlays/auth.js +2 -2
  42. package/dist/clients/attach/overlays/graph.js +1 -1
  43. package/dist/clients/attach/render/tool-calls.js +3 -3
  44. package/dist/clients/attach/session/connection.js +1 -1
  45. package/dist/clients/attach/session/profile-files.js +1 -1
  46. package/dist/clients/attach/viewer.js +1569 -816
  47. package/dist/commands/api-client.js +3 -3
  48. package/dist/commands/broker-permissions.d.ts +2 -0
  49. package/dist/commands/broker-permissions.js +1 -0
  50. package/dist/commands/canvas-analytics/chart.d.ts +52 -0
  51. package/dist/commands/canvas-analytics/chart.js +1 -0
  52. package/dist/commands/canvas-analytics/drilldown.d.ts +34 -0
  53. package/dist/commands/canvas-analytics/drilldown.js +1 -0
  54. package/dist/commands/canvas-analytics/format.d.ts +29 -0
  55. package/dist/commands/canvas-analytics/format.js +1 -0
  56. package/dist/commands/canvas-analytics/graph-detail.d.ts +2 -0
  57. package/dist/commands/canvas-analytics/graph-detail.js +2 -0
  58. package/dist/commands/canvas-analytics/graphs.d.ts +9 -0
  59. package/dist/commands/canvas-analytics/graphs.js +1 -0
  60. package/dist/commands/canvas-analytics/memory.d.ts +2 -0
  61. package/dist/commands/canvas-analytics/memory.js +1 -0
  62. package/dist/commands/canvas-analytics/overview.d.ts +2 -0
  63. package/dist/commands/canvas-analytics/overview.js +1 -0
  64. package/dist/commands/canvas-analytics/shell.d.ts +60 -0
  65. package/dist/commands/canvas-analytics/shell.js +2 -0
  66. package/dist/commands/canvas-analytics/time.d.ts +2 -0
  67. package/dist/commands/canvas-analytics/time.js +1 -0
  68. package/dist/commands/canvas-analytics/usage.d.ts +2 -0
  69. package/dist/commands/canvas-analytics/usage.js +1 -0
  70. package/dist/commands/canvas-analytics/view.d.ts +85 -0
  71. package/dist/commands/canvas-analytics/view.js +1 -0
  72. package/dist/commands/canvas-analytics.d.ts +2 -0
  73. package/dist/commands/canvas-analytics.js +1 -0
  74. package/dist/commands/canvas-prune.js +1 -1
  75. package/dist/commands/canvas.js +1 -1
  76. package/dist/commands/cron.js +5 -5
  77. package/dist/commands/human/components.d.ts +2 -0
  78. package/dist/commands/human/components.js +2 -2
  79. package/dist/commands/human/prompts.js +1 -1
  80. package/dist/commands/human/queue.js +1 -1
  81. package/dist/commands/memory/client.d.ts +11 -0
  82. package/dist/commands/memory/client.js +1 -0
  83. package/dist/commands/memory/delete.js +1 -1
  84. package/dist/commands/memory/edit.js +3 -3
  85. package/dist/commands/memory/find.js +1 -1
  86. package/dist/commands/memory/history.js +4 -4
  87. package/dist/commands/memory/lint.js +1 -1
  88. package/dist/commands/memory/list.d.ts +0 -2
  89. package/dist/commands/memory/list.js +1 -1
  90. package/dist/commands/memory/move.js +1 -1
  91. package/dist/commands/memory/origin.js +1 -1
  92. package/dist/commands/memory/read.d.ts +0 -5
  93. package/dist/commands/memory/read.js +3 -3
  94. package/dist/commands/memory/shared.d.ts +0 -178
  95. package/dist/commands/memory/shared.js +1 -12
  96. package/dist/commands/memory/write.js +5 -5
  97. package/dist/commands/node/bash.js +5 -5
  98. package/dist/commands/node/create.d.ts +0 -17
  99. package/dist/commands/node/create.js +2 -3
  100. package/dist/commands/node/inspect.js +6 -6
  101. package/dist/commands/node/lifecycle.js +2 -2
  102. package/dist/commands/node-context.js +2 -2
  103. package/dist/commands/node-inspect-artifacts.js +6 -6
  104. package/dist/commands/pkg/browse/catalog.js +1 -1
  105. package/dist/commands/pkg/browse/model.d.ts +1 -1
  106. package/dist/commands/pkg/market-manage.js +1 -1
  107. package/dist/commands/pkg/plugin-manage.js +10 -10
  108. package/dist/commands/profile/daemon-profiles.d.ts +13 -0
  109. package/dist/commands/profile/daemon-profiles.js +4 -0
  110. package/dist/commands/profile/delete.js +1 -1
  111. package/dist/commands/profile/env.d.ts +6 -0
  112. package/dist/commands/profile/env.js +2 -2
  113. package/dist/commands/profile/kind.js +1 -2
  114. package/dist/commands/profile/list.js +1 -1
  115. package/dist/commands/profile/meta.js +1 -1
  116. package/dist/commands/profile/new.js +1 -1
  117. package/dist/commands/profile/pause.js +1 -1
  118. package/dist/commands/profile/project.js +1 -1
  119. package/dist/commands/profile/rename.js +1 -1
  120. package/dist/commands/profile/show.js +1 -1
  121. package/dist/commands/profile.js +1 -1
  122. package/dist/commands/push.js +3 -3
  123. package/dist/commands/surface-inspect.js +1 -1
  124. package/dist/commands/sys/branch.js +1 -1
  125. package/dist/commands/sys/config.js +1 -1
  126. package/dist/commands/sys/connect.js +3 -3
  127. package/dist/commands/sys/context/admin/actions.js +1 -1
  128. package/dist/commands/sys/context/admin/model.d.ts +1 -0
  129. package/dist/commands/sys/context/admin/model.js +1 -1
  130. package/dist/commands/sys/context/admin.js +1 -1
  131. package/dist/commands/sys/context/expose.js +2 -1
  132. package/dist/commands/sys/context/prompt-review.js +2 -2
  133. package/dist/commands/sys/context/resolve.js +7 -7
  134. package/dist/commands/sys/context/sysprompt.js +1 -1
  135. package/dist/commands/sys/join.d.ts +1 -0
  136. package/dist/commands/sys/join.js +1 -0
  137. package/dist/commands/sys/migrate.js +1 -1
  138. package/dist/commands/sys/panels/models-panel.js +1 -1
  139. package/dist/commands/sys/panels/profiles-panel.d.ts +0 -1
  140. package/dist/commands/sys/panels/profiles-panel.js +1 -1
  141. package/dist/commands/sys/provider-login.js +6 -6
  142. package/dist/commands/sys/setup-core.d.ts +1 -1
  143. package/dist/commands/sys/setup-core.js +6 -6
  144. package/dist/commands/sys/setup-settings-runner.js +1 -1
  145. package/dist/commands/sys/setup.js +1 -1
  146. package/dist/commands/sys/spaces.d.ts +1 -0
  147. package/dist/commands/sys/spaces.js +2 -0
  148. package/dist/commands/sys/sync-deps.js +2 -2
  149. package/dist/commands/sys/sync-project-guidance.js +4 -4
  150. package/dist/commands/sys/sync-skills.js +2 -2
  151. package/dist/commands/sys/worktrees.d.ts +1 -0
  152. package/dist/commands/sys/worktrees.js +1 -1
  153. package/dist/commands/sys.js +1 -1
  154. package/dist/core/auth-file.js +2 -2
  155. package/dist/core/bash-job-supervisor.d.ts +6 -0
  156. package/dist/core/bash-job-supervisor.js +4 -0
  157. package/dist/core/bash-jobs.d.ts +13 -6
  158. package/dist/core/bash-jobs.js +8 -7
  159. package/dist/core/broker-client/transport-relay.d.ts +6 -3
  160. package/dist/core/broker-client/transport-relay.js +1 -1
  161. package/dist/core/broker-client/transport-socket.d.ts +6 -1
  162. package/dist/core/broker-client/transport-socket.js +1 -1
  163. package/dist/core/canvas/canvas.d.ts +39 -18
  164. package/dist/core/canvas/canvas.js +21 -20
  165. package/dist/core/canvas/context-strip.d.ts +20 -0
  166. package/dist/core/canvas/context-strip.js +5 -0
  167. package/dist/core/canvas/crons.d.ts +12 -20
  168. package/dist/core/canvas/crons.js +15 -13
  169. package/dist/core/canvas/db.js +2 -2
  170. package/dist/core/canvas/deliveries.d.ts +4 -1
  171. package/dist/core/canvas/deliveries.js +1 -1
  172. package/dist/core/canvas/executions.js +1 -1
  173. package/dist/core/canvas/history.d.ts +2 -1
  174. package/dist/core/canvas/history.js +17 -18
  175. package/dist/core/canvas/memory-reads.d.ts +19 -0
  176. package/dist/core/canvas/memory-reads.js +1 -0
  177. package/dist/core/canvas/migrations.d.ts +0 -4
  178. package/dist/core/canvas/migrations.js +99 -32
  179. package/dist/core/canvas/nav-render.js +1 -1
  180. package/dist/core/canvas/node-agent-paths.d.ts +8 -0
  181. package/dist/core/canvas/node-agent-paths.js +1 -0
  182. package/dist/core/canvas/node-recap.d.ts +2 -2
  183. package/dist/core/canvas/node-recap.js +2 -2
  184. package/dist/core/canvas/node-tokens.d.ts +24 -0
  185. package/dist/core/canvas/node-tokens.js +5 -0
  186. package/dist/core/canvas/paths.d.ts +16 -19
  187. package/dist/core/canvas/paths.js +1 -1
  188. package/dist/core/canvas/render-source.d.ts +2 -2
  189. package/dist/core/canvas/render-source.js +6 -9
  190. package/dist/core/canvas/sessions.d.ts +18 -0
  191. package/dist/core/canvas/sessions.js +4 -1
  192. package/dist/core/canvas/types.d.ts +22 -6
  193. package/dist/core/command-hooks/compose.js +1 -1
  194. package/dist/core/command-hooks/discovery.d.ts +15 -1
  195. package/dist/core/command-hooks/discovery.js +1 -1
  196. package/dist/core/command-hooks/help.d.ts +2 -2
  197. package/dist/core/command-hooks/lifecycle-create.d.ts +1 -1
  198. package/dist/core/command-hooks/lifecycle-create.js +1 -1
  199. package/dist/core/command-hooks/transport/exec-invoke.d.ts +2 -0
  200. package/dist/core/command-hooks/transport/exec-invoke.js +1 -1
  201. package/dist/core/command-hooks/transport/exec-lifecycle.d.ts +1 -0
  202. package/dist/core/command-hooks/transport/exec-lifecycle.js +1 -1
  203. package/dist/core/command-hooks/transport/plan.d.ts +3 -0
  204. package/dist/core/command-hooks/transport/plan.js +1 -0
  205. package/dist/core/command-plugins/discovery.js +1 -1
  206. package/dist/core/command.d.ts +6 -2
  207. package/dist/core/command.js +6 -6
  208. package/dist/core/config.d.ts +8 -5
  209. package/dist/core/config.js +1 -1
  210. package/dist/core/conversation-store/client-worker.d.ts +1 -0
  211. package/dist/core/conversation-store/client-worker.js +1 -0
  212. package/dist/core/conversation-store/client.d.ts +2 -0
  213. package/dist/core/conversation-store/client.js +2 -0
  214. package/dist/core/conversation-store/file-store.d.ts +37 -0
  215. package/dist/core/conversation-store/file-store.js +9 -0
  216. package/dist/core/conversation-store/index.d.ts +50 -0
  217. package/dist/core/conversation-store/index.js +1 -0
  218. package/dist/core/conversation-store/listener.d.ts +4 -0
  219. package/dist/core/conversation-store/listener.js +3 -0
  220. package/dist/core/conversation-store/patch.d.ts +1 -0
  221. package/dist/core/conversation-store/patch.js +1 -0
  222. package/dist/core/directory/join.d.ts +27 -0
  223. package/dist/core/directory/join.js +1 -0
  224. package/dist/core/disk-usage.d.ts +4 -0
  225. package/dist/core/disk-usage.js +1 -0
  226. package/dist/core/events/emit.d.ts +2 -0
  227. package/dist/core/events/emit.js +3 -1
  228. package/dist/core/feed/feed.js +4 -4
  229. package/dist/core/feed/messages.d.ts +3 -0
  230. package/dist/core/feed/messages.js +6 -6
  231. package/dist/core/fs-utils.d.ts +2 -0
  232. package/dist/core/fs-utils.js +3 -3
  233. package/dist/core/grants/local.d.ts +4 -0
  234. package/dist/core/grants/local.js +1 -0
  235. package/dist/core/grants/mirror.d.ts +44 -0
  236. package/dist/core/grants/mirror.js +4 -0
  237. package/dist/core/grants/on-sync.d.ts +22 -0
  238. package/dist/core/grants/on-sync.js +1 -0
  239. package/dist/core/grants/remove.d.ts +7 -0
  240. package/dist/core/grants/remove.js +1 -0
  241. package/dist/core/grants/sandboxes.d.ts +7 -0
  242. package/dist/core/grants/sandboxes.js +1 -0
  243. package/dist/core/grants/sync.d.ts +12 -0
  244. package/dist/core/grants/sync.js +1 -0
  245. package/dist/core/help/memory-extensions.d.ts +3 -0
  246. package/dist/core/help/memory-extensions.js +2 -0
  247. package/dist/core/help.d.ts +14 -0
  248. package/dist/core/help.js +7 -7
  249. package/dist/core/host-exports/builtins.js +3 -3
  250. package/dist/core/host-exports/export.js +3 -3
  251. package/dist/core/human/action-binding.d.ts +2 -0
  252. package/dist/core/human/action-binding.js +1 -1
  253. package/dist/core/human/feedback-companion.d.ts +0 -1
  254. package/dist/core/human/feedback-companion.js +1 -1
  255. package/dist/core/human/page-schema.d.ts +1 -1
  256. package/dist/core/inspector/core.d.ts +2 -0
  257. package/dist/core/inspector/core.js +1 -1
  258. package/dist/core/inspector/tui.js +2 -2
  259. package/dist/core/installed-plugins.js +1 -1
  260. package/dist/core/io.js +6 -6
  261. package/dist/core/keybindings/catalog.d.ts +1 -1
  262. package/dist/core/keybindings/catalog.js +1 -1
  263. package/dist/core/layout-migrate/index.d.ts +15 -0
  264. package/dist/core/layout-migrate/index.js +4 -0
  265. package/dist/core/layout-migrate/paths.d.ts +26 -0
  266. package/dist/core/layout-migrate/paths.js +1 -0
  267. package/dist/core/layout-migrate/stored-paths.d.ts +2 -0
  268. package/dist/core/layout-migrate/stored-paths.js +11 -0
  269. package/dist/core/layout-migrate/stores.d.ts +17 -0
  270. package/dist/core/layout-migrate/stores.js +4 -0
  271. package/dist/core/layout.d.ts +26 -0
  272. package/dist/core/layout.js +2 -0
  273. package/dist/core/llm/run.d.ts +60 -0
  274. package/dist/core/llm/run.js +4 -0
  275. package/dist/core/memory/cli-selector.d.ts +13 -0
  276. package/dist/core/memory/cli-selector.js +1 -0
  277. package/dist/core/memory/history.d.ts +5 -4
  278. package/dist/core/memory/history.js +6 -6
  279. package/dist/core/memory/inline-ref-inventory.d.ts +2 -1
  280. package/dist/core/memory/inline-ref-inventory.js +1 -1
  281. package/dist/core/memory/lint.js +2 -2
  282. package/dist/core/memory/mutation-domain.d.ts +2 -2
  283. package/dist/core/memory/mutation-domain.js +8 -7
  284. package/dist/core/memory/mutations.js +1 -1
  285. package/dist/core/memory/service.d.ts +5 -0
  286. package/dist/core/memory/service.js +2 -2
  287. package/dist/core/memory-resolver.d.ts +11 -7
  288. package/dist/core/memory-resolver.js +2 -2
  289. package/dist/core/model-auth/daemon-login.d.ts +13 -0
  290. package/dist/core/model-auth/daemon-login.js +1 -0
  291. package/dist/core/model-auth/flows.d.ts +45 -0
  292. package/dist/core/model-auth/flows.js +1 -0
  293. package/dist/core/model-auth/handoff-jti.d.ts +4 -0
  294. package/dist/core/model-auth/handoff-jti.js +1 -0
  295. package/dist/core/model-routes.js +1 -1
  296. package/dist/core/nested-stores.d.ts +2 -1
  297. package/dist/core/nested-stores.js +1 -2
  298. package/dist/core/preview-registry.js +2 -2
  299. package/dist/core/profiles/env-store.js +2 -2
  300. package/dist/core/profiles/manifest.d.ts +16 -5
  301. package/dist/core/profiles/manifest.js +1 -1
  302. package/dist/core/provider-management.js +1 -1
  303. package/dist/core/review/birth.js +1 -1
  304. package/dist/core/review/companion.d.ts +0 -2
  305. package/dist/core/review/companion.js +1 -1
  306. package/dist/core/review/fork.js +2 -2
  307. package/dist/core/review/realize.js +1 -1
  308. package/dist/core/review/stage.d.ts +1 -1
  309. package/dist/core/review/stage.js +1 -1
  310. package/dist/core/review/types.d.ts +1 -1
  311. package/dist/core/runs/events.d.ts +34 -0
  312. package/dist/core/runs/events.js +1 -0
  313. package/dist/core/runs/operations.d.ts +43 -0
  314. package/dist/core/runs/operations.js +12 -0
  315. package/dist/core/runtime/bearings-render.d.ts +2 -2
  316. package/dist/core/runtime/bearings-render.js +11 -11
  317. package/dist/core/runtime/bearings.js +2 -2
  318. package/dist/core/runtime/broker/cli-relay.d.ts +5 -0
  319. package/dist/core/runtime/broker/cli-relay.js +1 -0
  320. package/dist/core/runtime/broker/client-registry.d.ts +0 -5
  321. package/dist/core/runtime/broker/client-registry.js +1 -1
  322. package/dist/core/runtime/broker/daemon-ops.d.ts +28 -1
  323. package/dist/core/runtime/broker/daemon-ops.js +1 -1
  324. package/dist/core/runtime/broker/engine-drive.d.ts +0 -2
  325. package/dist/core/runtime/broker/engine-drive.js +1 -1
  326. package/dist/core/runtime/broker/fault-retry.d.ts +9 -0
  327. package/dist/core/runtime/broker/fault-retry.js +1 -1
  328. package/dist/core/runtime/broker/frame-dispatch.d.ts +5 -9
  329. package/dist/core/runtime/broker/frame-dispatch.js +1 -1
  330. package/dist/core/runtime/broker/frame-engine-control.d.ts +3 -2
  331. package/dist/core/runtime/broker/frame-engine-control.js +1 -1
  332. package/dist/core/runtime/broker/frame-memory-refs.d.ts +4 -3
  333. package/dist/core/runtime/broker/frame-memory-refs.js +1 -1
  334. package/dist/core/runtime/broker/frame-read.js +1 -1
  335. package/dist/core/runtime/broker/frame-session.js +1 -1
  336. package/dist/core/runtime/broker/held-deferred-inbox.d.ts +3 -1
  337. package/dist/core/runtime/broker/held-deferred-inbox.js +1 -1
  338. package/dist/core/runtime/broker/inbox.d.ts +1 -2
  339. package/dist/core/runtime/broker/inbox.js +7 -10
  340. package/dist/core/runtime/broker/model-adapter.d.ts +9 -0
  341. package/dist/core/runtime/broker/model-adapter.js +2 -0
  342. package/dist/core/runtime/broker/node-token.d.ts +3 -0
  343. package/dist/core/runtime/broker/node-token.js +1 -0
  344. package/dist/core/runtime/broker/read-ops.js +1 -1
  345. package/dist/core/runtime/broker/rebind.d.ts +2 -0
  346. package/dist/core/runtime/broker/rebind.js +1 -1
  347. package/dist/core/runtime/broker/tool-groups.js +1 -1
  348. package/dist/core/runtime/broker/turn-ignition.d.ts +3 -3
  349. package/dist/core/runtime/broker/turn-ignition.js +1 -1
  350. package/dist/core/runtime/broker-cli.js +3 -3
  351. package/dist/core/runtime/broker-extension-render.d.ts +2 -5
  352. package/dist/core/runtime/broker-extension-render.js +4 -4
  353. package/dist/core/runtime/broker-persona-guidance.js +3 -3
  354. package/dist/core/runtime/broker-protocol.d.ts +7 -8
  355. package/dist/core/runtime/broker.js +1 -1
  356. package/dist/core/runtime/canvas-extensions.d.ts +1 -0
  357. package/dist/core/runtime/canvas-extensions.js +1 -1
  358. package/dist/core/runtime/close.d.ts +9 -0
  359. package/dist/core/runtime/close.js +1 -1
  360. package/dist/core/runtime/deliver-live.js +1 -1
  361. package/dist/core/runtime/fleet.d.ts +1 -1
  362. package/dist/core/runtime/front-door-login.js +1 -1
  363. package/dist/core/runtime/front-door.js +2 -2
  364. package/dist/core/runtime/headless-pi.d.ts +1 -1
  365. package/dist/core/runtime/headless-pi.js +1 -1
  366. package/dist/core/runtime/host.d.ts +1 -1
  367. package/dist/core/runtime/host.js +3 -1
  368. package/dist/core/runtime/invocation.d.ts +3 -0
  369. package/dist/core/runtime/kickoff.d.ts +1 -0
  370. package/dist/core/runtime/kickoff.js +16 -16
  371. package/dist/core/runtime/launch-target.d.ts +1 -1
  372. package/dist/core/runtime/launch-target.js +1 -1
  373. package/dist/core/runtime/launch.d.ts +10 -35
  374. package/dist/core/runtime/launch.js +1 -1
  375. package/dist/core/runtime/lifecycle.js +2 -2
  376. package/dist/core/runtime/memory.d.ts +1 -1
  377. package/dist/core/runtime/memory.js +1 -1
  378. package/dist/core/runtime/model-registry.js +1 -1
  379. package/dist/core/runtime/model-swap.d.ts +17 -19
  380. package/dist/core/runtime/model-swap.js +1 -1
  381. package/dist/core/runtime/node-read.js +3 -2
  382. package/dist/core/runtime/nodes.d.ts +7 -0
  383. package/dist/core/runtime/nodes.js +1 -1
  384. package/dist/core/runtime/outcome-document.js +1 -1
  385. package/dist/core/runtime/package-health.js +2 -2
  386. package/dist/core/runtime/persona.js +2 -2
  387. package/dist/core/runtime/pi-vendored.js +1 -1
  388. package/dist/core/runtime/placement-tmux.d.ts +1 -1
  389. package/dist/core/runtime/placement-tmux.js +1 -1
  390. package/dist/core/runtime/placement.js +1 -1
  391. package/dist/core/runtime/promote.js +1 -1
  392. package/dist/core/runtime/provider-credential-gate.js +2 -2
  393. package/dist/core/runtime/recovery-hold.d.ts +2 -0
  394. package/dist/core/runtime/recovery-hold.js +1 -0
  395. package/dist/core/runtime/recycle.js +1 -1
  396. package/dist/core/runtime/reopen.js +1 -1
  397. package/dist/core/runtime/reset.js +1 -1
  398. package/dist/core/runtime/revive.d.ts +1 -1
  399. package/dist/core/runtime/revive.js +2 -3
  400. package/dist/core/runtime/roadmap.js +4 -4
  401. package/dist/core/runtime/run-command.d.ts +6 -0
  402. package/dist/core/runtime/run-command.js +1 -1
  403. package/dist/core/runtime/session-branch.d.ts +2 -8
  404. package/dist/core/runtime/session-branch.js +1 -1
  405. package/dist/core/runtime/session-list-cache.d.ts +6 -22
  406. package/dist/core/runtime/session-list-cache.js +1 -1
  407. package/dist/core/runtime/situational-context.js +2 -2
  408. package/dist/core/runtime/spawn-env.d.ts +6 -6
  409. package/dist/core/runtime/spawn-env.js +1 -1
  410. package/dist/core/runtime/spawn.d.ts +5 -0
  411. package/dist/core/runtime/spawn.js +2 -2
  412. package/dist/core/runtime/stop-guard.js +2 -2
  413. package/dist/core/runtime/stop-signals.d.ts +2 -2
  414. package/dist/core/runtime/stop-signals.js +1 -1
  415. package/dist/core/runtime/structured-output.d.ts +10 -4
  416. package/dist/core/runtime/structured-output.js +4 -4
  417. package/dist/core/runtime/tmux-bindings.js +3 -3
  418. package/dist/core/runtime/tmux-driver.d.ts +4 -0
  419. package/dist/core/runtime/tmux-driver.js +7 -7
  420. package/dist/core/runtime/view-socket.d.ts +9 -2
  421. package/dist/core/runtime/view-socket.js +1 -1
  422. package/dist/core/runtime/warm-pool.js +1 -1
  423. package/dist/core/scope.d.ts +3 -2
  424. package/dist/core/scope.js +1 -1
  425. package/dist/core/scoped-state/db.js +1 -1
  426. package/dist/core/scoped-state/migrate.js +3 -3
  427. package/dist/core/scoped-state/profiles.d.ts +2 -1
  428. package/dist/core/scoped-state/profiles.js +1 -1
  429. package/dist/core/scoped-state/schema.d.ts +2 -1
  430. package/dist/core/scoped-state/schema.js +4 -4
  431. package/dist/core/scopes.d.ts +2 -2
  432. package/dist/core/scopes.js +1 -1
  433. package/dist/core/secrets.d.ts +1 -0
  434. package/dist/core/secrets.js +2 -2
  435. package/dist/core/spaces/mounts.d.ts +32 -0
  436. package/dist/core/spaces/mounts.js +1 -0
  437. package/dist/core/spaces/open-beneath.d.ts +71 -0
  438. package/dist/core/spaces/open-beneath.js +1 -0
  439. package/dist/core/spaces/permissions.d.ts +46 -0
  440. package/dist/core/spaces/permissions.js +1 -0
  441. package/dist/core/spaces/process.d.ts +27 -0
  442. package/dist/core/spaces/process.js +1 -0
  443. package/dist/core/spaces/space.d.ts +8 -0
  444. package/dist/core/spaces/space.js +2 -0
  445. package/dist/core/spaces/stop.d.ts +8 -0
  446. package/dist/core/spaces/stop.js +2 -0
  447. package/dist/core/spaces/users.d.ts +19 -0
  448. package/dist/core/spaces/users.js +1 -0
  449. package/dist/core/subscription-state.d.ts +2 -0
  450. package/dist/core/subscription-state.js +3 -3
  451. package/dist/core/substrate/frontmatter-validation.js +1 -1
  452. package/dist/core/substrate/injected-store.d.ts +28 -3
  453. package/dist/core/substrate/injected-store.js +2 -1
  454. package/dist/core/substrate/listings.js +1 -1
  455. package/dist/core/substrate/memory-events.d.ts +6 -0
  456. package/dist/core/substrate/memory-events.js +1 -0
  457. package/dist/core/substrate/on-read-node.js +1 -1
  458. package/dist/core/substrate/on-read.d.ts +6 -6
  459. package/dist/core/substrate/on-read.js +5 -5
  460. package/dist/core/substrate/plan.js +1 -1
  461. package/dist/core/substrate/render-node.js +1 -1
  462. package/dist/core/substrate/render.d.ts +4 -3
  463. package/dist/core/substrate/render.js +38 -38
  464. package/dist/core/substrate/schema.d.ts +6 -0
  465. package/dist/core/substrate/schema.js +1 -1
  466. package/dist/core/tui/panel.js +1 -1
  467. package/dist/core/user-settings.d.ts +12 -0
  468. package/dist/core/user-settings.js +1 -1
  469. package/dist/core/worktree-mutation-async.js +5 -5
  470. package/dist/core/worktree-quarantine.js +1 -1
  471. package/dist/core/worktree-remove.d.ts +15 -0
  472. package/dist/core/worktree-remove.js +1 -0
  473. package/dist/core/worktree-sweep.js +6 -6
  474. package/dist/daemon/analytics/compute.d.ts +37 -0
  475. package/dist/daemon/analytics/compute.js +1 -0
  476. package/dist/daemon/analytics/scan-worker.d.ts +1 -0
  477. package/dist/daemon/analytics/scan-worker.js +2 -0
  478. package/dist/daemon/analytics/scan.d.ts +37 -0
  479. package/dist/daemon/analytics/scan.js +1 -0
  480. package/dist/daemon/api/app-listener.d.ts +11 -0
  481. package/dist/daemon/api/app-listener.js +21 -0
  482. package/dist/daemon/api/bridge.js +5 -5
  483. package/dist/daemon/api/handlers/analytics.d.ts +2 -0
  484. package/dist/daemon/api/handlers/analytics.js +1 -0
  485. package/dist/daemon/api/handlers/attach.js +1 -1
  486. package/dist/daemon/api/handlers/bash-jobs.js +2 -2
  487. package/dist/daemon/api/handlers/bash.js +1 -1
  488. package/dist/daemon/api/handlers/broker-ops.js +1 -1
  489. package/dist/daemon/api/handlers/canvas.d.ts +1 -1
  490. package/dist/daemon/api/handlers/canvas.js +6 -6
  491. package/dist/daemon/api/handlers/crons.js +1 -1
  492. package/dist/daemon/api/handlers/files.d.ts +1 -1
  493. package/dist/daemon/api/handlers/files.js +1 -1
  494. package/dist/daemon/api/handlers/health.js +2 -2
  495. package/dist/daemon/api/handlers/hook-exec.d.ts +2 -0
  496. package/dist/daemon/api/handlers/hook-exec.js +1 -0
  497. package/dist/daemon/api/handlers/human-requests.js +1 -1
  498. package/dist/daemon/api/handlers/inbox.js +1 -1
  499. package/dist/daemon/api/handlers/llm.d.ts +2 -0
  500. package/dist/daemon/api/handlers/llm.js +3 -0
  501. package/dist/daemon/api/handlers/memory-reads.d.ts +4 -0
  502. package/dist/daemon/api/handlers/memory-reads.js +1 -0
  503. package/dist/daemon/api/handlers/memory.js +5 -1
  504. package/dist/daemon/api/handlers/messages.js +2 -2
  505. package/dist/daemon/api/handlers/modelauth.js +1 -1
  506. package/dist/daemon/api/handlers/node-outcomes.js +1 -1
  507. package/dist/daemon/api/handlers/node-records.d.ts +2 -0
  508. package/dist/daemon/api/handlers/node-records.js +3 -0
  509. package/dist/daemon/api/handlers/nodes.d.ts +1 -1
  510. package/dist/daemon/api/handlers/nodes.js +1 -1
  511. package/dist/daemon/api/handlers/profiles.d.ts +4 -1
  512. package/dist/daemon/api/handlers/profiles.js +1 -1
  513. package/dist/daemon/api/handlers/reports.js +5 -3
  514. package/dist/daemon/api/handlers/reviews.d.ts +1 -1
  515. package/dist/daemon/api/handlers/reviews.js +1 -1
  516. package/dist/daemon/api/handlers/run-routes.d.ts +2 -0
  517. package/dist/daemon/api/handlers/run-routes.js +1 -0
  518. package/dist/daemon/api/handlers/runs.d.ts +9 -0
  519. package/dist/daemon/api/handlers/runs.js +1 -0
  520. package/dist/daemon/api/handlers/subscriptions.js +1 -1
  521. package/dist/daemon/api/handlers/worktree.js +1 -1
  522. package/dist/daemon/api/map.d.ts +10 -4
  523. package/dist/daemon/api/map.js +2 -2
  524. package/dist/daemon/api/operations.d.ts +18 -0
  525. package/dist/daemon/api/operations.js +1 -0
  526. package/dist/daemon/api/principal.d.ts +42 -0
  527. package/dist/daemon/api/principal.js +1 -0
  528. package/dist/daemon/api/router.d.ts +27 -3
  529. package/dist/daemon/api/router.js +1 -1
  530. package/dist/daemon/api/server.d.ts +4 -0
  531. package/dist/daemon/api/server.js +1 -1
  532. package/dist/daemon/api/vendor-signin.d.ts +7 -0
  533. package/dist/daemon/api/vendor-signin.js +77 -0
  534. package/dist/daemon/api/viewer-presence.d.ts +3 -0
  535. package/dist/daemon/api/viewer-presence.js +1 -0
  536. package/dist/daemon/cron/armed-context.d.ts +4 -0
  537. package/dist/daemon/cron/armed-context.js +1 -1
  538. package/dist/daemon/cron/escalation.js +3 -3
  539. package/dist/daemon/cron/lease-recovery.js +1 -1
  540. package/dist/daemon/cron/sinks.js +2 -2
  541. package/dist/daemon/cron-run.d.ts +5 -5
  542. package/dist/daemon/cron-run.js +1 -1
  543. package/dist/daemon/crtrd.js +8 -7
  544. package/dist/daemon/delivery/run-delivery.d.ts +4 -0
  545. package/dist/daemon/delivery/run-delivery.js +1 -1
  546. package/dist/daemon/fleet.d.ts +1 -1
  547. package/dist/daemon/fleet.js +6 -6
  548. package/dist/daemon/human/finish.js +7 -7
  549. package/dist/daemon/joined-owner.d.ts +5 -0
  550. package/dist/daemon/joined-owner.js +1 -0
  551. package/dist/daemon/manage.js +2 -2
  552. package/dist/daemon/messaging/node-message.js +1 -1
  553. package/dist/daemon/park-activity.js +1 -1
  554. package/dist/daemon/reconcilers/bash-deadline.js +1 -1
  555. package/dist/daemon/reconcilers/broker-supervision.d.ts +1 -1
  556. package/dist/daemon/reconcilers/broker-supervision.js +4 -4
  557. package/dist/daemon/reconcilers/delivery-lane.js +1 -1
  558. package/dist/daemon/reconcilers/live-obligation.d.ts +7 -0
  559. package/dist/daemon/reconcilers/live-obligation.js +1 -1
  560. package/dist/daemon/reconcilers/node-lifecycle/tick.js +1 -1
  561. package/dist/daemon/reconcilers/storage-maintenance.d.ts +20 -1
  562. package/dist/daemon/reconcilers/storage-maintenance.js +1 -1
  563. package/dist/daemon/runs/append-section.d.ts +6 -0
  564. package/dist/daemon/runs/append-section.js +2 -0
  565. package/dist/daemon/runs/observer.d.ts +5 -0
  566. package/dist/daemon/runs/observer.js +4 -0
  567. package/dist/launcher/bwrap.d.ts +4 -0
  568. package/dist/launcher/bwrap.js +2 -0
  569. package/dist/launcher/client.d.ts +2 -0
  570. package/dist/launcher/client.js +3 -0
  571. package/dist/launcher/main.d.ts +1 -0
  572. package/dist/launcher/main.js +3 -0
  573. package/dist/launcher/netrule.d.ts +1 -0
  574. package/dist/launcher/netrule.js +1 -0
  575. package/dist/launcher/seccomp.d.ts +1 -0
  576. package/dist/launcher/seccomp.js +1 -0
  577. package/dist/launcher/spec.d.ts +88 -0
  578. package/dist/launcher/spec.js +1 -0
  579. package/dist/launcher/users.d.ts +18 -0
  580. package/dist/launcher/users.js +7 -0
  581. package/dist/launcher/validate.d.ts +22 -0
  582. package/dist/launcher/validate.js +1 -0
  583. package/dist/migrations/corpus.js +3 -3
  584. package/dist/migrations/runner.js +1 -1
  585. package/dist/native/linux/addon.node +0 -0
  586. package/dist/native/linux.d.ts +29 -0
  587. package/dist/native/linux.js +1 -0
  588. package/dist/pi-extensions/broker-local.js +2 -2
  589. package/dist/pi-extensions/canvas-bash-valve.d.ts +1 -3
  590. package/dist/pi-extensions/canvas-bash-valve.js +4 -7
  591. package/dist/pi-extensions/canvas-context-intro.d.ts +1 -2
  592. package/dist/pi-extensions/canvas-context-intro.js +2 -2
  593. package/dist/pi-extensions/canvas-doc-substrate.js +6 -6
  594. package/dist/pi-extensions/canvas-inbox-watcher.d.ts +2 -1
  595. package/dist/pi-extensions/canvas-inbox-watcher.js +2 -1
  596. package/dist/pi-extensions/canvas-passive-context.d.ts +1 -1
  597. package/dist/pi-extensions/canvas-passive-context.js +11 -11
  598. package/dist/pi-extensions/canvas-recap.js +6 -6
  599. package/dist/pi-extensions/canvas-stophook.js +1 -1
  600. package/dist/pi-extensions/canvas-structured-output.js +4 -4
  601. package/dist/pi-extensions/canvas-tool-guide.js +1 -1
  602. package/dist/pi-extensions/system-prompt-entry.d.ts +15 -0
  603. package/dist/pi-extensions/system-prompt-entry.js +1 -0
  604. package/dist/shared/env.d.ts +5 -1
  605. package/dist/shared/env.js +1 -1
  606. package/dist/shared/strip-cd-prefix.d.ts +1 -0
  607. package/dist/shared/strip-cd-prefix.js +1 -0
  608. package/dist/types.d.ts +31 -15
  609. package/docs/cli/memory-and-preferences.md +3 -1
  610. package/docs/sdk/client.md +34 -0
  611. package/docs/sdk/errors.md +2 -0
  612. package/docs/sdk/memory.md +2 -2
  613. package/docs/sdk/streaming.md +21 -0
  614. package/package.json +18 -4
  615. package/packages/crouter-identity/dist/index.d.ts +54 -0
  616. package/packages/crouter-identity/dist/index.js +166 -0
  617. package/packages/crouter-identity/package.json +33 -0
  618. package/runtime.lock.json +34 -8
  619. package/scripts/build-native-linux.mjs +16 -0
  620. package/scripts/install-runtime.mjs +9 -7
  621. package/scripts/lib/isolation-env.mjs +42 -0
  622. package/scripts/runtime-smoke.mjs +49 -0
  623. package/src/native/linux/addon.c +249 -0
  624. package/dist/core/profiles/state-block.d.ts +0 -4
  625. package/dist/core/profiles/state-block.js +0 -3
  626. package/dist/core/runtime/broker/auth-reload.d.ts +0 -41
  627. package/dist/core/runtime/broker/auth-reload.js +0 -1
  628. package/dist/core/substrate/cli-context-delivery.d.ts +0 -22
  629. package/dist/core/substrate/cli-context-delivery.js +0 -1
@@ -1,2 +1,2 @@
1
- var d=Object.defineProperty;var r=(e,t)=>d(e,"name",{value:t,configurable:!0});import{join as g}from"node:path";import{mkdirSync as m}from"node:fs";import{jobDir as f}from"./paths.js";import{readJsonIfExists as y,atomicWriteJson as x}from"../fs-utils.js";function u(e){return g(f(e),"recap.json")}r(u,"recapPath");function l(e){return e.replace(/^\s*(goal|state)\s*:\s*/i,"").trim()}r(l,"stripLabel");function b(e){const t=e.split(`
2
- `).map(i=>i.trim()).filter(i=>i!=="");if(t.length===0)return null;const n=r(i=>t.find(p=>new RegExp(`^${i}\\s*:`,"i").test(p)),"labelled"),o=n("goal")??t[0],a=n("state")??(t[1]!==o?t[1]:void 0),s=o===void 0?"":l(o),c=a===void 0?"":l(a);return s===""&&c===""?null:{goal:s,state:c}}r(b,"parseRecapBriefing");function S(e,t){const n=b(t);if(n!==null)try{m(f(e),{recursive:!0}),x(u(e),{...n,at:new Date().toISOString()})}catch{}}r(S,"writeNodeRecap");function D(e){const t=y(u(e));if(t===null||typeof t!="object")return;const n=typeof t.goal=="string"?t.goal:"",o=typeof t.state=="string"?t.state:"";if(!(n===""&&o===""))return{goal:n,state:o,at:typeof t.at=="string"?t.at:""}}r(D,"readNodeRecap");export{b as parseRecapBriefing,D as readNodeRecap,S as writeNodeRecap};
1
+ var d=Object.defineProperty;var r=(e,t)=>d(e,"name",{value:t,configurable:!0});import{join as g}from"node:path";import{mkdirSync as m}from"node:fs";import{jobDir as c}from"./paths.js";import{readJsonIfExists as w,atomicWriteJson as y}from"../fs-utils.js";function l(e){return g(c(e),"recap.json")}r(l,"recapPath");function p(e){return e.replace(/^\s*(goal|state)\s*:\s*/i,"").trim()}r(p,"stripLabel");function b(e){const t=e.split(`
2
+ `).map(i=>i.trim()).filter(i=>i!=="");if(t.length===0)return null;const n=r(i=>t.find(u=>new RegExp(`^${i}\\s*:`,"i").test(u)),"labelled"),o=n("goal")??t[0],a=n("state")??(t[1]!==o?t[1]:void 0),s=o===void 0?"":p(o),f=a===void 0?"":p(a);return s===""&&f===""?null:{goal:s,state:f}}r(b,"parseRecapBriefing");function L(e,t){const n=b(t);if(n===null)throw new TypeError("recap briefing has no goal or state");m(c(e),{recursive:!0}),y(l(e),{...n,at:new Date().toISOString()})}r(L,"writeNodeRecap");function S(e){const t=w(l(e));if(t===null||typeof t!="object")return;const n=typeof t.goal=="string"?t.goal:"",o=typeof t.state=="string"?t.state:"";if(!(n===""&&o===""))return{goal:n,state:o,at:typeof t.at=="string"?t.at:""}}r(S,"readNodeRecap");export{b as parseRecapBriefing,S as readNodeRecap,L as writeNodeRecap};
@@ -0,0 +1,24 @@
1
+ import { openDb } from './db.js';
2
+ export interface NodePrincipal {
3
+ app: string;
4
+ node: string;
5
+ run: string | null;
6
+ uid: number;
7
+ sub: string;
8
+ grant: string | null;
9
+ client_id: string | null;
10
+ scopes: string[] | null;
11
+ }
12
+ export declare function mintNodeToken(db: ReturnType<typeof openDb>, executionId: string, nodeId: string, issuedAt: string): void;
13
+ /** Called exactly once by the host at spawn, never serialized into a launch recipe. */
14
+ export declare function takeNodeToken(executionId: string): string;
15
+ export declare function forgetNodeToken(executionId: string): void;
16
+ /** A stopped or superseded execution can never authenticate, even after restart. */
17
+ export declare function resolveNodeToken(token: string): NodePrincipal | null;
18
+ export declare function revokeExitedNodeToken(executionId: string): void;
19
+ export declare function revokePriorEpochNodeTokens(epoch: string): void;
20
+ /** OWN-11 for a joined runtime: a `user:local` subject becomes the owner, a
21
+ * `user:local` grantee becomes `app:terminal` (no token has the owner as grantee),
22
+ * and a reference to the dropped local grant is cleared. */
23
+ export declare function rewriteLocalNodeTokenIdentity(db: ReturnType<typeof openDb>, owner: string, localGrantId: string): number;
24
+ export declare function revokeNodeTokens(db: ReturnType<typeof openDb>, where: 'broker_process_id' | 'node_id', id: string, at: string): void;
@@ -0,0 +1,5 @@
1
+ var g=Object.defineProperty;var t=(e,n)=>g(e,"name",{value:n,configurable:!0});import{createHash as k,randomBytes as m}from"node:crypto";import{openDb as u}from"./db.js";import{terminalGrant as N}from"../grants/mirror.js";import{readConfig as c}from"../config.js";import{uidForApp as T}from"../spaces/users.js";const i=new Map,l=t(e=>k("sha256").update(e).digest("hex"),"hash");function x(e,n,o,s){const r=e.prepare("SELECT grantee, sub, grant_id, client_id, scopes_json, run_id FROM nodes WHERE node_id = ?").get(o);if(!r)throw new Error(`cannot mint node token: missing node ${o}`);const a=r.run_id&&r.run_id!==o?e.prepare("SELECT sub, grant_id, client_id FROM nodes WHERE node_id = ?").get(r.run_id):void 0,d=r.grantee==="app:terminal"?N():null,p=d?.sub??a?.sub??r.sub,E=d?.id??a?.grant_id??r.grant_id??null;if(r.grantee==="app:terminal"&&c("user").runtime?.issuer&&!d)throw new Error("cannot mint node token: terminal grant is not active");if(!p&&r.grantee!=="user:local"&&!(r.grantee==="app:terminal"&&!c("user").runtime?.issuer))throw new Error(`cannot mint node token: no subject for ${r.grantee}`);const _=m(32).toString("base64url");e.prepare("INSERT INTO node_tokens (broker_process_id, node_id, token_hash, grantee, uid, sub, grant, client_id, scopes_json, issued_at, revoked_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NULL)").run(n,o,l(_),r.grantee==="user:local"?"app:terminal":r.grantee,T(r.grantee==="user:local"?"app:terminal":r.grantee),p??"user:local",E,a?.client_id??r.client_id,r.scopes_json,s),i.set(n,_)}t(x,"mintNodeToken");function A(e){const n=i.get(e);if(i.delete(e),!n)throw new Error(`missing node token for execution ${e}`);return n}t(A,"takeNodeToken");function f(e){i.delete(e)}t(f,"forgetNodeToken");function D(e){if(!/^[A-Za-z0-9_-]{43}$/.test(e))return null;const n=u().prepare(`SELECT t.node_id, t.grantee, t.uid, t.sub, t.grant, t.client_id, t.scopes_json, n.run_id
2
+ FROM node_tokens t JOIN executions e ON e.execution_id = t.broker_process_id
3
+ JOIN nodes n ON n.node_id = t.node_id
4
+ WHERE t.token_hash = ? AND t.revoked_at IS NULL AND e.state != 'exited'`).get(l(e));return n?{app:n.grantee,node:n.node_id,run:n.run_id,uid:n.uid,sub:n.sub,grant:n.grant,client_id:n.client_id,scopes:n.scopes_json===null?null:JSON.parse(n.scopes_json)}:null}t(D,"resolveNodeToken");function v(e){f(e),S(u(),"broker_process_id",e,new Date().toISOString())}t(v,"revokeExitedNodeToken");function U(e){u().prepare(`UPDATE node_tokens SET revoked_at = ? WHERE revoked_at IS NULL
5
+ AND broker_process_id IN (SELECT execution_id FROM executions WHERE daemon_epoch IS NOT ?)`).run(new Date().toISOString(),e)}t(U,"revokePriorEpochNodeTokens");function H(e,n,o){return Number(e.prepare("UPDATE node_tokens SET sub = ? WHERE sub = 'user:local'").run(n).changes)+Number(e.prepare("UPDATE node_tokens SET grantee = 'app:terminal' WHERE grantee = 'user:local'").run().changes)+Number(e.prepare('UPDATE node_tokens SET "grant" = NULL WHERE "grant" = ?').run(o).changes)}t(H,"rewriteLocalNodeTokenIdentity");function S(e,n,o,s){e.prepare(`UPDATE node_tokens SET revoked_at = ? WHERE ${n} = ? AND revoked_at IS NULL`).run(s,o)}t(S,"revokeNodeTokens");export{f as forgetNodeToken,x as mintNodeToken,D as resolveNodeToken,v as revokeExitedNodeToken,S as revokeNodeTokens,U as revokePriorEpochNodeTokens,H as rewriteLocalNodeTokenIdentity,A as takeNodeToken};
@@ -1,25 +1,14 @@
1
- /** Root of the global canvas home (`~/.crouter/canvas` unless `CRTR_HOME` is set).
2
- * Nested under the `.crouter` scope root so the whole runtime lives in one
3
- * visible top-level dir; `canvas/` keeps node-graph runtime state separate from
4
- * durable user content (memory/plugins/marketplaces/config) at the scope root. */
1
+ /** Runtime-owned records; never a bind source for an app sandbox. */
5
2
  export declare function crtrHome(): string;
6
3
  /** The canvas home requires durable storage with SQLite WAL locking support. */
7
4
  export declare function canvasDbPath(): string;
8
5
  export declare function onDiskMigrationLockPath(): string;
9
6
  export declare function onDiskMigrationMarkerPath(): string;
10
- /** Absolute path to a node's broker `view.sock` — always `view.sock` under the
11
- * node dir. Stale socket files (a host reboot, a sandbox recreate on a
12
- * durable volume) are harmless: the broker unlinks any existing socket before
13
- * it binds. */
7
+ /** The viewer socket belongs to the per-node run folder, not the durable records. */
14
8
  export declare function viewSocketPath(nodeId: string): string;
15
9
  export declare function nodesRoot(): string;
16
10
  export declare function reviewsRoot(): string;
17
11
  export declare function reviewDir(reviewId: string): string;
18
- export declare function reviewBranchPath(reviewId: string): string;
19
- /** The immutable session branch a single comment's fork is born from. Each
20
- * comment gets its own branch file so concurrent forks never share a source. */
21
- export declare function reviewForkBranchPath(reviewId: string, commentId: string): string;
22
- export declare function ensureReviewForkDir(reviewId: string): void;
23
12
  export declare function reviewResultPath(reviewId: string): string;
24
13
  export declare function ensureReviewDir(reviewId: string): void;
25
14
  /** Absolute path to crtrd's API listener unix socket, a sibling of
@@ -38,8 +27,14 @@ export declare function apiSocketPath(): string;
38
27
  export declare function sessionListCachePath(): string;
39
28
  /** Whether a persisted node ID is safe as a single filesystem path segment. */
40
29
  export declare function isSafeNodeId(nodeId: string): boolean;
41
- export declare function nodeDir(nodeId: string): string;
42
- export declare function contextDir(nodeId: string): string;
30
+ export declare function nodeRecordDir(nodeId: string): string;
31
+ /** Existing callers use nodeDir for the daemon's records only. */
32
+ export declare const nodeDir: typeof nodeRecordDir;
33
+ /** Pure path builder. A broker may resolve its own app from its launch identity;
34
+ * every other caller must supply the app from the daemon's node row. */
35
+ export declare function nodeAgentDir(nodeId: string, grantee?: string): string;
36
+ export declare function nodeRunDir(nodeId: string): string;
37
+ export declare function contextDir(nodeId: string, grantee?: string): string;
43
38
  /** Replace the literal env-var tokens `$CRTR_CONTEXT_DIR` / `$CRTR_NODE_ID` in
44
39
  * agent-facing doc text with the node's real values, so a doc surfaced INTO a
45
40
  * node hands it a concrete absolute path instead of a shell-only string. The
@@ -49,9 +44,10 @@ export declare function contextDir(nodeId: string): string;
49
44
  * Write, so this substitution is strictly safer. Callers must only apply it
50
45
  * when they have a concrete node to render for (never on generic, node-less
51
46
  * output). Pure string work — no I/O. */
52
- export declare function interpolateNodePaths(text: string, nodeId: string): string;
47
+ export declare function interpolateNodePaths(text: string, nodeId: string, grantee?: string): string;
53
48
  export declare function jobDir(nodeId: string): string;
54
- export declare function reportsDir(nodeId: string): string;
49
+ export declare function nodeRunJobDir(nodeId: string): string;
50
+ export declare function reportsDir(nodeId: string, grantee?: string): string;
55
51
  /** Overflow store for inbox entries whose inline body exceeds the digest's
56
52
  * bounded preview (a direct `node message send` or a close/cancel doctrine
57
53
  * wake) — the full body spills here, mirroring how a
@@ -68,7 +64,8 @@ export declare function sessionPtrPath(nodeId: string): string;
68
64
  /** Frozen preference snapshot and rank-aware exposure state for the node's
69
65
  * currently loaded LLM context. The filename remains stable across schema versions. */
70
66
  export declare function injectedDocsPath(nodeId: string): string;
71
- /** Create the full directory skeleton for a node. Idempotent. */
72
- export declare function ensureNodeDirs(nodeId: string): void;
67
+ /** Create the full directory skeleton for a node. Idempotent. The agent and
68
+ * run folders are app-writable, so their subfolders are made beneath them. */
69
+ export declare function ensureNodeDirs(nodeId: string, grantee: string): void;
73
70
  /** Ensure the canvas home exists. Idempotent. */
74
71
  export declare function ensureHome(): void;
@@ -1 +1 @@
1
- var f=Object.defineProperty;var r=(t,o)=>f(t,"name",{value:o,configurable:!0});import{homedir as x}from"node:os";import{join as e}from"node:path";import{mkdirSync as u}from"node:fs";import{CRTR_DIR_NAME as h}from"../../types.js";function i(){const t=process.env.CRTR_HOME;return t!==void 0&&t!==""?t:e(x(),h,"canvas")}r(i,"crtrHome");function b(){return e(i(),"canvas.db")}r(b,"canvasDbPath");function g(){return e(i(),"on-disk-migration.lock")}r(g,"onDiskMigrationLockPath");function T(){return e(i(),"on-disk-migrations.json")}r(T,"onDiskMigrationMarkerPath");function N(t){return c(t),e(n(t),"view.sock")}r(N,"viewSocketPath");function a(){return e(i(),"nodes")}r(a,"nodesRoot");function m(){return e(i(),"reviews")}r(m,"reviewsRoot");function s(t){return c(t),e(m(),t)}r(s,"reviewDir");function C(t){return e(s(t),"branch-point.jsonl")}r(C,"reviewBranchPath");function E(t,o){return c(o),e(s(t),"forks",`${o}.jsonl`)}r(E,"reviewForkBranchPath");function M(t){u(e(s(t),"forks"),{recursive:!0,mode:448})}r(M,"ensureReviewForkDir");function d(t){return e(s(t),"result.json")}r(d,"reviewResultPath");function y(t){u(s(t),{recursive:!0,mode:448})}r(y,"ensureReviewDir");function S(){return e(i(),"crtrd.sock")}r(S,"apiSocketPath");function A(){return e(i(),"session-list-cache.json")}r(A,"sessionListCachePath");const v=128;function D(t){return typeof t=="string"&&t!==""&&t!=="."&&t!==".."&&!/[\\/\0]/u.test(t)&&Buffer.byteLength(t,"utf8")<=v}r(D,"isSafeNodeId");function c(t){if(!D(t))throw new TypeError("node_id must be a non-empty path segment of at most 128 UTF-8 bytes")}r(c,"assertSafeNodeId");function n(t){return c(t),e(a(),t)}r(n,"nodeDir");function p(t){return e(n(t),"context")}r(p,"contextDir");function B(t,o){return t.replaceAll("$CRTR_CONTEXT_DIR",p(o)).replaceAll("$CRTR_NODE_ID",o)}r(B,"interpolateNodePaths");function l(t){return e(n(t),"job")}r(l,"jobDir");function P(t){return e(n(t),"reports")}r(P,"reportsDir");function O(t){return e(n(t),"messages")}r(O,"messagesDir");function F(t){return e(n(t),"meta.json")}r(F,"nodeMetaPath");function H(t){return e(n(t),"inbox.jsonl")}r(H,"inboxPath");function L(t){return e(n(t),"situational-context.md")}r(L,"situationalContextPath");function $(t){return e(n(t),"passive.jsonl")}r($,"passivePath");function X(t){return e(n(t),"transcript.jsonl")}r(X,"transcriptPath");function U(t){return e(n(t),"session.ptr")}r(U,"sessionPtrPath");function Y(t){return e(n(t),"injected-docs.json")}r(Y,"injectedDocsPath");function q(t){for(const o of[p(t),l(t),P(t)])u(o,{recursive:!0})}r(q,"ensureNodeDirs");function z(){u(a(),{recursive:!0})}r(z,"ensureHome");export{S as apiSocketPath,b as canvasDbPath,p as contextDir,i as crtrHome,z as ensureHome,q as ensureNodeDirs,y as ensureReviewDir,M as ensureReviewForkDir,H as inboxPath,Y as injectedDocsPath,B as interpolateNodePaths,D as isSafeNodeId,l as jobDir,O as messagesDir,n as nodeDir,F as nodeMetaPath,a as nodesRoot,g as onDiskMigrationLockPath,T as onDiskMigrationMarkerPath,$ as passivePath,P as reportsDir,C as reviewBranchPath,s as reviewDir,E as reviewForkBranchPath,d as reviewResultPath,m as reviewsRoot,A as sessionListCachePath,U as sessionPtrPath,L as situationalContextPath,X as transcriptPath,N as viewSocketPath};
1
+ var P=Object.defineProperty;var r=(t,n)=>P(t,"name",{value:n,configurable:!0});import{join as e}from"node:path";import{mkdirSync as c}from"node:fs";import{appSpace as x,runtimeRoot as j,socketDir as m}from"../layout.js";import{envGrantee as k,envNodeId as R}from"../../shared/env.js";import{withDirBeneath as h}from"../spaces/open-beneath.js";function i(){return j()}r(i,"crtrHome");function A(){return e(i(),"canvas.db")}r(A,"canvasDbPath");function B(){return e(i(),"on-disk-migration.lock")}r(B,"onDiskMigrationLockPath");function L(){return e(i(),"on-disk-migrations.json")}r(L,"onDiskMigrationMarkerPath");function O(t){return e(u(t),"view.sock")}r(O,"viewSocketPath");function D(){return e(i(),"nodes")}r(D,"nodesRoot");function w(){return e(i(),"reviews")}r(w,"reviewsRoot");function l(t){return p(t),e(w(),t)}r(l,"reviewDir");function $(t){return e(l(t),"result.json")}r($,"reviewResultPath");function H(t){c(l(t),{recursive:!0,mode:448})}r(H,"ensureReviewDir");function X(){return e(m(),"api.sock")}r(X,"apiSocketPath");function F(){return e(i(),"session-list-cache.json")}r(F,"sessionListCachePath");const b=128;function g(t){return typeof t=="string"&&t!==""&&t!=="."&&t!==".."&&!/[\\/\0]/u.test(t)&&Buffer.byteLength(t,"utf8")<=b}r(g,"isSafeNodeId");function p(t){if(!g(t))throw new TypeError("node_id must be a non-empty path segment of at most 128 UTF-8 bytes")}r(p,"assertSafeNodeId");function a(t){return p(t),e(D(),t)}r(a,"nodeRecordDir");const s=a;function f(t,n){p(t);const o=n??(R()===t?k():void 0);if(!o)throw new Error(`node ${t} has no app assignment`);return e(x(o).nodes,t)}r(f,"nodeAgentDir");function u(t){return p(t),process.platform==="linux"?e(m(),"nodes",t):e(a(t),"run")}r(u,"nodeRunDir");function N(t,n){return e(f(t,n),"context")}r(N,"contextDir");function G(t,n,o){return t.replaceAll("$CRTR_CONTEXT_DIR",N(n,o)).replaceAll("$CRTR_NODE_ID",n)}r(G,"interpolateNodePaths");function _(t){return e(a(t),"job")}r(_,"jobDir");function S(t){return e(u(t),"job")}r(S,"nodeRunJobDir");function J(t,n){return e(f(t,n),"reports")}r(J,"reportsDir");function U(t){return e(s(t),"messages")}r(U,"messagesDir");function Y(t){return e(s(t),"meta.json")}r(Y,"nodeMetaPath");function q(t){return e(s(t),"inbox.jsonl")}r(q,"inboxPath");function z(t){return e(u(t),"situational-context.md")}r(z,"situationalContextPath");function K(t){return e(s(t),"passive.jsonl")}r(K,"passivePath");function Q(t){return e(s(t),"transcript.jsonl")}r(Q,"transcriptPath");function V(t){return e(s(t),"session.ptr")}r(V,"sessionPtrPath");function W(t){return e(u(t),"injected-docs.json")}r(W,"injectedDocsPath");function Z(t,n){const o=f(t,n);c(a(t),{recursive:!0}),c(_(t),{recursive:!0});for(const v of["context","reports","attachments","worktree"])h(x(n).nodes,e(o,v),()=>{},!0);h(u(t),S(t),()=>{},!0)}r(Z,"ensureNodeDirs");function I(){c(D(),{recursive:!0})}r(I,"ensureHome");export{X as apiSocketPath,A as canvasDbPath,N as contextDir,i as crtrHome,I as ensureHome,Z as ensureNodeDirs,H as ensureReviewDir,q as inboxPath,W as injectedDocsPath,G as interpolateNodePaths,g as isSafeNodeId,_ as jobDir,U as messagesDir,f as nodeAgentDir,s as nodeDir,Y as nodeMetaPath,a as nodeRecordDir,u as nodeRunDir,S as nodeRunJobDir,D as nodesRoot,B as onDiskMigrationLockPath,L as onDiskMigrationMarkerPath,K as passivePath,J as reportsDir,l as reviewDir,$ as reviewResultPath,w as reviewsRoot,F as sessionListCachePath,V as sessionPtrPath,z as situationalContextPath,Q as transcriptPath,O as viewSocketPath};
@@ -108,7 +108,7 @@ export interface DashboardRow {
108
108
  * Undefined for rows built by other paths (dashboardRowsFromSource). */
109
109
  srcRow?: NodeRow;
110
110
  }
111
- export declare function readGoalText(nodeId: string): string | undefined;
111
+ export declare function readGoalText(contextPath: string): string | undefined;
112
112
  /** The newest pushed report, reduced to what a preview panel can use. */
113
113
  export interface NodeReportPreview {
114
114
  /** final | update | urgent (frontmatter, else the filename suffix). */
@@ -123,7 +123,7 @@ export interface NodeReportPreview {
123
123
  /** The node's newest report, read straight off disk. Report filenames lead with a
124
124
  * compact timestamp, so the lexicographic maximum is the latest one — no stat of
125
125
  * the whole directory. Never throws; undefined when the node pushed nothing. */
126
- export declare function readNewestReport(nodeId: string): NodeReportPreview | undefined;
126
+ export declare function readNewestReport(reportPath: string): NodeReportPreview | undefined;
127
127
  interface SessionParts {
128
128
  prompts?: string;
129
129
  lastAssistant?: string;
@@ -1,10 +1,7 @@
1
- var Y=Object.defineProperty;var f=(t,e)=>Y(t,"name",{value:e,configurable:!0});import{existsSync as b,readFileSync as _,readdirSync as B,statSync as U,openSync as W,readSync as H,closeSync as Z}from"node:fs";import{join as T}from"node:path";import{RemoteCanvasSource as x}from"./remote-canvas-source.js";import{fullName as $}from"./labels.js";import{jobDir as q,contextDir as K,reportsDir as R}from"./paths.js";import{readNodeRecap as Q}from"./node-recap.js";import{parseFrontmatterGeneric as X}from"../frontmatter.js";import{isFrozenRow as v,resolveNodeVisual as C,faultSummary as P}from"./status-glyph.js";import{parseCard as L}from"../../shared/generated-context.js";function j(t){return t===void 0||t===0?"0k":`${Math.floor(t/1e3)}k`}f(j,"fmtCtx");function I(t,e,n,i,c,a){if(t===void 0)return`${n}${i}? <missing meta: ${e}>`;const s=t.fault??null,r=C(t.status,{hanging:s,frozen:v(t)}).glyph,o=c?"0k":j(t.telemetry_tokens_in??void 0),u=a[e]??0,m=u>0?` \u2691${u}`:"",d=s!==null?` \xB7 ${P(s)}`:"";return`${n}${i}${r} ${$(t)} [${t.kind}/${t.mode}] ctx ${o}${m}${d}`}f(I,"nodeLineFromSource");async function z(t,e,n,i,c,a,s,r,o){if(a.has(n))return;a.add(n);const u=c?"\u2514\u2500 ":"\u251C\u2500 ";s.push(I(e.get(n),n,i,u,r,o));const m=i+(c?" ":"\u2502 ");let d;try{d=await t.subscriptionsOf(n)}catch(l){s.push(`${m}\u26A0 children unavailable: ${l instanceof Error?l.message:String(l)}`);return}for(let l=0;l<d.length;l++){const h=d[l],S=l===d.length-1;if(a.has(h.node_id)){const N=S?"\u2514\u2500 ":"\u251C\u2500 ";s.push(`${m}${N}\u21BA <cycle: ${h.node_id}>`);continue}await z(t,e,h.node_id,m,S,a,s,r,o)}}f(z,"walkTreeFromSource");async function tt(t,e,n,i,c){const a=t instanceof x,s=new Map((n??await t.listNodes()).map(p=>[p.node_id,p])),r=s.get(e);if(r===void 0)return`? <missing node: ${e}>`;let o=i,u=c??null;if(o===void 0)try{o=await t.ticketCountsForView(e)}catch(p){o={},u=p instanceof Error?p.message:String(p)}const m=a?"0k":j(r.telemetry_tokens_in??void 0),d=o[e]??0,l=d>0?` \u2691${d}`:"",h=r.fault??null,S=C(r.status,{hanging:h,frozen:v(r)}).glyph,N=h!==null?` \xB7 ${P(h)}`:"",g=[];g.push(`${S} ${$(r)} [${r.kind}/${r.mode}] ctx ${m}${l}${N}`);const V=new Set([e]);let y;try{y=await t.subscriptionsOf(e)}catch(p){g.push(`\u26A0 children unavailable: ${p instanceof Error?p.message:String(p)}`),y=[]}for(let p=0;p<y.length;p++){const G=y[p],J=p===y.length-1;await z(t,s,G.node_id,"",J,V,g,a,o)}return u!==null&&g.push(`Tickets: unavailable (${u}).`),g.join(`
2
- `)}f(tt,"renderTreeFromSource");async function Nt(t,e,n,i){const c=e??await t.listNodes();if(c.length===0)return"(canvas is empty)";const a=c.filter(r=>r.parent===null&&(r.status==="active"||r.status==="idle"));if(a.length===0)return"(no live roots)";const s=[];for(const r of a)s.push(await tt(t,r.node_id,c,n,i));return s.join(`
1
+ var H=Object.defineProperty;var u=(t,e)=>H(t,"name",{value:e,configurable:!0});import{conversationIdFromPath as v,conversationStore as A,ConversationNotFoundError as C}from"../conversation-store/index.js";import{dirname as b,join as N}from"node:path";import{readdirBeneath as J,readFileBeneath as F,readTextBeneathIfExists as U}from"../spaces/open-beneath.js";import{RemoteCanvasSource as y}from"./remote-canvas-source.js";import{fullName as $}from"./labels.js";import{nodeRunDir as Z,nodeRunJobDir as q,contextDir as K,reportsDir as Q}from"./paths.js";import{readNodeRecap as X}from"./node-recap.js";import{parseFrontmatterGeneric as I}from"../frontmatter.js";import{isFrozenRow as P,resolveNodeVisual as L,faultSummary as E}from"./status-glyph.js";import{parseCard as j}from"../../shared/generated-context.js";function w(t){return t===void 0||t===0?"0k":`${Math.floor(t/1e3)}k`}u(w,"fmtCtx");function tt(t,e,n,i,r,s){if(t===void 0)return`${n}${i}? <missing meta: ${e}>`;const a=t.fault??null,o=L(t.status,{hanging:a,frozen:P(t)}).glyph,c=r?"0k":w(t.telemetry_tokens_in??void 0),l=s[e]??0,h=l>0?` \u2691${l}`:"",m=a!==null?` \xB7 ${E(a)}`:"";return`${n}${i}${o} ${$(t)} [${t.kind}/${t.mode}] ctx ${c}${h}${m}`}u(tt,"nodeLineFromSource");async function M(t,e,n,i,r,s,a,o,c){if(s.has(n))return;s.add(n);const l=r?"\u2514\u2500 ":"\u251C\u2500 ";a.push(tt(e.get(n),n,i,l,o,c));const h=i+(r?" ":"\u2502 ");let m;try{m=await t.subscriptionsOf(n)}catch(f){a.push(`${h}\u26A0 children unavailable: ${f instanceof Error?f.message:String(f)}`);return}for(let f=0;f<m.length;f++){const d=m[f],x=f===m.length-1;if(s.has(d.node_id)){const S=x?"\u2514\u2500 ":"\u251C\u2500 ";a.push(`${h}${S}\u21BA <cycle: ${d.node_id}>`);continue}await M(t,e,d.node_id,h,x,s,a,o,c)}}u(M,"walkTreeFromSource");async function et(t,e,n,i,r){const s=t instanceof y,a=new Map((n??await t.listNodes()).map(p=>[p.node_id,p])),o=a.get(e);if(o===void 0)return`? <missing node: ${e}>`;let c=i,l=r??null;if(c===void 0)try{c=await t.ticketCountsForView(e)}catch(p){c={},l=p instanceof Error?p.message:String(p)}const h=s?"0k":w(o.telemetry_tokens_in??void 0),m=c[e]??0,f=m>0?` \u2691${m}`:"",d=o.fault??null,x=L(o.status,{hanging:d,frozen:P(o)}).glyph,S=d!==null?` \xB7 ${E(d)}`:"",g=[];g.push(`${x} ${$(o)} [${o.kind}/${o.mode}] ctx ${h}${f}${S}`);const G=new Set([e]);let _;try{_=await t.subscriptionsOf(e)}catch(p){g.push(`\u26A0 children unavailable: ${p instanceof Error?p.message:String(p)}`),_=[]}for(let p=0;p<_.length;p++){const Y=_[p],W=p===_.length-1;await M(t,a,Y.node_id,"",W,G,g,s,c)}return l!==null&&g.push(`Tickets: unavailable (${l}).`),g.join(`
2
+ `)}u(et,"renderTreeFromSource");async function Tt(t,e,n,i){const r=e??await t.listNodes();if(r.length===0)return"(canvas is empty)";const s=r.filter(o=>o.parent===null&&(o.status==="active"||o.status==="idle"));if(s.length===0)return"(no live roots)";const a=[];for(const o of s)a.push(await et(t,o.node_id,r,n,i));return a.join(`
3
3
 
4
- `)}f(Nt,"renderForestFromSource");const M=4096;function et(t){try{const e=T(K(t),"initial-prompt.md");if(!b(e))return;const n=_(e,"utf8").trim();return n===""?void 0:n.length>M?n.slice(0,M):n}catch{return}}f(et,"readGoalText");const E=1024;function nt(t){const e=t.match(/^(\d{4})(\d{2})(\d{2})T(\d{2})(\d{2})(\d{2})(\d{3})?$/);if(e!==null)return`${e[1]}-${e[2]}-${e[3]}T${e[4]}:${e[5]}:${e[6]}.${e[7]??"000"}Z`}f(nt,"reportStampToIso");function it(t){let e;try{for(const l of B(R(t)))l.endsWith(".md")&&(e===void 0||l>e)&&(e=l)}catch{return}if(e===void 0)return;let n;try{n=_(T(R(t),e),"utf8")}catch{return}const{data:i,body:c}=X(n),a=e.replace(/\.md$/,""),s=typeof i?.kind=="string"?i.kind:a.split("-").pop()??"report",r=typeof i?.ts=="string"?i.ts:nt(a.split("-")[0]??"")??"",o=c.split(`
5
- `);let u="",m=c;for(let l=0;l<o.length;l++){const h=(o[l]??"").trim();if(h!==""){u=h.startsWith("#")?h.replace(/^#+\s*/,"").trim():h,m=o.slice(l+1).join(`
6
- `);break}}const d=m.replace(/\s+/g," ").trim();return{kind:s,ts:r,heading:u,body:d.length>E?d.slice(0,E):d}}f(it,"readNewestReport");const rt=1<<20,st=1<<20,ot=4<<20;function w(t,e,n){if(t==null||t==="")return null;try{if(!b(t))return null;const i=U(t).size;if(i<=e+n){const a=_(t,"utf8").split(`
7
- `);return{head:a,tail:a}}const c=W(t,"r");try{const a=f((o,u)=>{if(u<=0)return[];const m=Buffer.allocUnsafe(u),d=H(c,m,0,u,o);return m.subarray(0,d).toString("utf8").split(`
8
- `)},"slice"),s=a(0,e),r=a(i-n,n);return s.length>0&&s.pop(),r.length>0&&r.shift(),{head:s,tail:r}}finally{Z(c)}}catch{return null}}f(w,"readSessionWindow");const O=8192,k=2048;function at(t){const e=w(t,rt,st);if(e===null)return{};const n=[];let i=0;for(const s of e.head){if(s===""||s.indexOf('"role":"user"')===-1&&s.indexOf('"role": "user"')===-1)continue;let r;try{r=JSON.parse(s)}catch{continue}if(r.type!=="message"||r.message?.role!=="user")continue;const o=A(r.message.content);if(o===""||L({role:"user",content:o})!==null)continue;const u=o.length>k?o.slice(0,k):o;if(n.push(u),i+=u.length+1,i>=O)break}let c;if(n.length>0){const s=n.join(`
9
- `);c=s.length>O?s.slice(0,O):s}let a;for(let s=e.tail.length-1;s>=0;s--){const r=e.tail[s];if(r===""||r.indexOf('"role":"assistant"')===-1&&r.indexOf('"role": "assistant"')===-1)continue;let o;try{o=JSON.parse(r)}catch{continue}if(o.type!=="message"||o.message?.role!=="assistant")continue;const u=A(o.message.content);if(u!==""){a=u.length>k?u.slice(0,k):u;break}}return{prompts:c,lastAssistant:a}}f(at,"readSessionParts");const D=120,F=4096;function ct(t){const e=w(t,0,ot);if(e===null)return[];const n=[];for(const i of e.tail){if(i==="")continue;const c=i.indexOf('"role":"user"')!==-1||i.indexOf('"role": "user"')!==-1,a=!c&&(i.indexOf('"role":"assistant"')!==-1||i.indexOf('"role": "assistant"')!==-1);if(!c&&!a)continue;let s;try{s=JSON.parse(i)}catch{continue}if(s.type!=="message")continue;const r=s.message?.role;if(r!=="user"&&r!=="assistant")continue;const o=A(s.message?.content);o!==""&&L({role:r,content:o})===null&&n.push({role:r,text:o.length>F?o.slice(0,F):o})}return n.length>D?n.slice(n.length-D):n}f(ct,"readTranscript");function bt(t){if(t==null||t==="")return!1;let e;try{if(!b(t))return!1;e=_(t,"utf8").split(`
10
- `)}catch{return!1}for(const n of e){if(n===""||n.indexOf('"role":"assistant"')===-1&&n.indexOf('"role": "assistant"')===-1)continue;let i;try{i=JSON.parse(n)}catch{continue}if(!(i.type!=="message"||i.message?.role!=="assistant")&&ut(i.message.content))return!0}return!1}f(bt,"nodeHasAssistantMessage");function ut(t){if(typeof t=="string")return t.trim()!=="";if(!Array.isArray(t))return!1;for(const e of t){if(e===null||typeof e!="object")continue;const n=e,i=(n.type??"").toLowerCase();if(i==="text"){if(typeof n.text=="string"&&n.text.trim()!=="")return!0}else if(i==="thinking"){if(typeof n.thinking=="string"&&n.thinking.trim()!=="")return!0}else return!0}return!1}f(ut,"assistantContentIsSubstantive");function A(t){if(typeof t=="string")return t.trim();if(!Array.isArray(t))return"";const e=[];for(const n of t)if(n!==null&&typeof n=="object"){const i=n;i.type==="text"&&typeof i.text=="string"&&e.push(i.text)}return e.join(" ").trim()}f(A,"extractUserText");function ft(t,e,n=!1){if(!n&&e!==null&&e!==void 0){const c=Date.parse(e);if(!Number.isNaN(c))return c}const i=Date.parse(t);return Number.isNaN(i)?0:i}f(ft,"sessionMtime");function lt(t){if(t.status!=="active")return!1;try{const e=JSON.parse(_(T(q(t.node_id),"attach.json"),"utf8"));return typeof e.viewers=="number"&&e.viewers>0}catch{return!1}}f(lt,"hasLiveBrokerViewer");function dt(t,e,n){const i=t.status==="active"||t.status==="idle",c=t.fault??null;return{node_id:t.node_id,name:$(t),handle:t.name,description:t.description,status:t.status,frozen_at:t.frozen_at??null,terminal_reason:t.terminal_reason??null,kind:t.kind,mode:t.mode,ctx_tokens:n?0:t.telemetry_tokens_in??0,asks:0,cwd:t.cwd,profile_id:t.profile_id,created:t.created,lifecycle:t.lifecycle,finalized:t.final_report!=null,mtimeMs:ft(t.created,t.telemetry_updated_at,n),streaming:c===null&&i&&t.streaming===!0,hanging:c,viewed:n?!1:e.has(t.node_id)||lt(t),srcRow:t}}f(dt,"dashboardRowFromNodeRow");async function Tt(t,e,n,i){const c=t instanceof x,a=i??await t.ticketCountsForView(e).catch(()=>({})),s=new Map((n??await t.listNodes()).map(o=>[o.node_id,o]));return[e,...await t.view(e)].flatMap(o=>{const u=s.get(o);return u===void 0?[]:[{node_id:o,name:$(u),handle:u.name,description:u.description,status:u.status,frozen_at:u.frozen_at??null,terminal_reason:u.terminal_reason??null,kind:u.kind,mode:u.mode,ctx_tokens:c?0:u.telemetry_tokens_in??0,asks:a[o]??0,cwd:u.cwd,profile_id:u.profile_id,created:u.created}]})}f(Tt,"dashboardRowsFromSource");async function Ot(t,e=new Set,n=!1,i){const c=t instanceof x,a=c?new Set:e;return(i??await t.listNodes(n?{status:["active","idle"]}:void 0)).map(r=>dt(r,a,c))}f(Ot,"dashboardRowsAllFromSource");async function At(t,e,n){const i=e.filter(a=>a.enriched!==!0);if(i.length===0)return;const c=n??{};for(const a of i)a.asks=c[a.node_id]??0,a.enriched=!0}f(At,"enrichRowsFromSource");async function Rt(t,e){if(e.previewLoaded===!0)return e;const n=t instanceof x;if(e.goal=n?void 0:et(e.node_id),!n){const i=await t.getNode(e.node_id),{prompts:c,lastAssistant:a}=at(i?.pi_session_file);e.prompts=c,e.lastAssistant=a,e.recap=Q(e.node_id),e.report=it(e.node_id)}return e.previewLoaded=!0,e}f(Rt,"loadPreviewFromSource");async function vt(t,e){if(e.transcriptLoaded===!0)return e;if(t instanceof x)return e.transcript=[],e.transcriptLoaded=!0,e;const n=await t.getNode(e.node_id);return e.transcript=ct(n?.pi_session_file),e.transcriptLoaded=!0,e}f(vt,"loadTranscriptFromSource");export{dt as dashboardRowFromNodeRow,Ot as dashboardRowsAllFromSource,Tt as dashboardRowsFromSource,At as enrichRowsFromSource,j as fmtCtx,Rt as loadPreviewFromSource,vt as loadTranscriptFromSource,bt as nodeHasAssistantMessage,et as readGoalText,it as readNewestReport,at as readSessionParts,ct as readTranscript,Nt as renderForestFromSource,tt as renderTreeFromSource,ft as sessionMtime};
4
+ `)}u(Tt,"renderForestFromSource");const O=4096;function nt(t){try{const e=U(b(t),N(t,"initial-prompt.md"))?.trim()??"";return e===""?void 0:e.length>O?e.slice(0,O):e}catch{return}}u(nt,"readGoalText");const z=1024;function it(t){const e=t.match(/^(\d{4})(\d{2})(\d{2})T(\d{2})(\d{2})(\d{2})(\d{3})?$/);if(e!==null)return`${e[1]}-${e[2]}-${e[3]}T${e[4]}:${e[5]}:${e[6]}.${e[7]??"000"}Z`}u(it,"reportStampToIso");function rt(t){let e;try{for(const f of J(b(t),t)){const d=f.name;!f.isFile()||!d.endsWith(".md")||(e===void 0||d>e)&&(e=d)}}catch{return}if(e===void 0)return;let n;try{n=F(b(t),N(t,e)).toString("utf8")}catch{return}const{data:i,body:r}=I(n),s=e.replace(/\.md$/,""),a=typeof i?.kind=="string"?i.kind:s.split("-").pop()??"report",o=typeof i?.ts=="string"?i.ts:it(s.split("-")[0]??"")??"",c=r.split(`
5
+ `);let l="",h=r;for(let f=0;f<c.length;f++){const d=(c[f]??"").trim();if(d!==""){l=d.startsWith("#")?d.replace(/^#+\s*/,"").trim():d,h=c.slice(f+1).join(`
6
+ `);break}}const m=h.replace(/\s+/g," ").trim();return{kind:a,ts:o,heading:l,body:m.length>z?m.slice(0,z):m}}u(rt,"readNewestReport");const st=1<<20,ot=1<<20,at=4<<20;function B(t,e,n){if(t==null||t==="")return null;const i=v(t);if(i===null)return null;try{const{entries:r,tail:s}=A().read(i,{head:e,tail:n});return{head:r,tail:s??r}}catch(r){if(r instanceof C)return null;throw r}}u(B,"readSessionWindow");const T=8192,k=2048;function ct(t){const e=B(t,st,ot);if(e===null)return{};const n=[];let i=0;for(const a of e.head){if(a.type!=="message"||a.message.role!=="user")continue;const o=R(a.message.content);if(o===""||j({role:"user",content:o})!==null)continue;const c=o.length>k?o.slice(0,k):o;if(n.push(c),i+=c.length+1,i>=T)break}let r;if(n.length>0){const a=n.join(`
7
+ `);r=a.length>T?a.slice(0,T):a}let s;for(let a=e.tail.length-1;a>=0;a--){const o=e.tail[a];if(o.type!=="message"||o.message.role!=="assistant")continue;const c=R(o.message.content);if(c!==""){s=c.length>k?c.slice(0,k):c;break}}return{prompts:r,lastAssistant:s}}u(ct,"readSessionParts");const D=120,V=4096;function lt(t){const e=B(t,0,at);if(e===null)return[];const n=[];for(const i of e.tail){if(i.type!=="message")continue;const r=i.message.role;if(r!=="user"&&r!=="assistant")continue;const s=R(i.message.content);s!==""&&j({role:r,content:s})===null&&n.push({role:r,text:s.length>V?s.slice(0,V):s})}return n.length>D?n.slice(n.length-D):n}u(lt,"readTranscript");function Rt(t){if(t==null||t==="")return!1;const e=v(t);if(e===null)return!1;let n;try{n=A().read(e).entries}catch(i){if(i instanceof C)return!1;throw i}for(const i of n)if(!(i.type!=="message"||i.message.role!=="assistant")&&ut(i.message.content))return!0;return!1}u(Rt,"nodeHasAssistantMessage");function ut(t){if(typeof t=="string")return t.trim()!=="";if(!Array.isArray(t))return!1;for(const e of t){if(e===null||typeof e!="object")continue;const n=e,i=(n.type??"").toLowerCase();if(i==="text"){if(typeof n.text=="string"&&n.text.trim()!=="")return!0}else if(i==="thinking"){if(typeof n.thinking=="string"&&n.thinking.trim()!=="")return!0}else return!0}return!1}u(ut,"assistantContentIsSubstantive");function R(t){if(typeof t=="string")return t.trim();if(!Array.isArray(t))return"";const e=[];for(const n of t)if(n!==null&&typeof n=="object"){const i=n;i.type==="text"&&typeof i.text=="string"&&e.push(i.text)}return e.join(" ").trim()}u(R,"extractUserText");function ft(t,e,n=!1){if(!n&&e!==null&&e!==void 0){const r=Date.parse(e);if(!Number.isNaN(r))return r}const i=Date.parse(t);return Number.isNaN(i)?0:i}u(ft,"sessionMtime");function dt(t){if(t.status!=="active")return!1;try{const e=JSON.parse(F(Z(t.node_id),N(q(t.node_id),"attach.json")).toString("utf8"));return typeof e.viewers=="number"&&e.viewers>0}catch{return!1}}u(dt,"hasLiveBrokerViewer");function pt(t,e,n){const i=t.status==="active"||t.status==="idle",r=t.fault??null;return{node_id:t.node_id,name:$(t),handle:t.name,description:t.description,status:t.status,frozen_at:t.frozen_at??null,terminal_reason:t.terminal_reason??null,kind:t.kind,mode:t.mode,ctx_tokens:n?0:t.telemetry_tokens_in??0,asks:0,cwd:t.cwd,profile_id:t.profile_id,created:t.created,lifecycle:t.lifecycle,finalized:t.final_report!=null,mtimeMs:ft(t.created,t.telemetry_updated_at,n),streaming:r===null&&i&&t.streaming===!0,hanging:r,viewed:n?!1:e.has(t.node_id)||dt(t),srcRow:t}}u(pt,"dashboardRowFromNodeRow");async function vt(t,e,n,i){const r=t instanceof y,s=i??await t.ticketCountsForView(e).catch(()=>({})),a=new Map((n??await t.listNodes()).map(c=>[c.node_id,c]));return[e,...await t.view(e)].flatMap(c=>{const l=a.get(c);return l===void 0?[]:[{node_id:c,name:$(l),handle:l.name,description:l.description,status:l.status,frozen_at:l.frozen_at??null,terminal_reason:l.terminal_reason??null,kind:l.kind,mode:l.mode,ctx_tokens:r?0:l.telemetry_tokens_in??0,asks:s[c]??0,cwd:l.cwd,profile_id:l.profile_id,created:l.created}]})}u(vt,"dashboardRowsFromSource");async function At(t,e=new Set,n=!1,i){const r=t instanceof y,s=r?new Set:e;return(i??await t.listNodes(n?{status:["active","idle"]}:void 0)).map(o=>pt(o,s,r))}u(At,"dashboardRowsAllFromSource");async function Ct(t,e,n){const i=e.filter(s=>s.enriched!==!0);if(i.length===0)return;const r=n??{};for(const s of i)s.asks=r[s.node_id]??0,s.enriched=!0}u(Ct,"enrichRowsFromSource");async function Ft(t,e){if(e.previewLoaded===!0)return e;if(!(t instanceof y)){const i=await t.getNode(e.node_id),r=i?.paths,s=r===void 0?e.srcRow?.grantee??(await t.getRow(e.node_id))?.grantee:void 0;if(r===void 0&&!s)throw new Error(`node ${e.node_id} has no app assignment`);const a=r?.context_dir??K(e.node_id,s),o=r?.reports_dir??Q(e.node_id,s);e.goal=nt(a);const{prompts:c,lastAssistant:l}=ct(i?.pi_session_file);e.prompts=c,e.lastAssistant=l,e.recap=X(e.node_id),e.report=rt(o)}return e.previewLoaded=!0,e}u(Ft,"loadPreviewFromSource");async function Pt(t,e){if(e.transcriptLoaded===!0)return e;if(t instanceof y)return e.transcript=[],e.transcriptLoaded=!0,e;const n=await t.getNode(e.node_id);return e.transcript=lt(n?.pi_session_file),e.transcriptLoaded=!0,e}u(Pt,"loadTranscriptFromSource");export{pt as dashboardRowFromNodeRow,At as dashboardRowsAllFromSource,vt as dashboardRowsFromSource,Ct as enrichRowsFromSource,w as fmtCtx,Ft as loadPreviewFromSource,Pt as loadTranscriptFromSource,Rt as nodeHasAssistantMessage,nt as readGoalText,rt as readNewestReport,ct as readSessionParts,lt as readTranscript,Tt as renderForestFromSource,et as renderTreeFromSource,ft as sessionMtime};
@@ -1,3 +1,4 @@
1
+ import { type ConversationStore } from '../conversation-store/index.js';
1
2
  export interface SessionBinding {
2
3
  bindingId: string;
3
4
  sessionId: string | null;
@@ -31,3 +32,20 @@ export declare function transferSession(input: {
31
32
  }): 'transferred' | 'shutdown' | 'changed';
32
33
  export declare function unbindSession(nodeId: string): void;
33
34
  export declare function setCyclePending(nodeId: string, pending: boolean): void;
35
+ export declare function conversationOwner(conversationId: string): string | null;
36
+ /** Map only the indexed conversation paths; repair each file on first use. */
37
+ export declare function openCanvasConversationStore(root: string): ConversationStore & {
38
+ recover(rows: Array<{
39
+ session_id: string;
40
+ node_id: string;
41
+ transcript_path: string | null;
42
+ }>): void;
43
+ repair(id: string): void;
44
+ };
45
+ export declare function repairRunConversations(runId: string): void;
46
+ /** Open the canvas conversation store from the user `store` settings, install it in this
47
+ * process, and serve it for brokers. Unset settings use pi's sessions dir and
48
+ * `<CRTR_HOME>/store.sock`. */
49
+ export declare function serveCanvasConversationStore(): Promise<{
50
+ close(): Promise<void>;
51
+ }>;
@@ -1 +1,4 @@
1
- var p=Object.defineProperty;var r=(n,e)=>p(n,"name",{value:e,configurable:!0});import{randomUUID as a}from"node:crypto";import{openDb as d,withCanvasWrite as _}from"./db.js";import{canonicalSessionFile as t}from"./canvas.js";function u(){return new Date().toISOString()}r(u,"now");function c(n,e,s){return n.prepare("SELECT 1 FROM executions WHERE execution_id = ? AND node_id = ? AND state != 'exited'").get(s,e)!==void 0}r(c,"liveExecution");function l(n){return{bindingId:n.binding_id,sessionId:n.session_id??null,nodeId:n.node_id,transcriptPath:n.transcript_path??null,sourceSessionId:n.source_session_id??null,forkEntryId:n.fork_entry_id??null,createdAt:n.created_at,boundAt:n.bound_at,unboundAt:n.unbound_at??null}}r(l,"hydrate");function T(n){const e=d().prepare("SELECT * FROM sessions WHERE node_id = ? AND unbound_at IS NULL").get(n);return e===void 0?null:l(e)}r(T,"readLiveSession");function I(n){return d().prepare("SELECT node_id FROM sessions WHERE transcript_path = ? AND unbound_at IS NULL").get(t(n))?.node_id??null}r(I,"findNodeBySessionFileSql");function g(n,e){return _(s=>{if(!c(s,n,e.executionId))return"shutdown";const i=u(),E=e.transcriptPath===null?null:t(e.transcriptPath),o=s.prepare("SELECT binding_id, session_id FROM sessions WHERE node_id = ? AND unbound_at IS NULL").get(n);return o!==void 0&&o.session_id===e.sessionId?s.prepare("UPDATE sessions SET transcript_path = ?, source_session_id = ?, bound_at = ? WHERE binding_id = ?").run(E,e.sourceSessionId??null,i,o.binding_id):(o!==void 0&&s.prepare("UPDATE sessions SET unbound_at = ? WHERE binding_id = ?").run(i,o.binding_id),s.prepare("INSERT INTO sessions (binding_id, session_id, node_id, transcript_path, source_session_id, fork_entry_id, created_at, bound_at) VALUES (?, ?, ?, ?, ?, NULL, ?, ?)").run(a(),e.sessionId,n,E,e.sourceSessionId??null,i,i)),s.prepare("UPDATE nodes SET cycle_pending = 0 WHERE node_id = ?").run(n),"bound"})}r(g,"bindSession");function U(n,e){_(s=>{const i=u();s.prepare("UPDATE sessions SET unbound_at = ? WHERE node_id = ? AND unbound_at IS NULL").run(i,n),s.prepare("INSERT INTO sessions (binding_id, session_id, node_id, transcript_path, source_session_id, fork_entry_id, created_at, bound_at) VALUES (?, ?, ?, ?, NULL, NULL, ?, ?)").run(a(),e.sessionId,n,e.transcriptPath===null?null:t(e.transcriptPath),i,i),s.prepare("UPDATE nodes SET cycle_pending = 0 WHERE node_id = ?").run(n)})}r(U,"resetSession");function A(n){return _(e=>{if(!c(e,n.toNodeId,n.executionId))return"shutdown";if(e.prepare("SELECT binding_id FROM sessions WHERE node_id = ? AND binding_id = ? AND unbound_at IS NULL").get(n.fromNodeId,n.fromBindingId)===void 0)return"changed";const i=u();return e.prepare("UPDATE sessions SET unbound_at = ? WHERE binding_id = ?").run(i,n.fromBindingId),e.prepare("UPDATE sessions SET unbound_at = ? WHERE node_id = ? AND unbound_at IS NULL").run(i,n.toNodeId),e.prepare("INSERT INTO sessions (binding_id, session_id, node_id, transcript_path, source_session_id, fork_entry_id, created_at, bound_at) VALUES (?, ?, ?, ?, NULL, NULL, ?, ?)").run(a(),n.sessionId,n.toNodeId,n.transcriptPath===null?null:t(n.transcriptPath),i,i),e.prepare("UPDATE nodes SET cycle_pending = 0 WHERE node_id = ?").run(n.toNodeId),"transferred"})}r(A,"transferSession");function b(n){d().prepare("UPDATE sessions SET unbound_at = ? WHERE node_id = ? AND unbound_at IS NULL").run(u(),n)}r(b,"unbindSession");function D(n,e){d().prepare("UPDATE nodes SET cycle_pending = ? WHERE node_id = ?").run(e?1:0,n)}r(D,"setCyclePending");export{g as bindSession,I as findNodeBySessionFileSql,T as readLiveSession,U as resetSession,D as setCyclePending,A as transferSession,b as unbindSession};
1
+ var v=Object.defineProperty;var i=(n,e)=>v(n,"name",{value:e,configurable:!0});import{randomUUID as R}from"node:crypto";import{closeSync as C,existsSync as w,openSync as U,readSync as A,statSync as W,truncateSync as g,unlinkSync as m}from"node:fs";import{openDb as d,withCanvasWrite as p}from"./db.js";import{canonicalSessionFile as L}from"./canvas.js";import{join as I}from"node:path";import{readConfig as h}from"../config.js";import{appSpace as y,socketDir as H}from"../layout.js";import{createFileStore as M,conversationStore as F,defaultConversationRoot as x,installConversationStore as D}from"../conversation-store/index.js";import{listenConversationStore as P}from"../conversation-store/listener.js";import{appendConversationEvents as O}from"../../daemon/runs/append-section.js";function f(){return new Date().toISOString()}i(f,"now");function b(n,e,s){return n.prepare("SELECT 1 FROM executions WHERE execution_id = ? AND node_id = ? AND state != 'exited'").get(s,e)!==void 0}i(b,"liveExecution");function B(n){return{bindingId:n.binding_id,sessionId:n.session_id??null,nodeId:n.node_id,transcriptPath:n.transcript_path??null,sourceSessionId:n.source_session_id??null,forkEntryId:n.fork_entry_id??null,createdAt:n.created_at,boundAt:n.bound_at,unboundAt:n.unbound_at??null}}i(B,"hydrate");function en(n){const e=d().prepare("SELECT * FROM sessions WHERE node_id = ? AND unbound_at IS NULL").get(n);return e===void 0?null:B(e)}i(en,"readLiveSession");function sn(n){return d().prepare("SELECT node_id FROM sessions WHERE transcript_path = ? AND unbound_at IS NULL").get(L(n))?.node_id??null}i(sn,"findNodeBySessionFileSql");function on(n,e){return p(s=>{if(!b(s,n,e.executionId))return"shutdown";const o=f(),r=e.transcriptPath===null?null:L(e.transcriptPath),a=s.prepare("SELECT binding_id, session_id FROM sessions WHERE node_id = ? AND unbound_at IS NULL").get(n);if(a!==void 0&&a.session_id===e.sessionId)s.prepare("UPDATE sessions SET transcript_path = ?, source_session_id = ?, bound_at = ? WHERE binding_id = ?").run(r,e.sourceSessionId??null,o,a.binding_id);else{a!==void 0&&s.prepare("UPDATE sessions SET unbound_at = ? WHERE binding_id = ?").run(o,a.binding_id);const t=e.sessionId===null?void 0:s.prepare("SELECT binding_id FROM sessions WHERE node_id = ? AND session_id = ? ORDER BY created_at DESC LIMIT 1").get(n,e.sessionId);t?s.prepare("UPDATE sessions SET transcript_path = ?, source_session_id = ?, bound_at = ?, unbound_at = NULL WHERE binding_id = ?").run(r,e.sourceSessionId??null,o,t.binding_id):s.prepare("INSERT INTO sessions (binding_id, session_id, node_id, transcript_path, source_session_id, fork_entry_id, created_at, bound_at) VALUES (?, ?, ?, ?, ?, NULL, ?, ?)").run(R(),e.sessionId,n,r,e.sourceSessionId??null,o,o)}return s.prepare("UPDATE nodes SET cycle_pending = 0 WHERE node_id = ?").run(n),"bound"})}i(on,"bindSession");function rn(n,e){p(s=>{const o=f();s.prepare("UPDATE sessions SET unbound_at = ? WHERE node_id = ? AND unbound_at IS NULL").run(o,n),s.prepare("INSERT INTO sessions (binding_id, session_id, node_id, transcript_path, source_session_id, fork_entry_id, created_at, bound_at) VALUES (?, ?, ?, ?, NULL, NULL, ?, ?)").run(R(),e.sessionId,n,e.transcriptPath===null?null:L(e.transcriptPath),o,o),s.prepare("UPDATE nodes SET cycle_pending = 0 WHERE node_id = ?").run(n)})}i(rn,"resetSession");function tn(n){return p(e=>{if(!b(e,n.toNodeId,n.executionId))return"shutdown";if(e.prepare("SELECT binding_id FROM sessions WHERE node_id = ? AND binding_id = ? AND unbound_at IS NULL").get(n.fromNodeId,n.fromBindingId)===void 0)return"changed";if(e.prepare("SELECT run_id FROM nodes WHERE node_id IN (?, ?) AND run_id IS NOT NULL LIMIT 1").get(n.fromNodeId,n.toNodeId))throw new Error("run conversation transfer is not supported");const r=f();return e.prepare("UPDATE sessions SET unbound_at = ? WHERE binding_id = ?").run(r,n.fromBindingId),e.prepare("UPDATE sessions SET unbound_at = ? WHERE node_id = ? AND unbound_at IS NULL").run(r,n.toNodeId),e.prepare("INSERT INTO sessions (binding_id, session_id, node_id, transcript_path, source_session_id, fork_entry_id, created_at, bound_at) VALUES (?, ?, ?, ?, NULL, NULL, ?, ?)").run(R(),n.sessionId,n.toNodeId,n.transcriptPath===null?null:L(n.transcriptPath),r,r),e.prepare("UPDATE nodes SET cycle_pending = 0 WHERE node_id = ?").run(n.toNodeId),"transferred"})}i(tn,"transferSession");function dn(n){d().prepare("UPDATE sessions SET unbound_at = ? WHERE node_id = ? AND unbound_at IS NULL").run(f(),n)}i(dn,"unbindSession");function an(n,e){d().prepare("UPDATE nodes SET cycle_pending = ? WHERE node_id = ?").run(e?1:0,n)}i(an,"setCyclePending");const T="unbound_at IS NULL DESC, created_at DESC, rowid DESC";function _n(n){return d().prepare(`SELECT node_id FROM sessions WHERE session_id = ? ORDER BY ${T} LIMIT 1`).get(n)?.node_id??null}i(_n,"conversationOwner");const $={appendSection:i((n,e,s)=>{const o=e.kind==="create"?e:void 0;o&&p(r=>{if(!r.prepare("SELECT node_id FROM nodes WHERE node_id = ?").get(o.nodeId))throw new Error(`missing conversation owner ${o.nodeId}`);const t=f();r.prepare("INSERT INTO sessions (binding_id, session_id, node_id, transcript_path, source_session_id, fork_entry_id, created_at, bound_at, unbound_at, event_offset) VALUES (?, ?, ?, ?, ?, NULL, ?, ?, ?, 0)").run(R(),n,o.nodeId,o.path,o.sourceId??null,t,t,t)}),p(r=>{const a=r.prepare(`SELECT node_id, binding_id, input_ids_json FROM sessions WHERE session_id = ? ORDER BY ${T} LIMIT 1`).get(n),t=o?o.nodeId:a?.node_id;if(!t)throw new Error(`conversation ${n} has no active owner`);const u=r.prepare("SELECT run_id FROM nodes WHERE node_id = ?").get(t);if(!u)throw new Error(`cannot write conversation ${n}: missing node ${t}`);if(e.kind==="replace"&&u.run_id!==null)throw new Error(`run conversation ${n} is append-only; replace refused`);const l=a.binding_id,S=s();if(u.run_id!==null&&e.kind!=="replace"){const E=o?.sourceId?[]:e.entries,_=O(r,u.run_id,t,E,JSON.parse(a?.input_ids_json??"[]"));r.prepare("UPDATE sessions SET event_offset = ?, indexed_entry_id = ?, input_ids_json = ? WHERE binding_id = ?").run(S,E.at(-1)?.id??null,JSON.stringify(_),l)}})},"appendSection"),abortCreate(n){d().prepare("DELETE FROM sessions WHERE session_id = ? AND event_offset = 0").run(n)},delete(n){d().prepare("DELETE FROM sessions WHERE session_id = ?").run(n)},pathFor(n){return d().prepare(`SELECT transcript_path FROM sessions WHERE session_id = ? ORDER BY ${T} LIMIT 1`).get(n)?.transcript_path??void 0},createPath(n,e){const s=d().prepare("SELECT grantee FROM nodes WHERE node_id = ?").get(n);if(!s)throw new Error(`missing conversation owner ${n}`);return I(y(s.grantee).conversations,n,`${e.timestamp.replace(/[:.]/g,"-")}_${e.id}.jsonl`)},repair(n,e){k(n,e)},owners(){const n=new Map,e=d().prepare(`SELECT session_id, node_id FROM sessions WHERE session_id IS NOT NULL ORDER BY session_id, ${T}`).all();for(const s of e)n.has(s.session_id)||n.set(s.session_id,s.node_id);return n}};function k(n,e){const s=d().prepare(`SELECT s.binding_id, s.node_id, s.event_offset, s.input_ids_json, s.source_session_id, n.run_id
2
+ FROM sessions s JOIN nodes n ON n.node_id = s.node_id WHERE s.session_id = ? ORDER BY s.unbound_at IS NULL DESC, s.created_at DESC, s.rowid DESC LIMIT 1`).get(n);if(!s?.run_id||s.event_offset===null)return;if(s.event_offset===0&&!w(e)){d().prepare("DELETE FROM sessions WHERE binding_id = ?").run(s.binding_id);return}const o=W(e).size;if(o<s.event_offset)throw new Error(`conversation shorter than indexed offset: ${n}`);if(o===s.event_offset)return;const r=U(e,"r"),a=[];try{const _=Buffer.allocUnsafe(65536);for(let c=s.event_offset;c<o;){const N=A(r,_,0,Math.min(_.length,o-c),c);if(!N)throw new Error(`conversation read ended early: ${n}`);a.push(Buffer.from(_.subarray(0,N))),c+=N}}finally{C(r)}const t=Buffer.concat(a).toString("utf8"),u=t.lastIndexOf(`
3
+ `);if(u<0){s.event_offset===0?(m(e),d().prepare("DELETE FROM sessions WHERE binding_id = ?").run(s.binding_id)):g(e,s.event_offset);return}const l=t.slice(0,u+1),S=l.split(`
4
+ `).filter(Boolean).map(_=>JSON.parse(_)).filter(_=>_.type!=="session"),E=s.event_offset+Buffer.byteLength(l);E<o&&g(e,E),p(_=>{const c=s.source_session_id?[]:O(_,s.run_id,s.node_id,S,JSON.parse(s.input_ids_json));_.prepare("UPDATE sessions SET event_offset = ?, indexed_entry_id = ?, input_ids_json = ? WHERE binding_id = ?").run(E,S.at(-1)?.id??null,JSON.stringify(c),s.binding_id)})}i(k,"repairConversationTail");function j(n){return M(n,$)}i(j,"openCanvasConversationStore");function un(n){const e=d().prepare("SELECT DISTINCT s.session_id FROM sessions s JOIN nodes n ON n.node_id = s.node_id WHERE n.run_id = ? AND s.session_id IS NOT NULL").all(n),s=F();for(const o of e)s.repair?.(o.session_id)}i(un,"repairRunConversations");async function En(){const n=h("user").store,e=n?.address??I(H(),"store.sock"),s=j(n?.root??x());D(s),process.env.CRTR_STORE_ADDRESS=e;const o=await P(e,s);return{async close(){await o.close(),D(void 0)}}}i(En,"serveCanvasConversationStore");export{on as bindSession,_n as conversationOwner,sn as findNodeBySessionFileSql,j as openCanvasConversationStore,en as readLiveSession,un as repairRunConversations,rn as resetSession,En as serveCanvasConversationStore,an as setCyclePending,tn as transferSession,dn as unbindSession};
@@ -55,12 +55,7 @@ export interface LaunchSpec {
55
55
  /** Model id/pattern passed to pi `--model`. */
56
56
  model?: string;
57
57
  /** Original logical family/strength preference, retained after normalization. */
58
- modelIntent?: {
59
- family: string;
60
- strength: import('../../types.js').ModelStrength;
61
- };
62
- /** True only for a caller's explicit concrete `provider/id` override. */
63
- modelProviderPinned?: boolean;
58
+ modelIntent?: import('../../types.js').ModelIntent;
64
59
  /** True for an exact-consult launch: `model` is the verbatim captured
65
60
  * `provider/id:thinking` spec, bypassing the review floor/normalize and
66
61
  * every launch-time/turn-time provider fallback — an unavailable exact
@@ -259,6 +254,16 @@ export interface NodeIdentity {
259
254
  model_override?: string | null;
260
255
  /** Per-run allow-list; null inherits the full runtime vocabulary. */
261
256
  scopes?: string[] | null;
257
+ grantee?: string;
258
+ sub?: string | null;
259
+ grant_id?: string | null;
260
+ client_id?: string | null;
261
+ metadata_json?: string | null;
262
+ run_id?: string | null;
263
+ event_cursor?: number | null;
264
+ last_activity_at?: string | null;
265
+ usage_json?: string | null;
266
+ deleting_at?: string | null;
262
267
  /** Full pi launch recipe; rewritten on every polymorph. */
263
268
  launch?: LaunchSpec;
264
269
  /** Managed git worktree owned by this node (if any). */
@@ -351,6 +356,7 @@ export interface NodeMemoryTarget {
351
356
  nodeId: string;
352
357
  cwd: string;
353
358
  profileId: string | null;
359
+ grantee: string;
354
360
  }
355
361
  export interface NodeRow {
356
362
  node_id: string;
@@ -374,6 +380,16 @@ export interface NodeRow {
374
380
  profile_id: string | null;
375
381
  /** Per-run allow-list; null inherits the full runtime vocabulary. */
376
382
  scopes: string[] | null;
383
+ grantee?: string;
384
+ sub?: string | null;
385
+ grant_id?: string | null;
386
+ client_id?: string | null;
387
+ metadata_json?: string | null;
388
+ run_id?: string | null;
389
+ event_cursor?: number | null;
390
+ last_activity_at?: string | null;
391
+ usage_json?: string | null;
392
+ deleting_at?: string | null;
377
393
  parent: string | null;
378
394
  created: string;
379
395
  /** Authoritative runtime columns (see NodeRuntime). */
@@ -1 +1 @@
1
- var v=Object.defineProperty;var p=(n,r)=>v(n,"name",{value:r,configurable:!0});import{ExitCode as w}from"../../types.js";import{CrtrError as $}from"../errors.js";import{operationIdContext as E}from"../events/operation-id.js";import{createCoreHookCatalog as k}from"./catalog.js";function A(n,r){const o=k(n),a=p((t,e)=>{if(t.kind==="leaf"){const i=e.join(" ");return o.has(i)?Object.freeze({...t,effectiveHelp:x(t,i,r),run:j(t,e,r)}):t}return{...t,children:t.children.map(i=>a(i,[...e,i.name]))}},"visit");return n.map(t=>a(t,[t.name]))}p(A,"composeCoreHooks");function x(n,r,o){return async()=>{const{projectEffectiveLeafHelp:a}=await import("./help.js");try{const t=await o();return a(n.help,t.valid?t.plans.get(r):void 0)}catch{return a(n.help)}}}p(x,"projectedHelp");function j(n,r,o){const a=n.run,t=r.join(" ");return async(e,i)=>{const f=await o();if(!f.valid)throw y(t,f.issues);const d=f.plans.get(t);if(d===void 0)return a(e,i);const l=E.current();if(l===void 0)throw new $("internal",`\`${t}\` ran outside a crouter operation identity, so its plugin hooks cannot be dispatched.`,w.GENERAL,{command:[...r]});const{invokeExecHook:s}=await import("./transport/exec-invoke.js"),u=p(c=>({plugin:c.plugin.name,executable:c.executable,op:c.op,phase:c.phase,commandPath:r,...c.phase==="replace"?{output:n.help.output}:{}}),"spec"),h=[...i?.providedParams??[]];for(const c of d.before)await s(u(c),{operationId:l,input:e,providedParams:h});const g=d.replacements[0],m=g===void 0?await a(e,i):await s(u(g),{operationId:l,input:e,providedParams:h});for(const c of d.after)await s(u(c),{operationId:l,input:e,providedParams:h,...m===void 0?{}:{result:m}});return m}}p(j,"hookedRun");function y(n,r){const o=r[0],a=r.map(e=>`${e.plugin} (${e.scope}) ${e.path??"hooks"}: ${e.message} \u2014 received ${e.received}, expected ${e.expected}`).join("; "),t=[...new Set(r.map(e=>e.plugin))];return new $(o.code,`\`${n}\` cannot run: ${String(r.length)} unusable hook declaration${r.length===1?"":"s"} \u2014 ${a}.`,w.GENERAL,{received:o.received,...o.path===void 0?{}:{field:o.path},next:`${o.next} ${t.map(e=>`\`crtr pkg plugin show ${e}\``).join(" and ")} or \`crtr sys doctor\` reports the same issues; disabling the plugin also clears them.`})}p(y,"registryError");export{A as composeCoreHooks};
1
+ var $=Object.defineProperty;var p=(n,r)=>$(n,"name",{value:r,configurable:!0});import{ExitCode as w}from"../../types.js";import{CrtrError as v}from"../errors.js";import{operationIdContext as E}from"../events/operation-id.js";import{createCoreHookCatalog as x}from"./catalog.js";function A(n,r){const a=x(n),c=p((t,e)=>{if(t.kind==="leaf"){const o=e.join(" ");return a.has(o)?Object.freeze({...t,effectiveHelp:H(t,o,r),run:j(t,e,r)}):t}return{...t,children:t.children.map(o=>c(o,[...e,o.name]))}},"visit");return n.map(t=>c(t,[t.name]))}p(A,"composeCoreHooks");function H(n,r,a){return async c=>{const{projectEffectiveLeafHelp:t}=await import("./help.js"),e=n.effectiveHelp!==void 0?await n.effectiveHelp(c):n.help;try{const o=await a();return t(e,o.valid?o.plans.get(r):void 0)}catch{return t(e)}}}p(H,"projectedHelp");function j(n,r,a){const c=n.run,t=r.join(" ");return async(e,o)=>{const f=await a();if(!f.valid)throw k(t,f.issues);const d=f.plans.get(t);if(d===void 0)return c(e,o);const l=E.current();if(l===void 0)throw new v("internal",`\`${t}\` ran outside a crouter operation identity, so its plugin hooks cannot be dispatched.`,w.GENERAL,{command:[...r]});const{invokeExecHook:s}=await import("./transport/exec-invoke.js"),u=p(i=>({id:i.id,plugin:i.plugin.name,executable:i.executable,op:i.op,phase:i.phase,commandPath:r,...i.phase==="replace"?{output:n.help.output}:{}}),"spec"),m=[...o?.providedParams??[]];for(const i of d.before)await s(u(i),{operationId:l,input:e,providedParams:m});const g=d.replacements[0],h=g===void 0?await c(e,o):await s(u(g),{operationId:l,input:e,providedParams:m});for(const i of d.after)await s(u(i),{operationId:l,input:e,providedParams:m,...h===void 0?{}:{result:h}});return h}}p(j,"hookedRun");function k(n,r){const a=r[0],c=r.map(e=>`${e.plugin} (${e.scope}) ${e.path??"hooks"}: ${e.message} \u2014 received ${e.received}, expected ${e.expected}`).join("; "),t=[...new Set(r.map(e=>e.plugin))];return new v(a.code,`\`${n}\` cannot run: ${String(r.length)} unusable hook declaration${r.length===1?"":"s"} \u2014 ${c}.`,w.GENERAL,{received:a.received,...a.path===void 0?{}:{field:a.path},next:`${a.next} ${t.map(e=>`\`crtr pkg plugin show ${e}\``).join(" and ")} or \`crtr sys doctor\` reports the same issues; disabling the plugin also clears them.`})}p(k,"registryError");export{A as composeCoreHooks};
@@ -21,6 +21,8 @@ export interface HookPluginAttribution {
21
21
  }
22
22
  /** One declaration resolved to the local executable that will receive it. */
23
23
  export interface EffectiveHook {
24
+ /** Stable identity within this plugin's effective declaration set. */
25
+ id: string;
24
26
  executable: string;
25
27
  plugin: HookPluginAttribution;
26
28
  target: string;
@@ -70,6 +72,18 @@ export interface HookPluginValidation {
70
72
  hooks: readonly EffectiveHook[];
71
73
  issues: readonly HookDiscoveryIssue[];
72
74
  }
75
+ export type RemoteHookMetadata = Pick<EffectiveHook, 'id' | 'target' | 'phase' | 'op' | 'description' | 'effects' | 'declarationIndex'> & {
76
+ plugin: string;
77
+ };
78
+ export declare function hookIdentity(hook: {
79
+ plugin: {
80
+ name: string;
81
+ };
82
+ target: string;
83
+ phase: HookPhase;
84
+ op: string;
85
+ declarationIndex: number;
86
+ }): string;
73
87
  export interface HookRegistry {
74
88
  catalog: CoreHookCatalog;
75
89
  hooks: readonly EffectiveHook[];
@@ -97,7 +111,7 @@ export interface HookPluginCandidate {
97
111
  * Statically compiles hooks from already-resolved effective plugins. It reads
98
112
  * manifest files to validate them but never executes a plugin executable.
99
113
  */
100
- export declare function compileHookRegistry(catalog: CoreHookCatalog, plugins: readonly InstalledPlugin[]): HookRegistry;
114
+ export declare function compileHookRegistry(catalog: CoreHookCatalog, plugins: readonly InstalledPlugin[], remote?: readonly RemoteHookMetadata[]): HookRegistry;
101
115
  /** Compiles lifecycle declarations from resolved plugins without loading the command tree. */
102
116
  export declare function compileLifecycleHookRegistry(plugins: readonly InstalledPlugin[]): LifecycleHookRegistry;
103
117
  /** Discovers lifecycle hooks for one node's resolved cwd and profile. */
@@ -1 +1 @@
1
- var R=Object.defineProperty;var u=(t,n)=>R(t,"name",{value:n,configurable:!0});import{listInstalledPluginsInRoot as b}from"../resolver.js";import{projectScopeRoots as w,userScopeRoot as C}from"../scope.js";import{validatePluginHookArtifact as j}from"./artifact.js";function O(t){return t.manifest.hooks!==void 0||t.manifest.hookExecutable!==void 0}u(O,"hasHookDeclaration");function x(t){const n=new Set,s=[];for(const a of t){const p=b(a.scope,a.root).sort((c,r)=>c.name<r.name?-1:c.name>r.name?1:0);for(const c of p)n.has(c.name)||(n.add(c.name),c.enabled&&O(c)&&s.push(c))}return s}u(x,"orderedPluginsInScopes");function v(t=process.cwd(),n){return[...w(t,n).map(s=>({scope:"project",root:s})),{scope:"user",root:C()}]}u(v,"hookDiscoveryScopes");function z(t=process.cwd(),n){return x(v(t,n))}u(z,"effectiveHookPlugins");function I(t,n=process.cwd(),s){const a=new Set,p=[];for(const c of v(n,s)){const r=t.filter(e=>e.plugin.scope===c.scope&&e.scopeRoot===c.root),i=new Set(r.map(e=>e.plugin.name)),o=[...b(c.scope,c.root).filter(e=>!i.has(e.name)),...r.map(e=>e.plugin)];o.sort((e,l)=>e.name<l.name?-1:e.name>l.name?1:0);for(const e of o)a.has(e.name)||(a.add(e.name),e.enabled&&O(e)&&p.push(e))}return p}u(I,"effectiveHookPluginsWithCandidates");function h(t,n){return{...n,plugin:t.name,scope:t.scope}}u(h,"issue");function k(t,n){return n.map(s=>h(t,s))}u(k,"artifactIssues");function H(t,n,s){const a=[];return n.forEach((p,c)=>{s.has(p.target)||a.push(h(t,{code:"command_hook_target_invalid",path:`hooks[${c}].target`,message:`hook target "${p.target}" is not an eligible core returned-object leaf`,received:p.target,expected:"an exact eligible core leaf path",next:"Choose a current returned-object core leaf; pkg plugin, sys doctor, JSONL, passthrough, and UI/void surfaces are unavailable."}))}),a}u(H,"targetIssues");function g(t,n){const s=[],a=[],p=[];let c=0;for(const o of n){const e=j(o.root,o.manifest),l=k(o,e.issues);let f=[];if(l.length===0&&e.manifest!==void 0&&e.executablePath!==void 0){const d=H(o,e.manifest.hooks,t);l.push(...d),l.length===0&&(f=e.manifest.hooks.map((m,y)=>Object.freeze({executable:e.executablePath,plugin:Object.freeze({name:o.name,scope:o.scope,root:o.root}),target:m.target,phase:m.phase,op:m.op,description:m.description,effects:Object.freeze([...m.effects]),declarationIndex:y,order:c++})),a.push(...f))}s.push(Object.freeze({plugin:o,...e.manifestPath===void 0?{}:{manifestPath:e.manifestPath},...e.executablePath===void 0?{}:{executablePath:e.executablePath},...e.manifest===void 0?{}:{manifest:e.manifest},lifecycleCandidates:Object.freeze([...e.lifecycleCandidates]),hooks:Object.freeze(f),issues:Object.freeze(l)})),p.push(...l)}const r=new Map;for(const o of a){const e=r.get(o.target);e===void 0?r.set(o.target,[o]):e.push(o)}const i=new Map;for(const[o,e]of r){const l=e.filter(f=>f.phase==="replace");if(l.length>1)for(const f of l)p.push(h(f.plugin,{code:"command_hook_collision",path:`hooks[${f.declarationIndex}]`,message:`multiple replacements target "${o}"`,received:l.map(d=>`${d.plugin.name}:${d.op}`).join(", "),expected:"exactly one replacement for this core leaf",next:"Remove or change one replace declaration; before and after hooks may coexist with one replacement."}));i.set(o,Object.freeze({target:o,before:Object.freeze(e.filter(f=>f.phase==="before")),after:Object.freeze(e.filter(f=>f.phase==="after").reverse()),replacements:Object.freeze(l)}))}return Object.freeze({catalog:t,hooks:Object.freeze(a),plans:i,validations:Object.freeze(s),issues:Object.freeze(p),valid:p.length===0})}u(g,"compileHookRegistry");function P(t){const n=[],s=[],a=[];let p=0;for(const r of t){const i=j(r.root,r.manifest),o=k(r,i.issues);let e=[];o.length===0&&i.manifest!==void 0&&i.executablePath!==void 0&&(e=(i.manifest.schemaVersion===2?i.manifest.lifecycle:[]).map((f,d)=>Object.freeze({executable:i.executablePath,plugin:Object.freeze({name:r.name,scope:r.scope,root:r.root}),event:f.event,phase:f.phase,op:f.op,description:f.description,effects:Object.freeze([...f.effects]),declarationIndex:d,order:p++})),s.push(...e)),n.push(Object.freeze({plugin:r,...i.manifestPath===void 0?{}:{manifestPath:i.manifestPath},...i.executablePath===void 0?{}:{executablePath:i.executablePath},...i.manifest===void 0?{}:{manifest:i.manifest},lifecycleCandidates:Object.freeze([...i.lifecycleCandidates]),hooks:Object.freeze([]),issues:Object.freeze(o)})),a.push(...o)}const c=new Map;for(const r of s){const i=c.get(r.event)??[];c.set(r.event,Object.freeze([...i,r]))}return Object.freeze({hooks:Object.freeze(s),plans:c,validations:Object.freeze(n),issues:Object.freeze(a),valid:a.length===0})}u(P,"compileLifecycleHookRegistry");function T(t,n){return process.env.CRTR_TEST_DISABLE_LIFECYCLE_HOOK_DISCOVERY==="1"?P([]):P(z(t,n))}u(T,"discoverLifecycleHookRegistry");function D(t,n=process.cwd(),s){return g(t,z(n,s))}u(D,"discoverHookRegistry");function M(t,n,s,a=process.cwd(),p){return S(t,[{plugin:n,scopeRoot:s}],a,p)}u(M,"discoverCandidateHookRegistry");function S(t,n,s=process.cwd(),a){return g(t,I(n,s,a))}u(S,"discoverCandidateHookRegistryForCandidates");function A(t,n){return g(t,x(n))}u(A,"discoverHookRegistryInScopes");export{g as compileHookRegistry,P as compileLifecycleHookRegistry,M as discoverCandidateHookRegistry,S as discoverCandidateHookRegistryForCandidates,D as discoverHookRegistry,A as discoverHookRegistryInScopes,T as discoverLifecycleHookRegistry,z as effectiveHookPlugins,v as hookDiscoveryScopes};
1
+ var R=Object.defineProperty;var p=(t,n)=>R(t,"name",{value:n,configurable:!0});import{isSandboxedNode as I}from"../../shared/env.js";import{listInstalledPluginsInRoot as O}from"../resolver.js";import{projectScopeRoots as S,userScopeRoot as C}from"../scope.js";import{validatePluginHookArtifact as x}from"./artifact.js";function H(t){return JSON.stringify([t.plugin.name,t.target,t.phase,t.op,t.declarationIndex])}p(H,"hookIdentity");function z(t){return t.manifest.hooks!==void 0||t.manifest.hookExecutable!==void 0}p(z,"hasHookDeclaration");function v(t){const n=new Set,r=[];for(const i of t){const f=O(i.scope,i.root).sort((o,a)=>o.name<a.name?-1:o.name>a.name?1:0);for(const o of f)n.has(o.name)||(n.add(o.name),o.enabled&&z(o)&&r.push(o))}return r}p(v,"orderedPluginsInScopes");function y(t=process.cwd(),n){return[...S(t,n).map(r=>({scope:"project",root:r})),...I()?[]:[{scope:"user",root:C()}]]}p(y,"hookDiscoveryScopes");function P(t=process.cwd(),n){return v(y(t,n))}p(P,"effectiveHookPlugins");function _(t,n=process.cwd(),r){const i=new Set,f=[];for(const o of y(n,r)){const a=t.filter(e=>e.plugin.scope===o.scope&&e.scopeRoot===o.root),c=new Set(a.map(e=>e.plugin.name)),d=[...O(o.scope,o.root).filter(e=>!c.has(e.name)),...a.map(e=>e.plugin)];d.sort((e,s)=>e.name<s.name?-1:e.name>s.name?1:0);for(const e of d)i.has(e.name)||(i.add(e.name),e.enabled&&z(e)&&f.push(e))}return f}p(_,"effectiveHookPluginsWithCandidates");function g(t,n){return{...n,plugin:t.name,scope:t.scope}}p(g,"issue");function k(t,n){return n.map(r=>g(t,r))}p(k,"artifactIssues");function E(t,n,r){const i=[];return n.forEach((f,o)=>{r.has(f.target)||i.push(g(t,{code:"command_hook_target_invalid",path:`hooks[${o}].target`,message:`hook target "${f.target}" is not an eligible core returned-object leaf`,received:f.target,expected:"an exact eligible core leaf path",next:"Choose a current returned-object core leaf; pkg plugin, sys doctor, JSONL, passthrough, and UI/void surfaces are unavailable."}))}),i}p(E,"targetIssues");function b(t,n,r=[]){const i=[],f=[],o=[];let a=0;for(const e of n){const s=x(e.root,e.manifest),u=k(e,s.issues);let l=[];if(u.length===0&&s.manifest!==void 0&&s.executablePath!==void 0){const h=E(e,s.manifest.hooks,t);u.push(...h),u.length===0&&(l=s.manifest.hooks.map((m,j)=>Object.freeze({id:H({plugin:{name:e.name},...m,declarationIndex:j}),executable:s.executablePath,plugin:Object.freeze({name:e.name,scope:e.scope,root:e.root}),target:m.target,phase:m.phase,op:m.op,description:m.description,effects:Object.freeze([...m.effects]),declarationIndex:j,order:a++})),f.push(...l))}i.push(Object.freeze({plugin:e,...s.manifestPath===void 0?{}:{manifestPath:s.manifestPath},...s.executablePath===void 0?{}:{executablePath:s.executablePath},...s.manifest===void 0?{}:{manifest:s.manifest},lifecycleCandidates:Object.freeze([...s.lifecycleCandidates]),hooks:Object.freeze(l),issues:Object.freeze(u)})),o.push(...u)}for(const e of r){if(!t.has(e.target))throw new Error(`daemon supplied an ineligible hook target: ${e.target}`);f.push(Object.freeze({...e,executable:"",plugin:Object.freeze({name:e.plugin,scope:"user",root:""}),order:a++}))}const c=new Map;for(const e of f){const s=c.get(e.target);s===void 0?c.set(e.target,[e]):s.push(e)}const d=new Map;for(const[e,s]of c){const u=s.filter(l=>l.phase==="replace");if(u.length>1)for(const l of u)o.push(g(l.plugin,{code:"command_hook_collision",path:`hooks[${l.declarationIndex}]`,message:`multiple replacements target "${e}"`,received:u.map(h=>`${h.plugin.name}:${h.op}`).join(", "),expected:"exactly one replacement for this core leaf",next:"Remove or change one replace declaration; before and after hooks may coexist with one replacement."}));d.set(e,Object.freeze({target:e,before:Object.freeze(s.filter(l=>l.phase==="before")),after:Object.freeze(s.filter(l=>l.phase==="after").reverse()),replacements:Object.freeze(u)}))}return Object.freeze({catalog:t,hooks:Object.freeze(f),plans:d,validations:Object.freeze(i),issues:Object.freeze(o),valid:o.length===0})}p(b,"compileHookRegistry");function w(t){const n=[],r=[],i=[];let f=0;for(const a of t){const c=x(a.root,a.manifest),d=k(a,c.issues);let e=[];d.length===0&&c.manifest!==void 0&&c.executablePath!==void 0&&(e=(c.manifest.schemaVersion===2?c.manifest.lifecycle:[]).map((u,l)=>Object.freeze({executable:c.executablePath,plugin:Object.freeze({name:a.name,scope:a.scope,root:a.root}),event:u.event,phase:u.phase,op:u.op,description:u.description,effects:Object.freeze([...u.effects]),declarationIndex:l,order:f++})),r.push(...e)),n.push(Object.freeze({plugin:a,...c.manifestPath===void 0?{}:{manifestPath:c.manifestPath},...c.executablePath===void 0?{}:{executablePath:c.executablePath},...c.manifest===void 0?{}:{manifest:c.manifest},lifecycleCandidates:Object.freeze([...c.lifecycleCandidates]),hooks:Object.freeze([]),issues:Object.freeze(d)})),i.push(...d)}const o=new Map;for(const a of r){const c=o.get(a.event)??[];o.set(a.event,Object.freeze([...c,a]))}return Object.freeze({hooks:Object.freeze(r),plans:o,validations:Object.freeze(n),issues:Object.freeze(i),valid:i.length===0})}p(w,"compileLifecycleHookRegistry");function A(t,n){return process.env.CRTR_TEST_DISABLE_LIFECYCLE_HOOK_DISCOVERY==="1"?w([]):w(P(t,n))}p(A,"discoverLifecycleHookRegistry");function F(t,n=process.cwd(),r){return b(t,P(n,r))}p(F,"discoverHookRegistry");function J(t,n,r,i=process.cwd(),f){return $(t,[{plugin:n,scopeRoot:r}],i,f)}p(J,"discoverCandidateHookRegistry");function $(t,n,r=process.cwd(),i){return b(t,_(n,r,i))}p($,"discoverCandidateHookRegistryForCandidates");function V(t,n){return b(t,v(n))}p(V,"discoverHookRegistryInScopes");export{b as compileHookRegistry,w as compileLifecycleHookRegistry,J as discoverCandidateHookRegistry,$ as discoverCandidateHookRegistryForCandidates,F as discoverHookRegistry,V as discoverHookRegistryInScopes,A as discoverLifecycleHookRegistry,P as effectiveHookPlugins,y as hookDiscoveryScopes,H as hookIdentity};
@@ -1,5 +1,5 @@
1
- import type { EffectiveLeafHelp, LeafHelp } from '../help.js';
1
+ import type { EffectiveLeafHelp } from '../help.js';
2
2
  import type { EffectiveHookPlan } from './discovery.js';
3
3
  /** Build a frozen help view whose Effects order matches the effective pipeline.
4
4
  * Core help is never modified; all non-effects fields retain their references. */
5
- export declare function projectEffectiveLeafHelp(core: LeafHelp, plan?: EffectiveHookPlan): EffectiveLeafHelp;
5
+ export declare function projectEffectiveLeafHelp(core: EffectiveLeafHelp, plan?: EffectiveHookPlan): EffectiveLeafHelp;
@@ -1,4 +1,4 @@
1
1
  import type { NodeCreateHookRequest } from '../../hook-authoring.js';
2
2
  export type NodeCreateRequest = NodeCreateHookRequest['create'];
3
3
  /** Admit one node creation and return the release that must run after its row exists. */
4
- export declare function admitNodeCreate(create: NodeCreateRequest): Promise<() => void>;
4
+ export declare function admitNodeCreate(create: NodeCreateRequest, app: string): Promise<() => void>;
@@ -1 +1 @@
1
- var m=Object.defineProperty;var l=(e,r)=>m(e,"name",{value:r,configurable:!0});import{crtrHome as g}from"../canvas/paths.js";import{nodeCreateRefused as u}from"../errors.js";import{discoverLifecycleHookRegistry as y}from"./discovery.js";import{invokeBlockingLifecycleHooks as w}from"./transport/exec-lifecycle.js";let p=Promise.resolve();async function h(){let e;const r=p;p=new Promise(t=>{e=t}),await r;let o=!1;return()=>{o||(o=!0,e())}}l(h,"enterNodeCreateGate");function v(e,r){const o=y(e,r),t=o.plans.get("node:create")??[],a=o.validations.flatMap(s=>s.lifecycleCandidates.filter(n=>n.event==="node:create"&&!t.some(i=>i.plugin.name===s.plugin.name&&i.declarationIndex===n.index)).map(n=>({validation:s,candidate:n,issue:s.issues.find(i=>i.path===`lifecycle[${n.index}]`||i.path?.startsWith(`lifecycle[${n.index}].`))??s.issues[0]})))[0];if(a===void 0)return o;const{validation:c,candidate:f,issue:d}=a;throw u(`plugin "${c.plugin.name}" lifecycle hook "${f.op}" for node:create could not be discovered: ${d.message}`,`Refused by plugin ${c.plugin.name}, op ${f.op}.`)}l(v,"refusedCreateHookDiscovery");async function R(e){const r=await h();try{const o=v(e.cwd,e.profile),t=await w(o.plans.get("node:create")??[],{create:e,runtime:{canvasHome:g(),profile:e.profile}});if(t!==null)throw u(t.message,t.next);return r}catch(o){throw r(),o}}l(R,"admitNodeCreate");export{R as admitNodeCreate};
1
+ var m=Object.defineProperty;var a=(e,r)=>m(e,"name",{value:r,configurable:!0});import{crtrHome as g}from"../canvas/paths.js";import{nodeCreateRefused as u}from"../errors.js";import{discoverLifecycleHookRegistry as y}from"./discovery.js";import{invokeBlockingLifecycleHooks as w}from"./transport/exec-lifecycle.js";let p=Promise.resolve();async function h(){let e;const r=p;p=new Promise(t=>{e=t}),await r;let o=!1;return()=>{o||(o=!0,e())}}a(h,"enterNodeCreateGate");function v(e,r){const o=y(e,r),t=o.plans.get("node:create")??[],n=o.validations.flatMap(i=>i.lifecycleCandidates.filter(s=>s.event==="node:create"&&!t.some(l=>l.plugin.name===i.plugin.name&&l.declarationIndex===s.index)).map(s=>({validation:i,candidate:s,issue:i.issues.find(l=>l.path===`lifecycle[${s.index}]`||l.path?.startsWith(`lifecycle[${s.index}].`))??i.issues[0]})))[0];if(n===void 0)return o;const{validation:c,candidate:f,issue:d}=n;throw u(`plugin "${c.plugin.name}" lifecycle hook "${f.op}" for node:create could not be discovered: ${d.message}`,`Refused by plugin ${c.plugin.name}, op ${f.op}.`)}a(v,"refusedCreateHookDiscovery");async function R(e,r){const o=await h();try{const t=v(e.cwd,e.profile),n=await w(t.plans.get("node:create")??[],{app:r,create:e,runtime:{canvasHome:g(),profile:e.profile}});if(n!==null)throw u(n.message,n.next);return o}catch(t){throw o(),t}}a(R,"admitNodeCreate");export{R as admitNodeCreate};
@@ -2,6 +2,8 @@ import type { HookPhase } from '../../../hook-authoring.js';
2
2
  import type { Field } from '../../help.js';
3
3
  export declare const EXEC_HOOK_TIMEOUT_MS = 15000;
4
4
  export interface ExecHookSpec {
5
+ /** Identity resolved against the daemon's effective hook plan on Linux. */
6
+ id: string;
5
7
  plugin: string;
6
8
  /** Absolute, validated hookExecutable path. */
7
9
  executable: string;
@@ -1 +1 @@
1
- var R=Object.defineProperty;var l=(e,t)=>R(e,"name",{value:t,configurable:!0});import{spawn as I}from"node:child_process";import{posixProcessGroupSpawnOptions as A,terminateProcessGroup as D}from"../../../hook-process.js";import{ExitCode as N}from"../../../types.js";import{isRecord as k}from"../../../shared/predicates.js";import{validateCoreDeclaredResult as j}from"../../../api/command-manifest/result.js";import{CrtrError as J}from"../../errors.js";import{diag as V}from"../../io.js";const C=10*1024*1024,P=15e3,M=new Set(["internal","unknown_path","command_collision","command_hook_collision","plugin_protocol_error","hook_protocol_error"]),B=/^[a-z][a-z0-9]*(_[a-z0-9]+)*$/,G=/^[0-9a-f]{32}$/,$="Run `crtr pkg plugin show` or `crtr sys doctor` to inspect the plugin.";async function v(e,t){const s=process.cwd(),o=K(e,t,s),r=await H(e,t,JSON.stringify(o),s);if(r.signal!==null)throw n(e,t,`executable was killed by signal ${r.signal}`,"a clean exit with one JSON envelope on stdout");const i=z(e,t,r.stdout);if(i.ok&&r.status!==0?V(`crtr: ${y(e)} returned ok:true but exited ${r.status} (honoring the envelope)`):!i.ok&&r.status===0&&V(`crtr: ${y(e)} returned ok:false but exited 0 (honoring the envelope)`),i.ok||L(e,t,i),e.phase!=="replace")return;const a=i.result;if(!k(a))throw n(e,t,"replacement success result was not an object","result: an object matching the target output declaration");const p=e.output;if(p===void 0)throw n(e,t,"replacement target output declaration was missing","the target leaf output declaration");const d=j(p,a);if(d!==null){const u=p.find(c=>c.name===d.field);throw d.receivedType!==void 0?n(e,t,`replacement output field "${d.field}" has the wrong type`,`${d.field}: ${u?.type??"unknown"}`):n(e,t,`replacement result is missing required output field "${d.field}"`,`a "${d.field}" field of type ${u?.type??"unknown"}`)}return a}l(v,"invokeExecHook");async function H(e,t,s,o){let r;try{r=I(e.executable,["--crtr-hook-protocol","1"],{cwd:o,env:process.env,stdio:["pipe","pipe","inherit"],...A()})}catch(i){throw n(e,t,`executable could not be run (${E(i)})`,"a runnable hook executable")}return new Promise((i,a)=>{let p=0;const d=[];let u,c=!1,g=!1,S=null,_=null,m;const w=l(()=>{if(!(!c||u!==void 0&&!g)){if(m!==void 0&&clearTimeout(m),u?.kind==="timeout"){a(n(e,t,`executable timed out after ${P}ms`,"one JSON envelope before the execution timeout"));return}if(u?.kind==="output_limit"){a(n(e,t,"stdout exceeded the 10 MiB cap","one JSON envelope under 10 MiB on stdout"));return}if(u?.kind==="spawn"){a(n(e,t,`executable could not be run (${E(u.error)})`,"a runnable hook executable"));return}if(u?.kind==="cleanup"){a(n(e,t,`executable cleanup failed (${E(u.error)})`,"a hook executable whose process group can be terminated"));return}i({stdout:Buffer.concat(d).toString("utf8"),status:S,signal:_})}},"finish"),b=l(f=>{u===void 0&&(u=f,m!==void 0&&clearTimeout(m),D(r).then(()=>{g=!0,w()},x=>{u={kind:"cleanup",error:x},g=!0,w()}))},"terminate");r.stdout.on("data",f=>{if(p+=f.byteLength,p>C){b({kind:"output_limit"});return}d.push(f)}),r.once("error",f=>{if(r.pid===void 0){u={kind:"spawn",error:f},c=!0,g=!0,w();return}b({kind:"spawn",error:f})}),r.once("close",(f,x)=>{S=f,_=x,c=!0,w()}),m=setTimeout(()=>b({kind:"timeout"}),P),r.stdin.end(s)})}l(H,"runHookProcess");function K(e,t,s){if(!G.test(t.operationId))throw n(e,t,"operationId was not a 32-character lowercase hexadecimal string","a valid crouter operation identity");if(!h(t.input))throw n(e,t,"input was not JSON-compatible","a JSON object");if(!t.providedParams.every(r=>typeof r=="string"))throw n(e,t,"providedParams contained a non-string value","an array of parameter names");const o={protocolVersion:1,op:e.op,command:[...e.commandPath],operationId:t.operationId,input:t.input,context:{cwd:s,providedParams:[...t.providedParams]}};if(e.phase==="after"){if(t.result===void 0||!h(t.result))throw n(e,t,"after hook result was missing or not JSON-compatible","the completed primary result");return{...o,phase:"after",result:t.result}}if(t.result!==void 0)throw n(e,t,`${e.phase} hook invocation included a result`,"result only for after hooks");return e.phase==="before"?{...o,phase:"before"}:{...o,phase:"replace"}}l(K,"buildRequest");function z(e,t,s){let o;try{o=JSON.parse(s.trim())}catch{throw n(e,t,"stdout was not a single JSON envelope","exactly one JSON envelope on stdout")}if(!k(o))throw n(e,t,"stdout was not a JSON object","a { protocolVersion: 1, ok: boolean, ... } envelope");if(o.protocolVersion!==1)throw n(e,t,`unsupported protocolVersion ${String(o.protocolVersion)}`,"protocolVersion exactly 1");if(o.ok===!0){const i=e.phase==="replace"?["protocolVersion","ok","result"]:["protocolVersion","ok"];if(!O(o,i))throw n(e,t,"success envelope had missing or extra fields",`{ ${i.join(", ")} } only`);if(e.phase==="replace"){if(!h(o.result))throw n(e,t,"replacement result was not JSON-compatible","a JSON result");return{protocolVersion:1,ok:!0,result:o.result}}return{protocolVersion:1,ok:!0}}if(o.ok!==!1||!O(o,["protocolVersion","ok","error"]))throw n(e,t,"failure envelope had missing or extra fields","{ protocolVersion, ok, error } only");const r=o.error;if(!k(r)||!O(r,["code","message"],["field","next"]))throw n(e,t,"error envelope was missing fields or contained extra fields","error: { code, message, field?, next? }");if(typeof r.code!="string"||r.code===""||typeof r.message!="string"||r.message==="")throw n(e,t,"error envelope had an empty or non-string code/message","non-empty error code and message strings");if(r.field!==void 0&&typeof r.field!="string"||r.next!==void 0&&typeof r.next!="string")throw n(e,t,"error envelope had a non-string field/next","string field and next values when present");return{protocolVersion:1,ok:!1,error:{code:r.code,message:r.message,...r.field===void 0?{}:{field:r.field},...r.next===void 0?{}:{next:r.next}}}}l(z,"parseEnvelope");function L(e,t,s){const{code:o,message:r,field:i,next:a}=s.error;throw!B.test(o)||M.has(o)?n(e,t,`error code "${o}" was invalid or reserved`,"a non-reserved lowercase snake_case code"):new J(o,`${y(e)}: ${r}`,N.GENERAL,T(e,t,i,a))}l(L,"throwHookFailure");function n(e,t,s,o){return new J("hook_protocol_error",`${y(e)}: ${s}. Expected ${o}.`,N.GENERAL,T(e,t,void 0,$,s))}l(n,"protocolError");function T(e,t,s,o,r){const i={plugin:e.plugin,op:e.op,phase:e.phase,command:[...e.commandPath],...r===void 0?{}:{received:r},...s===void 0?{}:{field:s}};if(e.phase!=="after")return{...i,next:o??$};const a="Do not retry the original command; its primary action completed. Inspect and reconcile the failed after hook.";return{...i,primaryCompleted:!0,result:t.result,next:o===void 0||o===$?a:`${o} ${a}`}}l(T,"failureDetails");function y(e){return`plugin "${e.plugin}" ${e.phase} hook "${e.op}" for \`${e.commandPath.join(" ")}\``}l(y,"label");function O(e,t,s=[]){const o=Object.keys(e);return t.every(r=>Object.hasOwn(e,r))&&o.every(r=>t.includes(r)||s.includes(r))}l(O,"hasExactKeys");function h(e){return e===null||typeof e=="boolean"||typeof e=="string"?!0:typeof e=="number"?Number.isFinite(e):Array.isArray(e)?e.every(h):k(e)&&Object.values(e).every(h)}l(h,"isJson");function E(e){return e instanceof Error?e.message:String(e)}l(E,"describeError");export{P as EXEC_HOOK_TIMEOUT_MS,v as invokeExecHook};
1
+ var R=Object.defineProperty;var f=(e,t)=>R(e,"name",{value:t,configurable:!0});import{spawn as T}from"node:child_process";import{socketFetch as A}from"../../../api/node-transport.js";import{apiSocketPath as C}from"../../canvas/paths.js";import{posixProcessGroupSpawnOptions as j,terminateProcessGroup as D}from"../../../hook-process.js";import{ExitCode as S}from"../../../types.js";import{isRecord as m}from"../../../shared/predicates.js";import{envExecutionId as G,envNodeId as K}from"../../../shared/env.js";import{validateCoreDeclaredResult as M}from"../../../api/command-manifest/result.js";import{CrtrError as b}from"../../errors.js";import{diag as I}from"../../io.js";const q=10*1024*1024,V=15e3,B=new Set(["internal","unknown_path","command_collision","command_hook_collision","plugin_protocol_error","hook_protocol_error"]),H=/^[a-z][a-z0-9]*(_[a-z0-9]+)*$/,L=/^[0-9a-f]{32}$/,$="Run `crtr pkg plugin show` or `crtr sys doctor` to inspect the plugin.";async function ie(e,t){const u=process.cwd(),o=F(e,t,u),r=await z(e,t,JSON.stringify(o),u);if(r.signal!==null)throw n(e,t,`executable was killed by signal ${r.signal}`,"a clean exit with one JSON envelope on stdout");const s=U(e,t,r.stdout);if(s.ok&&r.status!==0?I(`crtr: ${k(e)} returned ok:true but exited ${r.status} (honoring the envelope)`):!s.ok&&r.status===0&&I(`crtr: ${k(e)} returned ok:false but exited 0 (honoring the envelope)`),s.ok||X(e,t,s),e.phase!=="replace")return;const l=s.result;if(!m(l))throw n(e,t,"replacement success result was not an object","result: an object matching the target output declaration");const h=e.output;if(h===void 0)throw n(e,t,"replacement target output declaration was missing","the target leaf output declaration");const d=M(h,l);if(d!==null){const i=h.find(a=>a.name===d.field);throw d.receivedType!==void 0?n(e,t,`replacement output field "${d.field}" has the wrong type`,`${d.field}: ${i?.type??"unknown"}`):n(e,t,`replacement result is missing required output field "${d.field}"`,`a "${d.field}" field of type ${i?.type??"unknown"}`)}return l}f(ie,"invokeExecHook");async function z(e,t,u,o){if(process.platform==="linux"){const s=K(),l=G(),h=process.env.CRTR_API_SOCKET??C();if(s&&!l)throw n(e,t,"executable requires a current node execution","a current node execution");let d;try{const i=s?`/v1/nodes/${encodeURIComponent(s)}/hooks/exec`:"/v1/hooks/exec";d=await A(h)(`http://localhost${i}`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({...s?{expected_execution_id:l}:{},hook_id:e.id,cwd:o,request:u})});const a=await d.json();if(!d.ok){const c=m(a)&&m(a.error)?a.error:null,g=c&&typeof c.message=="string"?c.message:`daemon refused hook execution (${d.status})`;throw c&&(c.code==="hook_timeout"||c.code==="hook_output_limit")?new b(c.code,`${k(e)}: ${g}`,S.GENERAL,N(e,t,void 0,$,g)):new Error(g)}if(!m(a)||typeof a.stdout!="string"||a.status!==null&&typeof a.status!="number"||a.signal!==null&&typeof a.signal!="string")throw new Error("invalid hook execution response");return{stdout:a.stdout,status:a.status,signal:a.signal}}catch(i){throw i instanceof b?i:n(e,t,`executable could not be run (${E(i)})`,"a registered runnable hook executable")}}let r;try{r=T(e.executable,["--crtr-hook-protocol","1"],{cwd:o,env:process.env,stdio:["pipe","pipe","inherit"],...j()})}catch(s){throw n(e,t,`executable could not be run (${E(s)})`,"a runnable hook executable")}return new Promise((s,l)=>{let h=0;const d=[];let i,a=!1,c=!1,g=null,P=null,w;const x=f(()=>{if(!(!a||i!==void 0&&!c)){if(w!==void 0&&clearTimeout(w),i?.kind==="timeout"){l(n(e,t,`executable timed out after ${V}ms`,"one JSON envelope before the execution timeout"));return}if(i?.kind==="output_limit"){l(n(e,t,"stdout exceeded the 10 MiB cap","one JSON envelope under 10 MiB on stdout"));return}if(i?.kind==="spawn"){l(n(e,t,`executable could not be run (${E(i.error)})`,"a runnable hook executable"));return}if(i?.kind==="cleanup"){l(n(e,t,`executable cleanup failed (${E(i.error)})`,"a hook executable whose process group can be terminated"));return}s({stdout:Buffer.concat(d).toString("utf8"),status:g,signal:P})}},"finish"),_=f(p=>{i===void 0&&(i=p,w!==void 0&&clearTimeout(w),D(r).then(()=>{c=!0,x()},O=>{i={kind:"cleanup",error:O},c=!0,x()}))},"terminate");r.stdout.on("data",p=>{if(h+=p.byteLength,h>q){_({kind:"output_limit"});return}d.push(p)}),r.once("error",p=>{if(r.pid===void 0){i={kind:"spawn",error:p},a=!0,c=!0,x();return}_({kind:"spawn",error:p})}),r.once("close",(p,O)=>{g=p,P=O,a=!0,x()}),w=setTimeout(()=>_({kind:"timeout"}),V),r.stdin.end(u)})}f(z,"runHookProcess");function F(e,t,u){if(!L.test(t.operationId))throw n(e,t,"operationId was not a 32-character lowercase hexadecimal string","a valid crouter operation identity");if(!y(t.input))throw n(e,t,"input was not JSON-compatible","a JSON object");if(!t.providedParams.every(r=>typeof r=="string"))throw n(e,t,"providedParams contained a non-string value","an array of parameter names");const o={protocolVersion:1,op:e.op,command:[...e.commandPath],operationId:t.operationId,input:t.input,context:{cwd:u,providedParams:[...t.providedParams]}};if(e.phase==="after"){if(t.result===void 0||!y(t.result))throw n(e,t,"after hook result was missing or not JSON-compatible","the completed primary result");return{...o,phase:"after",result:t.result}}if(t.result!==void 0)throw n(e,t,`${e.phase} hook invocation included a result`,"result only for after hooks");return e.phase==="before"?{...o,phase:"before"}:{...o,phase:"replace"}}f(F,"buildRequest");function U(e,t,u){let o;try{o=JSON.parse(u.trim())}catch{throw n(e,t,"stdout was not a single JSON envelope","exactly one JSON envelope on stdout")}if(!m(o))throw n(e,t,"stdout was not a JSON object","a { protocolVersion: 1, ok: boolean, ... } envelope");if(o.protocolVersion!==1)throw n(e,t,`unsupported protocolVersion ${String(o.protocolVersion)}`,"protocolVersion exactly 1");if(o.ok===!0){const s=e.phase==="replace"?["protocolVersion","ok","result"]:["protocolVersion","ok"];if(!J(o,s))throw n(e,t,"success envelope had missing or extra fields",`{ ${s.join(", ")} } only`);if(e.phase==="replace"){if(!y(o.result))throw n(e,t,"replacement result was not JSON-compatible","a JSON result");return{protocolVersion:1,ok:!0,result:o.result}}return{protocolVersion:1,ok:!0}}if(o.ok!==!1||!J(o,["protocolVersion","ok","error"]))throw n(e,t,"failure envelope had missing or extra fields","{ protocolVersion, ok, error } only");const r=o.error;if(!m(r)||!J(r,["code","message"],["field","next"]))throw n(e,t,"error envelope was missing fields or contained extra fields","error: { code, message, field?, next? }");if(typeof r.code!="string"||r.code===""||typeof r.message!="string"||r.message==="")throw n(e,t,"error envelope had an empty or non-string code/message","non-empty error code and message strings");if(r.field!==void 0&&typeof r.field!="string"||r.next!==void 0&&typeof r.next!="string")throw n(e,t,"error envelope had a non-string field/next","string field and next values when present");return{protocolVersion:1,ok:!1,error:{code:r.code,message:r.message,...r.field===void 0?{}:{field:r.field},...r.next===void 0?{}:{next:r.next}}}}f(U,"parseEnvelope");function X(e,t,u){const{code:o,message:r,field:s,next:l}=u.error;throw!H.test(o)||B.has(o)?n(e,t,`error code "${o}" was invalid or reserved`,"a non-reserved lowercase snake_case code"):new b(o,`${k(e)}: ${r}`,S.GENERAL,N(e,t,s,l))}f(X,"throwHookFailure");function n(e,t,u,o){return new b("hook_protocol_error",`${k(e)}: ${u}. Expected ${o}.`,S.GENERAL,N(e,t,void 0,$,u))}f(n,"protocolError");function N(e,t,u,o,r){const s={plugin:e.plugin,op:e.op,phase:e.phase,command:[...e.commandPath],...r===void 0?{}:{received:r},...u===void 0?{}:{field:u}};if(e.phase!=="after")return{...s,next:o??$};const l="Do not retry the original command; its primary action completed. Inspect and reconcile the failed after hook.";return{...s,primaryCompleted:!0,result:t.result,next:o===void 0||o===$?l:`${o} ${l}`}}f(N,"failureDetails");function k(e){return`plugin "${e.plugin}" ${e.phase} hook "${e.op}" for \`${e.commandPath.join(" ")}\``}f(k,"label");function J(e,t,u=[]){const o=Object.keys(e);return t.every(r=>Object.hasOwn(e,r))&&o.every(r=>t.includes(r)||u.includes(r))}f(J,"hasExactKeys");function y(e){return e===null||typeof e=="boolean"||typeof e=="string"?!0:typeof e=="number"?Number.isFinite(e):Array.isArray(e)?e.every(y):m(e)&&Object.values(e).every(y)}f(y,"isJson");function E(e){return e instanceof Error?e.message:String(e)}f(E,"describeError");export{V as EXEC_HOOK_TIMEOUT_MS,ie as invokeExecHook};
@@ -5,6 +5,7 @@ export interface NodeLifecycleHookInvocation {
5
5
  runtime: LifecycleHookRequest['runtime'];
6
6
  }
7
7
  export interface NodeCreateHookInvocation {
8
+ app: string;
8
9
  create: NodeCreateHookRequest['create'];
9
10
  runtime: NodeCreateHookRequest['runtime'];
10
11
  }