@north-light/cli 0.3.529 → 0.3.531

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 (509) hide show
  1. package/dist/api/dto/lifecycle.d.ts +3 -1
  2. package/dist/api/dto/messages.d.ts +5 -3
  3. package/dist/builtin-memory/crouter-plugin/bundles-and-memory.md +1 -1
  4. package/dist/builtin-memory/crouter-plugin/commands.md +1 -1
  5. package/dist/clients/attach/session/connection.js +1 -1
  6. package/dist/clients/attach/session/reconnect.js +1 -1
  7. package/dist/clients/attach/viewer.js +508 -508
  8. package/dist/commands/node/message.js +1 -1
  9. package/dist/commands/sys/join.js +1 -1
  10. package/dist/core/async-array.d.ts +7 -0
  11. package/dist/core/async-array.js +1 -0
  12. package/dist/core/audit.d.ts +1 -1
  13. package/dist/core/audit.js +2 -2
  14. package/dist/core/canvas/attention.d.ts +4 -4
  15. package/dist/core/canvas/attention.js +1 -1
  16. package/dist/core/canvas/boot.d.ts +4 -4
  17. package/dist/core/canvas/boot.js +1 -1
  18. package/dist/core/canvas/canvas.d.ts +59 -59
  19. package/dist/core/canvas/canvas.js +19 -19
  20. package/dist/core/canvas/context-strip.js +2 -2
  21. package/dist/core/canvas/crons.d.ts +27 -27
  22. package/dist/core/canvas/crons.js +11 -11
  23. package/dist/core/canvas/daemon-actions.d.ts +10 -10
  24. package/dist/core/canvas/daemon-actions.js +8 -8
  25. package/dist/core/canvas/daemon-owner.d.ts +3 -3
  26. package/dist/core/canvas/daemon-owner.js +2 -2
  27. package/dist/core/canvas/db.d.ts +19 -30
  28. package/dist/core/canvas/db.js +3 -2
  29. package/dist/core/canvas/deliveries.d.ts +16 -16
  30. package/dist/core/canvas/deliveries.js +24 -24
  31. package/dist/core/canvas/executions.d.ts +8 -8
  32. package/dist/core/canvas/executions.js +1 -1
  33. package/dist/core/canvas/focuses.d.ts +8 -8
  34. package/dist/core/canvas/focuses.js +1 -1
  35. package/dist/core/canvas/history.d.ts +3 -3
  36. package/dist/core/canvas/history.js +9 -9
  37. package/dist/core/canvas/install-id.d.ts +1 -1
  38. package/dist/core/canvas/install-id.js +1 -1
  39. package/dist/core/canvas/managed-worktree-sweep-candidates.d.ts +1 -1
  40. package/dist/core/canvas/managed-worktree-sweep-candidates.js +2 -2
  41. package/dist/core/canvas/memory-reads.d.ts +6 -6
  42. package/dist/core/canvas/memory-reads.js +1 -1
  43. package/dist/core/canvas/nav-model.d.ts +13 -13
  44. package/dist/core/canvas/nav-model.js +1 -1
  45. package/dist/core/canvas/node-agent-paths.d.ts +6 -6
  46. package/dist/core/canvas/node-agent-paths.js +1 -1
  47. package/dist/core/canvas/node-tokens.d.ts +7 -7
  48. package/dist/core/canvas/node-tokens.js +3 -3
  49. package/dist/core/canvas/outcome-actions.d.ts +5 -5
  50. package/dist/core/canvas/outcome-actions.js +3 -3
  51. package/dist/core/canvas/recovery.d.ts +26 -26
  52. package/dist/core/canvas/recovery.js +2 -2
  53. package/dist/core/canvas/render-source.d.ts +1 -1
  54. package/dist/core/canvas/render-source.js +1 -1
  55. package/dist/core/canvas/sessions.d.ts +10 -10
  56. package/dist/core/canvas/sessions.js +4 -4
  57. package/dist/core/canvas/source.js +1 -1
  58. package/dist/core/canvas/structured-requests.d.ts +15 -15
  59. package/dist/core/canvas/structured-requests.js +5 -5
  60. package/dist/core/canvas/tree.d.ts +9 -9
  61. package/dist/core/canvas/tree.js +5 -5
  62. package/dist/core/canvas/waits.d.ts +13 -13
  63. package/dist/core/canvas/waits.js +6 -6
  64. package/dist/core/canvas/worktrees.d.ts +15 -15
  65. package/dist/core/canvas/worktrees.js +1 -1
  66. package/dist/core/command-hooks/lifecycle-catalog.d.ts +4 -4
  67. package/dist/core/command-hooks/lifecycle-catalog.js +1 -1
  68. package/dist/core/command-hooks/transport/exec-lifecycle.js +1 -1
  69. package/dist/core/command-plugins/bundle.d.ts +1 -1
  70. package/dist/core/command-plugins/bundle.js +1 -1
  71. package/dist/core/conversation-store/file-store.d.ts +7 -7
  72. package/dist/core/conversation-store/file-store.js +9 -9
  73. package/dist/core/conversation-store/index.d.ts +16 -14
  74. package/dist/core/conversation-store/index.js +1 -1
  75. package/dist/core/conversation-store/listener.js +5 -5
  76. package/dist/core/conversation-store/patch.d.ts +3 -1
  77. package/dist/core/conversation-store/patch.js +1 -1
  78. package/dist/core/directory/join.d.ts +1 -1
  79. package/dist/core/feed/feed.js +3 -3
  80. package/dist/core/feed/inbox.d.ts +2 -2
  81. package/dist/core/feed/inbox.js +1 -1
  82. package/dist/core/feed/messages.d.ts +11 -12
  83. package/dist/core/feed/messages.js +5 -5
  84. package/dist/core/feed/reports.d.ts +4 -4
  85. package/dist/core/feed/reports.js +2 -2
  86. package/dist/core/grants/cover.d.ts +1 -1
  87. package/dist/core/grants/cover.js +1 -1
  88. package/dist/core/grants/local.d.ts +1 -1
  89. package/dist/core/grants/local.js +1 -1
  90. package/dist/core/grants/mirror.d.ts +19 -19
  91. package/dist/core/grants/mirror.js +2 -2
  92. package/dist/core/grants/on-sync.d.ts +1 -1
  93. package/dist/core/grants/on-sync.js +1 -1
  94. package/dist/core/grants/remove.js +1 -1
  95. package/dist/core/grants/sync.js +1 -1
  96. package/dist/core/graph/access.d.ts +17 -17
  97. package/dist/core/graph/access.js +3 -3
  98. package/dist/core/graph/custom.d.ts +16 -16
  99. package/dist/core/graph/custom.js +9 -9
  100. package/dist/core/graph/deletion.d.ts +3 -7
  101. package/dist/core/graph/deletion.js +4 -4
  102. package/dist/core/graph/documents.d.ts +24 -27
  103. package/dist/core/graph/documents.js +7 -7
  104. package/dist/core/graph/edges.d.ts +13 -13
  105. package/dist/core/graph/edges.js +1 -1
  106. package/dist/core/graph/events.d.ts +7 -9
  107. package/dist/core/graph/events.js +8 -8
  108. package/dist/core/graph/exposures.d.ts +6 -6
  109. package/dist/core/graph/exposures.js +4 -4
  110. package/dist/core/graph/jobs.d.ts +6 -8
  111. package/dist/core/graph/jobs.js +2 -2
  112. package/dist/core/graph/kinds/action.js +1 -1
  113. package/dist/core/graph/kinds/custom.js +2 -2
  114. package/dist/core/graph/kinds/document.d.ts +1 -0
  115. package/dist/core/graph/kinds/document.js +4 -4
  116. package/dist/core/graph/kinds/dto.d.ts +2 -2
  117. package/dist/core/graph/kinds/dto.js +1 -1
  118. package/dist/core/graph/kinds/job.js +2 -2
  119. package/dist/core/graph/kinds/kind.d.ts +6 -8
  120. package/dist/core/graph/kinds/kind.js +1 -1
  121. package/dist/core/graph/kinds/node.js +5 -5
  122. package/dist/core/graph/kinds/owner.js +2 -2
  123. package/dist/core/graph/kinds/registry.d.ts +6 -9
  124. package/dist/core/graph/kinds/registry.js +1 -1
  125. package/dist/core/graph/names.d.ts +6 -6
  126. package/dist/core/graph/names.js +3 -3
  127. package/dist/core/graph/object-waits.d.ts +4 -7
  128. package/dist/core/graph/object-waits.js +1 -1
  129. package/dist/core/graph/objects.d.ts +14 -14
  130. package/dist/core/graph/objects.js +9 -9
  131. package/dist/core/graph/package-docs.d.ts +2 -7
  132. package/dist/core/graph/package-docs.js +5 -5
  133. package/dist/core/graph/package-kinds.d.ts +2 -5
  134. package/dist/core/graph/package-kinds.js +1 -1
  135. package/dist/core/graph/package-reconcile.d.ts +2 -5
  136. package/dist/core/graph/package-reconcile.js +1 -1
  137. package/dist/core/graph/reader.d.ts +18 -18
  138. package/dist/core/graph/reader.js +3 -3
  139. package/dist/core/graph/receivers.d.ts +4 -4
  140. package/dist/core/graph/receivers.js +5 -5
  141. package/dist/core/graph/repo-sync/exchange.d.ts +3 -7
  142. package/dist/core/graph/repo-sync/exchange.js +2 -2
  143. package/dist/core/graph/repo-sync/repos.d.ts +7 -5
  144. package/dist/core/graph/repo-sync/repos.js +3 -3
  145. package/dist/core/graph/repo-sync/sync.d.ts +3 -6
  146. package/dist/core/graph/repo-sync/sync.js +2 -2
  147. package/dist/core/graph/rules.d.ts +5 -5
  148. package/dist/core/graph/rules.js +3 -3
  149. package/dist/core/graph/spaces/app.js +1 -1
  150. package/dist/core/graph/spaces/index.d.ts +4 -5
  151. package/dist/core/graph/spaces/index.js +1 -1
  152. package/dist/core/graph/spaces/own-memory.d.ts +4 -4
  153. package/dist/core/graph/spaces/own-memory.js +1 -1
  154. package/dist/core/graph/spaces/person.js +3 -3
  155. package/dist/core/graph/spaces/repo.d.ts +1 -1
  156. package/dist/core/graph/spaces/repo.js +1 -1
  157. package/dist/core/graph/watches.d.ts +15 -15
  158. package/dist/core/graph/watches.js +10 -10
  159. package/dist/core/human/feedback-companion.d.ts +2 -2
  160. package/dist/core/human/feedback-companion.js +1 -1
  161. package/dist/core/human/feedback.d.ts +3 -3
  162. package/dist/core/human/feedback.js +1 -1
  163. package/dist/core/human/requests.d.ts +34 -33
  164. package/dist/core/human/requests.js +20 -20
  165. package/dist/core/human/scan.d.ts +2 -2
  166. package/dist/core/human/scan.js +1 -1
  167. package/dist/core/human/tickets.d.ts +9 -9
  168. package/dist/core/human/tickets.js +1 -1
  169. package/dist/core/llm/app-rungs.d.ts +1 -1
  170. package/dist/core/llm/app-rungs.js +1 -1
  171. package/dist/core/llm/run.js +1 -1
  172. package/dist/core/peer/directory.d.ts +1 -1
  173. package/dist/core/peer/directory.js +1 -1
  174. package/dist/core/peer/envelope.d.ts +3 -3
  175. package/dist/core/peer/envelope.js +1 -1
  176. package/dist/core/peer/home.d.ts +7 -7
  177. package/dist/core/peer/home.js +2 -2
  178. package/dist/core/peer/ingest.d.ts +6 -6
  179. package/dist/core/peer/ingest.js +1 -1
  180. package/dist/core/peer/outbox-store.d.ts +14 -14
  181. package/dist/core/peer/outbox-store.js +5 -5
  182. package/dist/core/peer/receiver.d.ts +2 -2
  183. package/dist/core/peer/receiver.js +1 -1
  184. package/dist/core/peer/stubs.d.ts +10 -10
  185. package/dist/core/peer/stubs.js +1 -1
  186. package/dist/core/providers/approval.d.ts +2 -2
  187. package/dist/core/providers/approval.js +2 -2
  188. package/dist/core/providers/audit.d.ts +3 -3
  189. package/dist/core/providers/audit.js +2 -2
  190. package/dist/core/providers/bundles.js +2 -2
  191. package/dist/core/providers/call.d.ts +2 -2
  192. package/dist/core/providers/call.js +1 -1
  193. package/dist/core/providers/files.d.ts +1 -1
  194. package/dist/core/providers/files.js +1 -1
  195. package/dist/core/providers/mint.js +1 -1
  196. package/dist/core/providers/receipts.d.ts +1 -1
  197. package/dist/core/providers/receipts.js +2 -2
  198. package/dist/core/review/birth.js +1 -1
  199. package/dist/core/review/comments.d.ts +19 -19
  200. package/dist/core/review/comments.js +5 -5
  201. package/dist/core/review/companion.d.ts +1 -1
  202. package/dist/core/review/companion.js +1 -1
  203. package/dist/core/review/document.d.ts +3 -3
  204. package/dist/core/review/document.js +2 -2
  205. package/dist/core/review/fork.js +2 -2
  206. package/dist/core/review/realize.js +1 -1
  207. package/dist/core/review/remap.d.ts +2 -2
  208. package/dist/core/review/remap.js +4 -4
  209. package/dist/core/review/stage.d.ts +1 -1
  210. package/dist/core/review/stage.js +1 -1
  211. package/dist/core/review/store.d.ts +21 -21
  212. package/dist/core/review/store.js +1 -1
  213. package/dist/core/runs/activity.d.ts +1 -1
  214. package/dist/core/runs/activity.js +5 -5
  215. package/dist/core/runs/confinement.d.ts +7 -7
  216. package/dist/core/runs/confinement.js +2 -2
  217. package/dist/core/runs/events.d.ts +12 -12
  218. package/dist/core/runs/events.js +4 -4
  219. package/dist/core/runs/operations.d.ts +11 -11
  220. package/dist/core/runs/operations.js +5 -5
  221. package/dist/core/runs/questions.d.ts +10 -10
  222. package/dist/core/runs/questions.js +3 -3
  223. package/dist/core/runtime/auth-reload.js +1 -1
  224. package/dist/core/runtime/bearings.d.ts +5 -5
  225. package/dist/core/runtime/bearings.js +6 -6
  226. package/dist/core/runtime/broker-inventory.js +1 -1
  227. package/dist/core/runtime/broker-request.js +1 -1
  228. package/dist/core/runtime/broker.js +1 -1
  229. package/dist/core/runtime/close.d.ts +3 -3
  230. package/dist/core/runtime/close.js +1 -1
  231. package/dist/core/runtime/deliver-live.js +1 -1
  232. package/dist/core/runtime/fleet.d.ts +2 -2
  233. package/dist/core/runtime/host.d.ts +3 -3
  234. package/dist/core/runtime/host.js +3 -3
  235. package/dist/core/runtime/kickoff.d.ts +12 -12
  236. package/dist/core/runtime/kickoff.js +17 -17
  237. package/dist/core/runtime/launch-target.d.ts +1 -1
  238. package/dist/core/runtime/launch-target.js +1 -1
  239. package/dist/core/runtime/ledger.d.ts +3 -3
  240. package/dist/core/runtime/ledger.js +3 -3
  241. package/dist/core/runtime/lifecycle.d.ts +1 -1
  242. package/dist/core/runtime/lifecycle.js +2 -2
  243. package/dist/core/runtime/memory-admission.js +1 -1
  244. package/dist/core/runtime/model-swap.d.ts +2 -2
  245. package/dist/core/runtime/model-swap.js +1 -1
  246. package/dist/core/runtime/node-read.d.ts +1 -1
  247. package/dist/core/runtime/node-read.js +2 -2
  248. package/dist/core/runtime/nodes.d.ts +6 -6
  249. package/dist/core/runtime/nodes.js +1 -1
  250. package/dist/core/runtime/outcome-document.d.ts +1 -1
  251. package/dist/core/runtime/outcome-document.js +1 -1
  252. package/dist/core/runtime/persona.d.ts +3 -3
  253. package/dist/core/runtime/persona.js +2 -2
  254. package/dist/core/runtime/placement.d.ts +11 -11
  255. package/dist/core/runtime/placement.js +1 -1
  256. package/dist/core/runtime/promote.d.ts +3 -3
  257. package/dist/core/runtime/promote.js +1 -1
  258. package/dist/core/runtime/recycle.js +1 -1
  259. package/dist/core/runtime/reopen.d.ts +21 -10
  260. package/dist/core/runtime/reopen.js +1 -1
  261. package/dist/core/runtime/reset.d.ts +4 -4
  262. package/dist/core/runtime/reset.js +1 -1
  263. package/dist/core/runtime/revive-all.d.ts +2 -2
  264. package/dist/core/runtime/revive-all.js +1 -1
  265. package/dist/core/runtime/revive.d.ts +4 -4
  266. package/dist/core/runtime/revive.js +2 -2
  267. package/dist/core/runtime/roadmap.d.ts +6 -6
  268. package/dist/core/runtime/roadmap.js +5 -5
  269. package/dist/core/runtime/session-branch.d.ts +1 -1
  270. package/dist/core/runtime/session-branch.js +1 -1
  271. package/dist/core/runtime/session-list-cache.js +1 -1
  272. package/dist/core/runtime/situational-live.js +1 -1
  273. package/dist/core/runtime/spawn.d.ts +2 -2
  274. package/dist/core/runtime/spawn.js +2 -2
  275. package/dist/core/runtime/stop-guard.d.ts +2 -2
  276. package/dist/core/runtime/stop-guard.js +3 -3
  277. package/dist/core/runtime/warm-pool.d.ts +2 -2
  278. package/dist/core/runtime/warm-pool.js +1 -1
  279. package/dist/core/spaces/mounts.d.ts +2 -2
  280. package/dist/core/spaces/mounts.js +1 -1
  281. package/dist/core/spaces/permissions.d.ts +1 -1
  282. package/dist/core/spaces/permissions.js +1 -1
  283. package/dist/core/spaces/process.d.ts +1 -1
  284. package/dist/core/spaces/process.js +1 -1
  285. package/dist/core/spaces/space.js +1 -1
  286. package/dist/core/spaces/stop.d.ts +3 -3
  287. package/dist/core/spaces/stop.js +2 -2
  288. package/dist/core/spaces/users.d.ts +6 -6
  289. package/dist/core/spaces/users.js +1 -1
  290. package/dist/core/storage/attachments.d.ts +2 -2
  291. package/dist/core/storage/attachments.js +1 -1
  292. package/dist/core/storage/shares.d.ts +2 -2
  293. package/dist/core/storage/shares.js +1 -1
  294. package/dist/core/storage/tables.d.ts +21 -21
  295. package/dist/core/storage/tables.js +3 -3
  296. package/dist/core/substrate/delivery/corpus.d.ts +5 -8
  297. package/dist/core/substrate/delivery/corpus.js +3 -3
  298. package/dist/core/substrate/delivery/deliver.d.ts +10 -15
  299. package/dist/core/substrate/delivery/deliver.js +3 -3
  300. package/dist/core/substrate/delivery/plan.d.ts +2 -12
  301. package/dist/core/substrate/delivery/plan.js +3 -3
  302. package/dist/core/substrate/delivery/render-boot.d.ts +4 -4
  303. package/dist/core/substrate/delivery/render-boot.js +18 -18
  304. package/dist/core/substrate/delivery/render-event.d.ts +7 -14
  305. package/dist/core/substrate/delivery/render-event.js +4 -4
  306. package/dist/core/substrate/subject.d.ts +2 -2
  307. package/dist/core/substrate/subject.js +1 -1
  308. package/dist/core/usage/ledger.d.ts +6 -6
  309. package/dist/core/usage/ledger.js +4 -4
  310. package/dist/core/worktree-close.js +4 -4
  311. package/dist/core/worktree-mutation-async.js +7 -7
  312. package/dist/core/worktree-quarantine.js +1 -1
  313. package/dist/core/worktree-sweep.d.ts +1 -1
  314. package/dist/core/worktree-sweep.js +6 -6
  315. package/dist/core/worktree.d.ts +5 -5
  316. package/dist/core/worktree.js +13 -13
  317. package/dist/daemon/analytics/compute.d.ts +2 -2
  318. package/dist/daemon/analytics/compute.js +1 -1
  319. package/dist/daemon/api/app-listener.d.ts +4 -4
  320. package/dist/daemon/api/app-listener.js +13 -13
  321. package/dist/daemon/api/bridge.js +5 -5
  322. package/dist/daemon/api/document-listener.js +6 -6
  323. package/dist/daemon/api/handlers/analytics.js +1 -1
  324. package/dist/daemon/api/handlers/attach.js +1 -1
  325. package/dist/daemon/api/handlers/bash-jobs.js +1 -1
  326. package/dist/daemon/api/handlers/bash.js +1 -1
  327. package/dist/daemon/api/handlers/broker-ops.d.ts +1 -1
  328. package/dist/daemon/api/handlers/broker-ops.js +1 -1
  329. package/dist/daemon/api/handlers/broker-recovery.d.ts +1 -1
  330. package/dist/daemon/api/handlers/broker-recovery.js +1 -1
  331. package/dist/daemon/api/handlers/broker-signals.d.ts +2 -2
  332. package/dist/daemon/api/handlers/broker-signals.js +2 -2
  333. package/dist/daemon/api/handlers/canvas.d.ts +1 -1
  334. package/dist/daemon/api/handlers/canvas.js +4 -4
  335. package/dist/daemon/api/handlers/chat-inventory.js +1 -1
  336. package/dist/daemon/api/handlers/crons.js +1 -1
  337. package/dist/daemon/api/handlers/custom-objects.d.ts +4 -4
  338. package/dist/daemon/api/handlers/custom-objects.js +3 -3
  339. package/dist/daemon/api/handlers/delivery-retry.js +1 -1
  340. package/dist/daemon/api/handlers/delivery.js +1 -1
  341. package/dist/daemon/api/handlers/docs.d.ts +4 -4
  342. package/dist/daemon/api/handlers/docs.js +1 -1
  343. package/dist/daemon/api/handlers/feedback-comments.js +3 -3
  344. package/dist/daemon/api/handlers/files.js +1 -1
  345. package/dist/daemon/api/handlers/focus.js +1 -1
  346. package/dist/daemon/api/handlers/health.js +3 -3
  347. package/dist/daemon/api/handlers/hook-exec.js +1 -1
  348. package/dist/daemon/api/handlers/human-requests.js +1 -1
  349. package/dist/daemon/api/handlers/inbox-page.d.ts +1 -1
  350. package/dist/daemon/api/handlers/inbox-page.js +1 -1
  351. package/dist/daemon/api/handlers/inbox.d.ts +1 -1
  352. package/dist/daemon/api/handlers/inbox.js +1 -1
  353. package/dist/daemon/api/handlers/llm.d.ts +1 -1
  354. package/dist/daemon/api/handlers/llm.js +3 -3
  355. package/dist/daemon/api/handlers/memory-reads.js +1 -1
  356. package/dist/daemon/api/handlers/memory.d.ts +5 -5
  357. package/dist/daemon/api/handlers/memory.js +5 -5
  358. package/dist/daemon/api/handlers/messages.js +2 -2
  359. package/dist/daemon/api/handlers/node-events.d.ts +2 -2
  360. package/dist/daemon/api/handlers/node-events.js +3 -3
  361. package/dist/daemon/api/handlers/node-outcomes.js +1 -1
  362. package/dist/daemon/api/handlers/node-records.js +2 -2
  363. package/dist/daemon/api/handlers/nodes.d.ts +1 -1
  364. package/dist/daemon/api/handlers/nodes.js +1 -1
  365. package/dist/daemon/api/handlers/objects.js +3 -3
  366. package/dist/daemon/api/handlers/package-docs.js +1 -1
  367. package/dist/daemon/api/handlers/plugin-app-token.d.ts +1 -1
  368. package/dist/daemon/api/handlers/plugin-app-token.js +1 -1
  369. package/dist/daemon/api/handlers/profiles.d.ts +3 -3
  370. package/dist/daemon/api/handlers/profiles.js +1 -1
  371. package/dist/daemon/api/handlers/providers.d.ts +1 -1
  372. package/dist/daemon/api/handlers/providers.js +1 -1
  373. package/dist/daemon/api/handlers/questions.js +1 -1
  374. package/dist/daemon/api/handlers/reports.d.ts +1 -1
  375. package/dist/daemon/api/handlers/reports.js +5 -5
  376. package/dist/daemon/api/handlers/review-comments.js +1 -1
  377. package/dist/daemon/api/handlers/reviews.js +1 -1
  378. package/dist/daemon/api/handlers/runs.js +1 -1
  379. package/dist/daemon/api/handlers/structured-requests.js +1 -1
  380. package/dist/daemon/api/handlers/subscriptions.js +1 -1
  381. package/dist/daemon/api/handlers/transfer.js +1 -1
  382. package/dist/daemon/api/map.d.ts +3 -3
  383. package/dist/daemon/api/map.js +1 -1
  384. package/dist/daemon/api/principal.d.ts +1 -1
  385. package/dist/daemon/api/principal.js +1 -1
  386. package/dist/daemon/api/reader.d.ts +5 -5
  387. package/dist/daemon/api/reader.js +1 -1
  388. package/dist/daemon/api/router.d.ts +5 -5
  389. package/dist/daemon/api/router.js +1 -1
  390. package/dist/daemon/api/server.js +1 -1
  391. package/dist/daemon/broker-signals/bus.d.ts +1 -1
  392. package/dist/daemon/broker-signals/bus.js +1 -1
  393. package/dist/daemon/companion-retire.js +1 -1
  394. package/dist/daemon/cron/armed-context.d.ts +2 -2
  395. package/dist/daemon/cron/armed-context.js +1 -1
  396. package/dist/daemon/cron/authority.d.ts +2 -2
  397. package/dist/daemon/cron/authority.js +1 -1
  398. package/dist/daemon/cron/disposition.js +1 -1
  399. package/dist/daemon/cron/ended.d.ts +1 -1
  400. package/dist/daemon/cron/ended.js +2 -2
  401. package/dist/daemon/cron/escalation.js +3 -3
  402. package/dist/daemon/cron/folders.d.ts +1 -1
  403. package/dist/daemon/cron/folders.js +1 -1
  404. package/dist/daemon/cron/held.d.ts +1 -1
  405. package/dist/daemon/cron/held.js +1 -1
  406. package/dist/daemon/cron/lease-recovery.d.ts +1 -1
  407. package/dist/daemon/cron/lease-recovery.js +1 -1
  408. package/dist/daemon/cron/passes.d.ts +2 -2
  409. package/dist/daemon/cron/passes.js +1 -1
  410. package/dist/daemon/cron/run-socket.d.ts +1 -1
  411. package/dist/daemon/cron/run-socket.js +1 -1
  412. package/dist/daemon/cron/settle.js +1 -1
  413. package/dist/daemon/cron/sinks.d.ts +1 -1
  414. package/dist/daemon/cron/sinks.js +2 -2
  415. package/dist/daemon/cron-run.d.ts +12 -3
  416. package/dist/daemon/cron-run.js +2 -2
  417. package/dist/daemon/crtrd.js +6 -6
  418. package/dist/daemon/delivery/run-delivery.js +1 -1
  419. package/dist/daemon/due-sources.d.ts +3 -3
  420. package/dist/daemon/due-sources.js +1 -1
  421. package/dist/daemon/due.d.ts +3 -3
  422. package/dist/daemon/due.js +7 -7
  423. package/dist/daemon/fleet.d.ts +2 -2
  424. package/dist/daemon/fleet.js +11 -11
  425. package/dist/daemon/human/finish.js +3 -3
  426. package/dist/daemon/human/settle.d.ts +1 -1
  427. package/dist/daemon/human/settle.js +1 -1
  428. package/dist/daemon/human/sweep.js +1 -1
  429. package/dist/daemon/joined-owner.d.ts +3 -3
  430. package/dist/daemon/joined-owner.js +1 -1
  431. package/dist/daemon/messaging/node-message.js +1 -1
  432. package/dist/daemon/park-activity.d.ts +2 -2
  433. package/dist/daemon/park-activity.js +1 -1
  434. package/dist/daemon/peer/authority.js +1 -1
  435. package/dist/daemon/peer/forward.d.ts +6 -6
  436. package/dist/daemon/peer/forward.js +1 -1
  437. package/dist/daemon/peer/handlers.js +1 -1
  438. package/dist/daemon/peer/ingress.d.ts +4 -4
  439. package/dist/daemon/peer/ingress.js +1 -1
  440. package/dist/daemon/peer/outbox.d.ts +2 -2
  441. package/dist/daemon/peer/outbox.js +1 -1
  442. package/dist/daemon/peer/relay-service.js +1 -1
  443. package/dist/daemon/plugin-objects/read-leaf.d.ts +2 -2
  444. package/dist/daemon/plugin-objects/read-leaf.js +2 -2
  445. package/dist/daemon/profile-delete.js +1 -1
  446. package/dist/daemon/readiness.d.ts +2 -2
  447. package/dist/daemon/readiness.js +1 -1
  448. package/dist/daemon/reconcilers/action-lane.d.ts +1 -1
  449. package/dist/daemon/reconcilers/action-lane.js +1 -1
  450. package/dist/daemon/reconcilers/bash-deadline.js +2 -2
  451. package/dist/daemon/reconcilers/broker-supervision.d.ts +1 -1
  452. package/dist/daemon/reconcilers/broker-supervision.js +4 -4
  453. package/dist/daemon/reconcilers/controller-death.d.ts +1 -1
  454. package/dist/daemon/reconcilers/controller-death.js +1 -1
  455. package/dist/daemon/reconcilers/cron-lane.d.ts +1 -1
  456. package/dist/daemon/reconcilers/cron-lane.js +1 -1
  457. package/dist/daemon/reconcilers/delivery-lane.d.ts +1 -1
  458. package/dist/daemon/reconcilers/delivery-lane.js +2 -2
  459. package/dist/daemon/reconcilers/fault-retry-backstop.d.ts +3 -3
  460. package/dist/daemon/reconcilers/fault-retry-backstop.js +1 -1
  461. package/dist/daemon/reconcilers/grove-instance-sweep.d.ts +2 -2
  462. package/dist/daemon/reconcilers/grove-instance-sweep.js +1 -1
  463. package/dist/daemon/reconcilers/live-obligation.d.ts +6 -6
  464. package/dist/daemon/reconcilers/live-obligation.js +1 -1
  465. package/dist/daemon/reconcilers/managed-worktree-sweep.js +1 -1
  466. package/dist/daemon/reconcilers/node-deadline.d.ts +1 -1
  467. package/dist/daemon/reconcilers/node-deadline.js +1 -1
  468. package/dist/daemon/reconcilers/node-lifecycle/freeze-lane.js +1 -1
  469. package/dist/daemon/reconcilers/node-lifecycle/respawn-policy.d.ts +3 -3
  470. package/dist/daemon/reconcilers/node-lifecycle/respawn-policy.js +1 -1
  471. package/dist/daemon/reconcilers/node-lifecycle/terminating.js +1 -1
  472. package/dist/daemon/reconcilers/node-lifecycle/tick.js +1 -1
  473. package/dist/daemon/reconcilers/node-lifecycle/wants-execution.d.ts +1 -1
  474. package/dist/daemon/reconcilers/node-lifecycle/wants-execution.js +1 -1
  475. package/dist/daemon/reconcilers/pending-review-submit.d.ts +1 -1
  476. package/dist/daemon/reconcilers/pending-review-submit.js +1 -1
  477. package/dist/daemon/reconcilers/storage-due-work.js +1 -1
  478. package/dist/daemon/reconcilers/storage-maintenance.d.ts +1 -1
  479. package/dist/daemon/reconcilers/storage-maintenance.js +2 -2
  480. package/dist/daemon/reconcilers/structured-request-lane.d.ts +1 -1
  481. package/dist/daemon/reconcilers/structured-request-lane.js +1 -1
  482. package/dist/daemon/review/comment-notify.js +2 -2
  483. package/dist/daemon/review/companion.d.ts +3 -3
  484. package/dist/daemon/review/companion.js +1 -1
  485. package/dist/daemon/review/finish.js +1 -1
  486. package/dist/daemon/review/sweep.js +1 -1
  487. package/dist/daemon/run-notices.d.ts +4 -4
  488. package/dist/daemon/run-notices.js +1 -1
  489. package/dist/daemon/runs/append-section.d.ts +2 -2
  490. package/dist/daemon/runs/append-section.js +2 -2
  491. package/dist/daemon/runs/observer.d.ts +2 -2
  492. package/dist/daemon/runs/observer.js +2 -2
  493. package/dist/daemon/structured-requests/boot.d.ts +1 -1
  494. package/dist/daemon/structured-requests/boot.js +1 -1
  495. package/dist/daemon/structured-requests/effects.js +1 -1
  496. package/dist/daemon/structured-requests/sidecar.d.ts +1 -1
  497. package/dist/daemon/structured-requests/sidecar.js +1 -1
  498. package/dist/launcher/run.js +1 -1
  499. package/dist/migrations/004-canvas-documents/apply.d.ts +3 -3
  500. package/dist/migrations/004-canvas-documents/apply.js +1 -1
  501. package/dist/migrations/004-canvas-documents/index.d.ts +2 -2
  502. package/dist/migrations/004-canvas-documents/index.js +2 -2
  503. package/dist/migrations/activation.js +2 -2
  504. package/docs/plugin/bundles-and-memory.md +1 -1
  505. package/docs/plugin/commands.md +1 -1
  506. package/docs/public-api.md +11 -0
  507. package/package.json +4 -3
  508. package/packages/crouter-identity/package.json +1 -1
  509. package/runtime.lock.json +12 -12
@@ -85,10 +85,10 @@ export interface FleetRegistry {
85
85
  * Removes the entry (freeing the capacity slot), then enqueues its
86
86
  * observation on the daemon's serial work lane — it never runs inline on
87
87
  * the Node event callback (design D-3). */
88
- onChildExit(nodeId: string, status: FleetExitStatus, executionId?: string): void;
88
+ onChildExit(nodeId: string, status: FleetExitStatus, executionId?: string): Promise<void>;
89
89
  /** Test seam — delivers a synthetic exit through the SAME path as
90
90
  * onChildExit, so fabricated-row tests drive policy without a process. */
91
- deliverExit(nodeId: string, status: FleetExitStatus): void;
91
+ deliverExit(nodeId: string, status: FleetExitStatus): Promise<void>;
92
92
  /** The node-lifecycle tick's enactment entry: classify a row known to have no
93
93
  * live engine and enact through the SAME policy table exit events use, so
94
94
  * tick recovery and exit recovery can never diverge. */
@@ -39,18 +39,18 @@ export interface Host {
39
39
  /** Is this node's engine alive? PURE / non-mutating. `string | NodeRow` so
40
40
  * both call sites — the revive guard (passes the id) and the daemon (passes a
41
41
  * row) — share one selector. For the broker this IS isPidAlive(pi_pid). */
42
- isAlive(node: string | NodeRow): boolean;
42
+ isAlive(node: string | NodeRow): Promise<boolean>;
43
43
  /** Tear the engine down (close/cancel teardown). Resolves only after the
44
44
  * fixed process snapshot is confirmed dead, or with a diagnostic failure. */
45
45
  teardown(nodeId: string, opts?: TeardownOptions): Promise<TeardownResult>;
46
46
  /** Deliver an OS signal to the engine container — present so the daemon never
47
47
  * reaches around the abstraction. */
48
- signal(nodeId: string, sig: NodeJS.Signals): void;
48
+ signal(nodeId: string, sig: NodeJS.Signals): Promise<void>;
49
49
  }
50
50
  /** Validate the broker launch recipe before we detach a child process. This is
51
51
  * the fast-fail seam for known module/path errors: a bad engine resolve or a
52
52
  * missing plain session path throws here, before spawn(). */
53
- export declare function preflightBrokerLaunch(nodeId: string, inv: PiInvocation, cwd: string): void;
53
+ export declare function preflightBrokerLaunch(nodeId: string, inv: PiInvocation, cwd: string): Promise<void>;
54
54
  /** Queue broker teardown after the close response settles. Completion includes
55
55
  * any post-teardown work, which lets the daemon drain it during shutdown. */
56
56
  export declare function requestBrokerTeardown(nodeId: string, opts?: TeardownOptions, after?: () => Promise<void>): Promise<TeardownResult>;
@@ -1,3 +1,3 @@
1
- var ye=Object.defineProperty;var u=(e,t)=>ye(e,"name",{value:t,configurable:!0});import{assertGranteeRunsHere as Pe}from"./unsandboxed.js";import{spawn as Re}from"node:child_process";import{mkdirSync as ue,existsSync as j,unlinkSync as fe,openSync as F,closeSync as N,writeSync as xe,chmodSync as Oe,lstatSync as Te}from"node:fs";import{ensureAppSpace as De}from"../spaces/space.js";import{sandboxCacheEnv as Ne}from"../spaces/cache-env.js";import{compileLaunch as Ce,launchStillGranted as Ae}from"../spaces/mounts.js";import{grantsGeneration as de}from"../grants/mirror.js";import{LAUNCHER_SOCKET as z}from"../../launcher/spec.js";import{launcherRequest as M}from"../../launcher/client.js";import{piAgentDir as Le}from"./package-health.js";import{existsBeneath as V,readFileBeneath as Be,readTextBeneathIfExists as $e,setModeBeneath as P,withDirBeneath as X,writeFileBeneath as G}from"../spaces/open-beneath.js";import{dirname as Q,join as h,resolve as je,isAbsolute as Fe}from"node:path";import{fileURLToPath as me}from"node:url";import{connectViewSocket as Me}from"./view-socket.js";import{appSpace as K}from"../layout.js";import{readConfig as Ge,readMergedLaunchConfig as Ke}from"../config.js";import{readRotationConfig as He}from"../subscription-state.js";import{getNode as v}from"../canvas/index.js";import{scopesFilePath as Y,crtrHome as pe,nodeRunDir as Z,nodeRunJobDir as Je,jobDir as qe,viewSocketPath as Ue,nodeAgentDir as We,contextDir as ze,nodeHome as Ve}from"../canvas/paths.js";import{encodeFrame as Xe}from"./broker-protocol.js";import{buildBrokerEnv as Qe}from"./spawn-env.js";import{hostExecPathFresh as Ye}from"./branded-host.js";import{isPidAlive as I,killProcessTreePids as he,isAnyPidAlive as Ze,captureTeardownSnapshot as Ie}from"../canvas/pid.js";import{assertMandatoryCanvasExtensions as er}from"./canvas-extensions.js";import{appMemoryFull as rr,appMemoryTooSmall as tr,boundFleet as nr,brokerCapReached as or,brokerThresholdsForDaemon as ir}from"./fleet.js";import{admitBrokerMemory as sr}from"./memory-admission.js";import{emitEvent as g}from"../events/emit.js";import{bindBrokerEventSource as ar,eventSource as cr}from"../events/source.js";import{envBrokerEngine as lr}from"../../shared/env.js";import{conversationIdFromPath as ur,conversationStore as fr,ConversationNotFoundError as we,storeAddress as dr}from"../conversation-store/index.js";import{takeNodeToken as mr}from"../canvas/node-tokens.js";function H(){const e=Q(me(import.meta.url));return h(e,"broker-cli.js")}u(H,"resolveBrokerEntry");const pr="@earendil-works/pi-coding-agent";function hr(e,t){const n=h(Le(),"models.json"),r=h(t,"models.json"),o=$e(Q(n),n);if(o===null)return;const f=JSON.parse(o),a=u(i=>Array.isArray(i)?i.map(a):i===null||typeof i!="object"?i:Object.fromEntries(Object.entries(i).filter(([s])=>!/^(apiKey|authorization|headers|token|secret)$/i.test(s)).map(([s,_])=>[s,a(_)])),"scrub"),l=`${JSON.stringify(a(f),null,2)}
2
- `;if(n===r&&o!==l){if(JSON.stringify(f)!==JSON.stringify(a(f)))throw new Error("terminal models.json contains credentials; move them into daemon secrets");P(e,r,432);return}G(e,r,l,{atomic:!0,mode:432}),P(e,r,432)}u(hr,"writeBrokerModels");function ge(e){return e.env.CRTR_BROKER_ENGINE??lr()}u(ge,"resolveEngineSpec");function Ee(e){return e.includes("/")||e.endsWith(".jsonl")}u(Ee,"isPlainLaunchSessionPath");function wr(e,t){return Fe(e)?e:je(t,e)}u(wr,"resolvePlainLaunchPath");function gr(e,t,n,r){if(n==="--session"&&!Ee(r))throw new Error(`[broker] refusing to launch ${e}: launch recipe passes bare --session id '${r}' \u2014 the broker fatally rejects bare ids; pass the .jsonl path instead.`);if(!Ee(r))return;const o=wr(r,t),f=ur(o);try{if(f===null)throw new we(o);fr().header(f)}catch(a){if(!(a instanceof we))throw a;const l=n==="--session"?"session file":"fork source";throw new Error(`[broker] refusing to launch ${e}: launch recipe references missing ${l} '${r}' (${o})`)}}u(gr,"preflightLaunchSessionArg");function Er(e,t,n){const r=Z(e);ue(r,{recursive:!0}),process.platform==="linux"&&j(z)&&Te(r).uid===process.getuid()&&Oe(r,504);const o=h(r,"broker-launch.json"),f={user:Ge("user"),launch:Ke(n,t.env.CRTR_PROFILE_ID||null),rotation:He()};G(r,o,JSON.stringify({...t,configSnapshot:f}),{atomic:!0}),t.env.CRTR_SCOPES_FILE!==void 0&&G(r,Y(e),JSON.stringify(v(e)?.scopes??[]),{atomic:!0});const a=Be(r,o).toString("utf8"),l=JSON.parse(a);if(!Array.isArray(l.argv))throw new Error(`[broker] refusing to launch ${e}: broker-launch.json is missing the argv array`);const i=ge(t);try{const d=import.meta.resolve(i);if(d.startsWith("file:")&&!j(me(d)))throw new Error(`resolved to missing file ${d}`)}catch(d){throw new Error(`[broker] refusing to launch ${e}: cannot resolve broker engine '${i}' from ${H()} \u2014 ${d.message}`)}const s=l.argv,_=[];for(let d=0;d<s.length;d++){const R=s[d];if(R==="-e"){const C=s[++d];C!==void 0&&_.push(C);continue}if(R!=="--session"&&R!=="--fork")continue;const O=s[++d];O!==void 0&&gr(e,n,R,O)}try{er(_)}catch(d){throw new Error(`[broker] refusing to launch ${e}: ${d.message}`)}}u(Er,"preflightBrokerLaunch");const kr=2e3,vr=2e3,_r=150;async function J(e,t){const n=Date.now()+t;for(;Ze(e);){const r=n-Date.now();if(r<=0)return!1;await new Promise(o=>setTimeout(o,Math.min(_r,r)))}return!0}u(J,"waitForTreeExit");async function Sr(e,t,n){return e.length===0?{confirmed:!0}:n&&await J(e,kr)?{confirmed:!0}:(he(e,"SIGTERM",t),await J(e,vr)?{confirmed:!0}:(he(e,"SIGKILL",t),await J(e,5e3)?{confirmed:!0}:{confirmed:!1,error:new Error(`broker process tree for ${e.join(", ")} remained alive after SIGKILL`)}))}u(Sr,"terminateBrokerTree");function ke(e,t){const n=v(e),r=n?.pi_pid,o=r!=null?Ie(r,n?.pi_pid_identity??null,t.excludePid):null;return o?.reused===!0&&g({level:"warn",event:"broker.teardown.pid_reuse_refused",node_id:e,fields:{recorded_pid:r,expected_identity:n?.pi_pid_identity??null}}),{tree:o?.tree??[],identities:o?.identities??null,nodeId:e,launcherPid:j(z)&&o?.tree.includes(r)?r:null}}u(ke,"prepareBrokerTeardown");async function ve(e){if(e.launcherPid!==null){try{await M({operation:"stop",pid:e.launcherPid})}catch(t){return I(e.launcherPid)?{confirmed:!1,error:t instanceof Error?t:new Error(String(t))}:{confirmed:!0}}return await J([e.launcherPid],5e3)?{confirmed:!0}:{confirmed:!1,error:new Error(`launcher pid ${e.launcherPid} remained alive`)}}return new Promise(t=>{let n=!1,r=!1;const o=u(i=>{r||(r=!0,t(i))},"settle"),f=u(()=>{try{fe(Ue(e.nodeId))}catch{}},"cleanupSocket"),a=u(i=>{Sr(e.tree,e.identities,i).then(o,s=>o({confirmed:!1,error:s instanceof Error?s:new Error(String(s))}))},"finish"),l=Me(e.nodeId);l.once("error",()=>{n||(f(),a(!1))}),l.once("connect",()=>{n=!0;try{l.write(Xe({type:"shutdown"}))}catch{}l.end(),f(),a(!0)})})}u(ve,"runPreparedBrokerTeardown");const q=new Map;function rt(e,t={},n){const r=q.get(e);if(r!==void 0)return n!==void 0&&r.after.push(n),r.completion;let o;const f=new Promise(i=>{o=i}),a={completion:f,resolve:o,after:n===void 0?[]:[n]};q.set(e,a);let l;try{l=ke(e,t)}catch(i){const s={confirmed:!1,error:i instanceof Error?i:new Error(String(i))};return q.delete(e),g({level:"error",event:"broker.teardown.unconfirmed",node_id:e,error:s.error}),a.resolve(s),f}return setImmediate(()=>{q.delete(e),ve(l).then(async i=>{if(i.confirmed)for(const s of a.after)try{await s()}catch(_){g({level:"error",event:"broker.teardown.after_failed",node_id:e,error:_})}else g({level:"error",event:"broker.teardown.unconfirmed",node_id:e,error:i.error});a.resolve(i)},i=>{const s={confirmed:!1,error:i instanceof Error?i:new Error(String(i))};g({level:"error",event:"broker.teardown.unconfirmed",node_id:e,error:s.error}),a.resolve(s)})}),f}u(rt,"requestBrokerTeardown");function _e(){return process.platform==="linux"&&j(z)}u(_e,"isolatedBrokerLauncherAvailable");const tt={async launch(e,t,n){if(Pe(v(e)?.grantee),v(e)?.isolated===!0&&!_e())throw new Error("isolated broker requires the Linux root launcher");Er(e,t,n.cwd);const r=nr();if(!r.reserveSlot(e))throw or(ir().automaticReviveCap,r.size());let o=null,f,a=!1;try{const l=qe(e);ue(l,{recursive:!0}),o=F(h(l,"broker.log"),"a");const i=ge(t),s={...Qe(t),CRTR_BROKER_ENGINE:i,CRTR_STORE_ADDRESS:dr()};if(i!==pr){const c=t.env.NODE_OPTIONS??process.env.NODE_OPTIONS;c!==void 0&&(s.NODE_OPTIONS=c)}cr()===void 0&&ar(e);const _=v(e)?.run_id;if(_){const c=v(_);if(!c||c.deleting_at)throw new Error("run is deleting")}const d=t.env.CRTR_EXECUTION_ID;if(!d)throw new Error("broker launch has no execution id");const R=mr(d),O=_e();if(v(e)?.isolated===!0&&!O)throw new Error("isolated broker requires the Linux root launcher");if(process.platform==="linux"&&process.env.CRTR_LAUNCHER_SOCKET&&!O)throw new Error("root launcher socket is unavailable; refusing an unsandboxed broker");if(O){const c=v(e);if(!c)throw new Error(`missing node ${e}`);const p=c.grantee??"app:terminal",x=await sr(e,{useMemo:!1});if(x.verdict==="denied")throw rr(x);if(x.verdict==="too_small")throw tr(x);const S=await De(p);Object.assign(s,Ne(p));const b={uid:process.getuid(),gid:S.gid},w=Z(e);for(const[m,E]of[[K(p).nodes,We(e,p)],[K(p).nodes,ze(e,p)],[w,Je(e)]])X(m,E,()=>{},!0),P(m,E,1528,b);P(w,h(w,"broker-launch.json"),416,b),V(w,Y(e))&&P(w,Y(e),416,b);const te=h(w,"system-prompt.md");V(w,te)&&P(w,te,432,b);for(const m of["output-schema.json","situational-context.md"]){const E=h(w,m);V(w,E)&&P(w,E,432,b)}const ne=c.isolated===!0,y=Ve(e,p,ne);ne&&(X(K(p).nodes,y,()=>{},!0),P(K(p).nodes,y,1528,b),s.HOME=y,s.PI_CODING_AGENT_DIR=h(y,".pi","agent"));const W=h(y,".pi","agent");X(y,W,()=>{},!0),hr(y,W);const oe=h(W,"settings.json"),Se=h(Q(H()),"../../builtin-pi-packages/pi-crtr-extensions");G(y,oe,`${JSON.stringify({packages:[Se]})}
3
- `,{atomic:!0,mode:432}),P(y,oe,432);const ie=h(Z(e),`token-${d}`),L=F(ie,"wx+",384);fe(ie),xe(L,R);const se=[F(`/proc/self/fd/${L}`,"r"),F(`/proc/self/fd/${L}`,"r")];N(L);const ae={nodeId:e,app:p,sub:c.sub??"user:local",grantId:c.grant_id??null,scopes:c.scopes??null,isolated:c.isolated===!0,...c.isolated===!0?{cwd:c.cwd}:{},command:[process.execPath,H(),"--canvas-home",pe(),"--epoch",r.epoch(),e],env:Object.fromEntries(Object.entries({...s,...c.isolated===!0?{PWD:c.cwd}:{}}).filter(m=>m[1]!==void 0)),auditMissing:u(m=>g({level:"warn",event:"broker.mount.missing",node_id:e,fields:{source:m}}),"auditMissing")};try{let m;for(const D of se){const B=de(),k=Ce(ae);k.broker=!0;const $=await M({operation:"launch",spec:k},[D]);if(!("pid"in $))throw new Error("launcher did not return a pid");if(de()===B||Ae(ae,k)){m=$.pid;break}g({level:"info",event:"broker.launch.regranted",node_id:e,fields:{pid:$.pid}}),await M({operation:"stop",pid:$.pid,signal:"SIGKILL"}).catch(()=>{})}if(m===void 0)throw new Error("grant changed during every launch attempt");const E=m,be=Date.now(),ce=new Promise(D=>{const B=setInterval(()=>{I(E)||(clearInterval(B),M({operation:"exit.status",pid:E}).then(k=>"oomKilled"in k&&k.oomKilled,()=>!1).then(k=>{g({level:k?"warn":"info",event:"broker.exited",node_id:e,fields:{pid:E,uptime_ms:Date.now()-be,oom_killed:k}}),D({code:null,signal:null,...k?{oomKilled:!0}:{}})}))},250);B.unref()});N(o),o=null;const le={pid:E,exited:ce};return r.register(e,le),a=!0,ce.then(D=>r.onChildExit(e,D,d)),le}finally{for(const m of se)N(m)}}const C=await Ye(),T=Re(C,[H(),"--canvas-home",pe(),"--epoch",r.epoch(),e],{cwd:n.cwd,detached:!0,stdio:["ignore",o,o,"pipe"],env:s});f=T;const A=T.stdio[3];if(!A||!("end"in A))throw new Error("broker token pipe did not open");A.on("error",c=>g({event:"broker.token_pipe.failed",level:"error",node_id:e,error:c})),A.end(R),N(o),o=null;const ee=Date.now(),re=new Promise(c=>{let p=!1;const x=u(S=>{p||(p=!0,c(S))},"finish");T.once("exit",(S,b)=>{g({level:S===0?"info":"warn",event:"broker.exited",node_id:e,fields:{code:S,signal:b,uptime_ms:Date.now()-ee}}),x({code:S,signal:b})}),T.once("error",S=>{g({level:"error",event:"broker.launch.failed",node_id:e,error:S,fields:{uptime_ms:Date.now()-ee}}),x({code:null,signal:null})})});T.unref();const U={pid:T.pid??null,exited:re};return U.pid!==null&&(r.register(e,U),a=!0,re.then(c=>r.onChildExit(e,c,d))),U}catch(l){if(!a&&f?.pid!=null)try{f.kill("SIGTERM")}catch{}throw l}finally{a||r.releaseReservation(e),o!==null&&N(o)}},isAlive(e){return I((typeof e=="string"?v(e):e)?.pi_pid)},teardown(e,t={}){try{return ve(ke(e,t))}catch(n){return Promise.resolve({confirmed:!1,error:n instanceof Error?n:new Error(String(n))})}},signal(e,t){const n=v(e)?.pi_pid;if(n!=null)try{process.kill(n,t)}catch{}}};export{tt as headlessBrokerHost,_e as isolatedBrokerLauncherAvailable,Er as preflightBrokerLaunch,rt as requestBrokerTeardown};
1
+ var be=Object.defineProperty;var u=(e,t)=>be(e,"name",{value:t,configurable:!0});import{assertGranteeRunsHere as Pe}from"./unsandboxed.js";import{spawn as Re}from"node:child_process";import{mkdirSync as ue,existsSync as j,unlinkSync as fe,openSync as F,closeSync as N,writeSync as xe,chmodSync as Oe,lstatSync as Te}from"node:fs";import{ensureAppSpace as De}from"../spaces/space.js";import{sandboxCacheEnv as Ne}from"../spaces/cache-env.js";import{compileLaunch as Ce,launchStillGranted as Ae}from"../spaces/mounts.js";import{grantsGeneration as de}from"../grants/mirror.js";import{LAUNCHER_SOCKET as z}from"../../launcher/spec.js";import{launcherRequest as M}from"../../launcher/client.js";import{piAgentDir as Le}from"./package-health.js";import{existsBeneath as V,readFileBeneath as Be,readTextBeneathIfExists as $e,setModeBeneath as P,withDirBeneath as X,writeFileBeneath as G}from"../spaces/open-beneath.js";import{dirname as Q,join as h,resolve as je,isAbsolute as Fe}from"node:path";import{fileURLToPath as me}from"node:url";import{connectViewSocket as Me}from"./view-socket.js";import{appSpace as K}from"../layout.js";import{readConfig as Ge,readMergedLaunchConfig as Ke}from"../config.js";import{readRotationConfig as He}from"../subscription-state.js";import{getNode as v}from"../canvas/index.js";import{scopesFilePath as Y,crtrHome as pe,nodeRunDir as Z,nodeRunJobDir as Je,jobDir as qe,viewSocketPath as Ue,nodeAgentDir as We,contextDir as ze,nodeHome as Ve}from"../canvas/paths.js";import{encodeFrame as Xe}from"./broker-protocol.js";import{buildBrokerEnv as Qe}from"./spawn-env.js";import{hostExecPathFresh as Ye}from"./branded-host.js";import{isPidAlive as I,killProcessTreePids as he,isAnyPidAlive as Ze,captureTeardownSnapshot as Ie}from"../canvas/pid.js";import{assertMandatoryCanvasExtensions as er}from"./canvas-extensions.js";import{appMemoryFull as rr,appMemoryTooSmall as tr,boundFleet as nr,brokerCapReached as or,brokerThresholdsForDaemon as ir}from"./fleet.js";import{admitBrokerMemory as sr}from"./memory-admission.js";import{emitEvent as g}from"../events/emit.js";import{bindBrokerEventSource as ar,eventSource as cr}from"../events/source.js";import{envBrokerEngine as lr}from"../../shared/env.js";import{conversationIdFromPath as ur,conversationStore as fr,ConversationNotFoundError as we,storeAddress as dr}from"../conversation-store/index.js";import{takeNodeToken as mr}from"../canvas/node-tokens.js";function H(){const e=Q(me(import.meta.url));return h(e,"broker-cli.js")}u(H,"resolveBrokerEntry");const pr="@earendil-works/pi-coding-agent";function hr(e,t){const n=h(Le(),"models.json"),r=h(t,"models.json"),o=$e(Q(n),n);if(o===null)return;const f=JSON.parse(o),a=u(i=>Array.isArray(i)?i.map(a):i===null||typeof i!="object"?i:Object.fromEntries(Object.entries(i).filter(([s])=>!/^(apiKey|authorization|headers|token|secret)$/i.test(s)).map(([s,_])=>[s,a(_)])),"scrub"),l=`${JSON.stringify(a(f),null,2)}
2
+ `;if(n===r&&o!==l){if(JSON.stringify(f)!==JSON.stringify(a(f)))throw new Error("terminal models.json contains credentials; move them into daemon secrets");P(e,r,432);return}G(e,r,l,{atomic:!0,mode:432}),P(e,r,432)}u(hr,"writeBrokerModels");function ge(e){return e.env.CRTR_BROKER_ENGINE??lr()}u(ge,"resolveEngineSpec");function Ee(e){return e.includes("/")||e.endsWith(".jsonl")}u(Ee,"isPlainLaunchSessionPath");function wr(e,t){return Fe(e)?e:je(t,e)}u(wr,"resolvePlainLaunchPath");async function gr(e,t,n,r){if(n==="--session"&&!Ee(r))throw new Error(`[broker] refusing to launch ${e}: launch recipe passes bare --session id '${r}' \u2014 the broker fatally rejects bare ids; pass the .jsonl path instead.`);if(!Ee(r))return;const o=wr(r,t),f=ur(o);try{if(f===null)throw new we(o);await fr().header(f)}catch(a){if(!(a instanceof we))throw a;const l=n==="--session"?"session file":"fork source";throw new Error(`[broker] refusing to launch ${e}: launch recipe references missing ${l} '${r}' (${o})`)}}u(gr,"preflightLaunchSessionArg");async function Er(e,t,n){const r=Z(e);ue(r,{recursive:!0}),process.platform==="linux"&&j(z)&&Te(r).uid===process.getuid()&&Oe(r,504);const o=h(r,"broker-launch.json"),f={user:Ge("user"),launch:Ke(n,t.env.CRTR_PROFILE_ID||null),rotation:He()};G(r,o,JSON.stringify({...t,configSnapshot:f}),{atomic:!0}),t.env.CRTR_SCOPES_FILE!==void 0&&G(r,Y(e),JSON.stringify((await v(e))?.scopes??[]),{atomic:!0});const a=Be(r,o).toString("utf8"),l=JSON.parse(a);if(!Array.isArray(l.argv))throw new Error(`[broker] refusing to launch ${e}: broker-launch.json is missing the argv array`);const i=ge(t);try{const d=import.meta.resolve(i);if(d.startsWith("file:")&&!j(me(d)))throw new Error(`resolved to missing file ${d}`)}catch(d){throw new Error(`[broker] refusing to launch ${e}: cannot resolve broker engine '${i}' from ${H()} \u2014 ${d.message}`)}const s=l.argv,_=[];for(let d=0;d<s.length;d++){const R=s[d];if(R==="-e"){const C=s[++d];C!==void 0&&_.push(C);continue}if(R!=="--session"&&R!=="--fork")continue;const O=s[++d];O!==void 0&&await gr(e,n,R,O)}try{er(_)}catch(d){throw new Error(`[broker] refusing to launch ${e}: ${d.message}`)}}u(Er,"preflightBrokerLaunch");const kr=2e3,vr=2e3,_r=150;async function J(e,t){const n=Date.now()+t;for(;Ze(e);){const r=n-Date.now();if(r<=0)return!1;await new Promise(o=>setTimeout(o,Math.min(_r,r)))}return!0}u(J,"waitForTreeExit");async function yr(e,t,n){return e.length===0?{confirmed:!0}:n&&await J(e,kr)?{confirmed:!0}:(he(e,"SIGTERM",t),await J(e,vr)?{confirmed:!0}:(he(e,"SIGKILL",t),await J(e,5e3)?{confirmed:!0}:{confirmed:!1,error:new Error(`broker process tree for ${e.join(", ")} remained alive after SIGKILL`)}))}u(yr,"terminateBrokerTree");async function ke(e,t){const n=await v(e),r=n?.pi_pid,o=r!=null?Ie(r,n?.pi_pid_identity??null,t.excludePid):null;return o?.reused===!0&&g({level:"warn",event:"broker.teardown.pid_reuse_refused",node_id:e,fields:{recorded_pid:r,expected_identity:n?.pi_pid_identity??null}}),{tree:o?.tree??[],identities:o?.identities??null,nodeId:e,launcherPid:j(z)&&o?.tree.includes(r)?r:null}}u(ke,"prepareBrokerTeardown");async function ve(e){if(e.launcherPid!==null){try{await M({operation:"stop",pid:e.launcherPid})}catch(t){return I(e.launcherPid)?{confirmed:!1,error:t instanceof Error?t:new Error(String(t))}:{confirmed:!0}}return await J([e.launcherPid],5e3)?{confirmed:!0}:{confirmed:!1,error:new Error(`launcher pid ${e.launcherPid} remained alive`)}}return new Promise(t=>{let n=!1,r=!1;const o=u(i=>{r||(r=!0,t(i))},"settle"),f=u(()=>{try{fe(Ue(e.nodeId))}catch{}},"cleanupSocket"),a=u(i=>{yr(e.tree,e.identities,i).then(o,s=>o({confirmed:!1,error:s instanceof Error?s:new Error(String(s))}))},"finish"),l=Me(e.nodeId);l.once("error",()=>{n||(f(),a(!1))}),l.once("connect",()=>{n=!0;try{l.write(Xe({type:"shutdown"}))}catch{}l.end(),f(),a(!0)})})}u(ve,"runPreparedBrokerTeardown");const q=new Map;async function rt(e,t={},n){const r=q.get(e);if(r!==void 0)return n!==void 0&&r.after.push(n),r.completion;let o;const f=new Promise(i=>{o=i}),a={completion:f,resolve:o,after:n===void 0?[]:[n]};q.set(e,a);let l;try{l=await ke(e,t)}catch(i){const s={confirmed:!1,error:i instanceof Error?i:new Error(String(i))};return q.delete(e),g({level:"error",event:"broker.teardown.unconfirmed",node_id:e,error:s.error}),a.resolve(s),f}return setImmediate(()=>{q.delete(e),ve(l).then(async i=>{if(i.confirmed)for(const s of a.after)try{await s()}catch(_){g({level:"error",event:"broker.teardown.after_failed",node_id:e,error:_})}else g({level:"error",event:"broker.teardown.unconfirmed",node_id:e,error:i.error});a.resolve(i)},i=>{const s={confirmed:!1,error:i instanceof Error?i:new Error(String(i))};g({level:"error",event:"broker.teardown.unconfirmed",node_id:e,error:s.error}),a.resolve(s)})}),f}u(rt,"requestBrokerTeardown");function _e(){return process.platform==="linux"&&j(z)}u(_e,"isolatedBrokerLauncherAvailable");const tt={async launch(e,t,n){if(Pe((await v(e))?.grantee),(await v(e))?.isolated===!0&&!_e())throw new Error("isolated broker requires the Linux root launcher");await Er(e,t,n.cwd);const r=nr();if(!r.reserveSlot(e))throw or(ir().automaticReviveCap,r.size());let o=null,f,a=!1;try{const l=qe(e);ue(l,{recursive:!0}),o=F(h(l,"broker.log"),"a");const i=ge(t),s={...Qe(t),CRTR_BROKER_ENGINE:i,CRTR_STORE_ADDRESS:dr()};if(i!==pr){const c=t.env.NODE_OPTIONS??process.env.NODE_OPTIONS;c!==void 0&&(s.NODE_OPTIONS=c)}cr()===void 0&&ar(e);const _=(await v(e))?.run_id;if(_){const c=await v(_);if(!c||c.deleting_at)throw new Error("run is deleting")}const d=t.env.CRTR_EXECUTION_ID;if(!d)throw new Error("broker launch has no execution id");const R=mr(d),O=_e();if((await v(e))?.isolated===!0&&!O)throw new Error("isolated broker requires the Linux root launcher");if(process.platform==="linux"&&process.env.CRTR_LAUNCHER_SOCKET&&!O)throw new Error("root launcher socket is unavailable; refusing an unsandboxed broker");if(O){const c=await v(e);if(!c)throw new Error(`missing node ${e}`);const p=c.grantee??"app:terminal",x=await sr(e,{useMemo:!1});if(x.verdict==="denied")throw rr(x);if(x.verdict==="too_small")throw tr(x);const y=await De(p);Object.assign(s,Ne(p));const S={uid:process.getuid(),gid:y.gid},w=Z(e);for(const[m,E]of[[K(p).nodes,We(e,p)],[K(p).nodes,ze(e,p)],[w,Je(e)]])X(m,E,()=>{},!0),P(m,E,1528,S);P(w,h(w,"broker-launch.json"),416,S),V(w,Y(e))&&P(w,Y(e),416,S);const te=h(w,"system-prompt.md");V(w,te)&&P(w,te,432,S);for(const m of["output-schema.json","situational-context.md"]){const E=h(w,m);V(w,E)&&P(w,E,432,S)}const ne=c.isolated===!0,b=Ve(e,p,ne);ne&&(X(K(p).nodes,b,()=>{},!0),P(K(p).nodes,b,1528,S),s.HOME=b,s.PI_CODING_AGENT_DIR=h(b,".pi","agent"));const W=h(b,".pi","agent");X(b,W,()=>{},!0),hr(b,W);const oe=h(W,"settings.json"),ye=h(Q(H()),"../../builtin-pi-packages/pi-crtr-extensions");G(b,oe,`${JSON.stringify({packages:[ye]})}
3
+ `,{atomic:!0,mode:432}),P(b,oe,432);const ie=h(Z(e),`token-${d}`),L=F(ie,"wx+",384);fe(ie),xe(L,R);const se=[F(`/proc/self/fd/${L}`,"r"),F(`/proc/self/fd/${L}`,"r")];N(L);const ae={nodeId:e,app:p,sub:c.sub??"user:local",grantId:c.grant_id??null,scopes:c.scopes??null,isolated:c.isolated===!0,...c.isolated===!0?{cwd:c.cwd}:{},command:[process.execPath,H(),"--canvas-home",pe(),"--epoch",r.epoch(),e],env:Object.fromEntries(Object.entries({...s,...c.isolated===!0?{PWD:c.cwd}:{}}).filter(m=>m[1]!==void 0)),auditMissing:u(m=>g({level:"warn",event:"broker.mount.missing",node_id:e,fields:{source:m}}),"auditMissing")};try{let m;for(const D of se){const B=await de(),k=await Ce(ae);k.broker=!0;const $=await M({operation:"launch",spec:k},[D]);if(!("pid"in $))throw new Error("launcher did not return a pid");if(await de()===B||await Ae(ae,k)){m=$.pid;break}g({level:"info",event:"broker.launch.regranted",node_id:e,fields:{pid:$.pid}}),await M({operation:"stop",pid:$.pid,signal:"SIGKILL"}).catch(()=>{})}if(m===void 0)throw new Error("grant changed during every launch attempt");const E=m,Se=Date.now(),ce=new Promise(D=>{const B=setInterval(()=>{I(E)||(clearInterval(B),M({operation:"exit.status",pid:E}).then(k=>"oomKilled"in k&&k.oomKilled,()=>!1).then(k=>{g({level:k?"warn":"info",event:"broker.exited",node_id:e,fields:{pid:E,uptime_ms:Date.now()-Se,oom_killed:k}}),D({code:null,signal:null,...k?{oomKilled:!0}:{}})}))},250);B.unref()});N(o),o=null;const le={pid:E,exited:ce};return r.register(e,le),a=!0,ce.then(async D=>await r.onChildExit(e,D,d)),le}finally{for(const m of se)N(m)}}const C=await Ye(),T=Re(C,[H(),"--canvas-home",pe(),"--epoch",r.epoch(),e],{cwd:n.cwd,detached:!0,stdio:["ignore",o,o,"pipe"],env:s});f=T;const A=T.stdio[3];if(!A||!("end"in A))throw new Error("broker token pipe did not open");A.on("error",c=>g({event:"broker.token_pipe.failed",level:"error",node_id:e,error:c})),A.end(R),N(o),o=null;const ee=Date.now(),re=new Promise(c=>{let p=!1;const x=u(y=>{p||(p=!0,c(y))},"finish");T.once("exit",(y,S)=>{g({level:y===0?"info":"warn",event:"broker.exited",node_id:e,fields:{code:y,signal:S,uptime_ms:Date.now()-ee}}),x({code:y,signal:S})}),T.once("error",y=>{g({level:"error",event:"broker.launch.failed",node_id:e,error:y,fields:{uptime_ms:Date.now()-ee}}),x({code:null,signal:null})})});T.unref();const U={pid:T.pid??null,exited:re};return U.pid!==null&&(r.register(e,U),a=!0,re.then(async c=>await r.onChildExit(e,c,d))),U}catch(l){if(!a&&f?.pid!=null)try{f.kill("SIGTERM")}catch{}throw l}finally{a||r.releaseReservation(e),o!==null&&N(o)}},async isAlive(e){return I((typeof e=="string"?await v(e):e)?.pi_pid)},async teardown(e,t={}){try{return ve(await ke(e,t))}catch(n){return Promise.resolve({confirmed:!1,error:n instanceof Error?n:new Error(String(n))})}},async signal(e,t){const n=(await v(e))?.pi_pid;if(n!=null)try{process.kill(n,t)}catch{}}};export{tt as headlessBrokerHost,_e as isolatedBrokerLauncherAvailable,Er as preflightBrokerLaunch,rt as requestBrokerTeardown};
@@ -5,30 +5,30 @@ import { type WakeOrigin } from './bearings.js';
5
5
  export declare const RUNTIME_RESTART_CONTINUATION: string;
6
6
  /** The goal file — the prompt/task a node was spawned with, persisted at birth
7
7
  * so a fresh revive can re-read its mandate. */
8
- export declare function goalPath(nodeId: string): string;
9
- export declare function readGoal(nodeId: string): string | null;
8
+ export declare function goalPath(nodeId: string): Promise<string>;
9
+ export declare function readGoal(nodeId: string): Promise<string | null>;
10
10
  /** Persist the spawning prompt as the node's goal. No-op for an empty prompt
11
11
  * (e.g. a bare root). Idempotent enough — call once at spawn/boot. */
12
- export declare function writeGoal(nodeId: string, text: string): void;
12
+ export declare function writeGoal(nodeId: string, text: string): Promise<void>;
13
13
  /** Write the goal ONLY if the node has none yet. This is how a bare root (no
14
14
  * spawn prompt) acquires its mandate: the first real user message becomes the
15
15
  * goal. Returns true when it wrote one, false when a goal already existed or
16
16
  * the text was empty. Guarded so a later message never clobbers the mandate. */
17
- export declare function captureGoalIfAbsent(nodeId: string, text: string): boolean;
17
+ export declare function captureGoalIfAbsent(nodeId: string, text: string): Promise<boolean>;
18
18
  /** The yield-message file — a short note `crtr node yield` records for the next
19
19
  * fresh/cycling revive ("on wake, do X"). It remains durable through failed
20
20
  * launch attempts and is cleared only when session_start confirms a boot. */
21
- export declare function yieldMessagePath(nodeId: string): string;
22
- export declare function writeYieldMessage(nodeId: string, text: string): void;
21
+ export declare function yieldMessagePath(nodeId: string): Promise<string>;
22
+ export declare function writeYieldMessage(nodeId: string, text: string): Promise<void>;
23
23
  /** Read the pending yield message without mutating its confirmation state. */
24
- export declare function readYieldMessage(nodeId: string): string | null;
24
+ export declare function readYieldMessage(nodeId: string): Promise<string | null>;
25
25
  /** Idempotently commit delivery of the yield message after a confirmed boot. */
26
- export declare function clearYieldMessage(nodeId: string): void;
26
+ export declare function clearYieldMessage(nodeId: string): Promise<void>;
27
27
  /** List the node's context/ dir (filenames, sorted). Empty when absent. */
28
- export declare function listContextDir(nodeId: string): string[];
28
+ export declare function listContextDir(nodeId: string): Promise<string[]>;
29
29
  /** A retained report proves this node has already done work. It must restart
30
30
  * from current context, never by replaying its birth mandate. */
31
- export declare function hasRetainedReports(nodeId: string): boolean;
31
+ export declare function hasRetainedReports(nodeId: string): Promise<boolean>;
32
32
  export interface ReviveBearings {
33
33
  /** The one-shot yield note left by the prior self, pending boot confirmation. */
34
34
  yieldMsg: string | null;
@@ -40,10 +40,10 @@ export interface ReviveBearings {
40
40
  driftGuidance: string | null;
41
41
  }
42
42
  /** Claim wake mail for this launch without acknowledging it before a turn. */
43
- export declare function drainBearings(meta: NodeMeta, executionId: string): ReviveBearings;
43
+ export declare function drainBearings(meta: NodeMeta, executionId: string): Promise<ReviveBearings>;
44
44
  /** Assemble the auto-injected first message for a FRESH revive of `meta` from its
45
45
  * already-drained `bearings` (see drainBearings) plus pure on-disk reads of the
46
46
  * node's goal, roadmap, and context dir, framed so the revived node can rebuild
47
47
  * its bearings in one turn. PURE: no state mutation, so calling it twice yields
48
48
  * the same string and consumes nothing — drainBearings owns the one-shot reads. */
49
- export declare function buildReviveKickoff(meta: NodeMeta, bearings: ReviveBearings, wakeReason?: WakeOrigin): string;
49
+ export declare function buildReviveKickoff(meta: NodeMeta, bearings: ReviveBearings, wakeReason?: WakeOrigin): Promise<string>;
@@ -1,28 +1,28 @@
1
- var B=Object.defineProperty;var i=(t,e)=>B(t,"name",{value:e,configurable:!0});import{join as w}from"node:path";import{getNode as M,subscriptionsOf as R,subscribersOf as N}from"../canvas/index.js";import{contextDir as h,nodeAgentDir as l}from"../canvas/node-agent-paths.js";import{hasReportDocuments as A}from"../feed/reports.js";import{readdirBeneath as E,readTextBeneathIfExists as x,unlinkBeneath as T,writeFileBeneath as $}from"../spaces/open-beneath.js";import{activeBackgroundBashJobs as D,bashJobCommandLine as I,formatBashElapsed as G}from"../bash-jobs.js";import{readRoadmap as O}from"./roadmap.js";import{buildWakeBearings as _}from"./bearings.js";import{personaDrift as Y}from"./persona.js";import{coalesce as C,nodeMailEntry as L}from"../feed/inbox.js";import{claimKickoffMail as U}from"../canvas/deliveries.js";import{formatCard as k}from"../../shared/generated-context.js";const ut=k("restart-continuation",{},"continue");function y(t){return w(h(t),"initial-prompt.md")}i(y,"goalPath");function j(t){return x(l(t),y(t))}i(j,"readGoal");function J(t,e){const n=e.trim();n!==""&&$(l(t),y(t),n+`
2
- `)}i(J,"writeGoal");function dt(t,e){const n=j(t);if(n!==null&&n.trim()!=="")return!1;const r=e.trim();return r===""?!1:(J(t,r),!0)}i(dt,"captureGoalIfAbsent");function b(t){return w(h(t),"yield-message.md")}i(b,"yieldMessagePath");function ct(t,e){const n=e.trim();n!==""&&$(l(t),b(t),n+`
3
- `)}i(ct,"writeYieldMessage");function P(t){const e=x(l(t),b(t))?.trim()??"";return e!==""?e:null}i(P,"readYieldMessage");function lt(t){try{T(l(t),b(t))}catch{}}i(lt,"clearYieldMessage");function F(t){return S(t,h(t)).sort()}i(F,"listContextDir");function K(t){return A(t)}i(K,"hasRetainedReports");function S(t,e){try{return E(l(t),e).map(n=>n.name)}catch(n){if(n.code==="ENOENT")return[];throw n}}i(S,"agentDirNames");function ft(t,e){const n=t.node_id,r=P(n),o=t.run_id?[]:U(n,e),s=o.map(a=>a.message.messageId),f=o.map(L);let u=null;if(f.length>0){const a=i(d=>{const m=d.data?.cards;return Array.isArray(m)?m.filter(v=>typeof v=="string"):[]},"cardsFor"),p=[];for(const d of f)(a(d).length>0||p.length===0)&&p.push([]),p.at(-1).push(d);u=p.map(d=>[...a(d[0]),C(d).map(m=>m.text).join(`
1
+ var M=Object.defineProperty;var r=(t,n)=>M(t,"name",{value:n,configurable:!0});import{join as b}from"node:path";import{getNode as R,subscriptionsOf as A,subscribersOf as N}from"../canvas/index.js";import{contextDir as h,nodeAgentDir as l}from"../canvas/node-agent-paths.js";import{hasReportDocuments as E}from"../feed/reports.js";import{readdirBeneath as T,readTextBeneathIfExists as x,unlinkBeneath as D,writeFileBeneath as $}from"../spaces/open-beneath.js";import{activeBackgroundBashJobs as I,bashJobCommandLine as G,formatBashElapsed as O}from"../bash-jobs.js";import{readRoadmap as _}from"./roadmap.js";import{buildWakeBearings as Y}from"./bearings.js";import{personaDrift as C}from"./persona.js";import{coalesce as L,nodeMailEntry as U}from"../feed/inbox.js";import{claimKickoffMail as J}from"../canvas/deliveries.js";import{formatCard as k}from"../../shared/generated-context.js";import{mapAsync as j}from"../async-array.js";const dt=k("restart-continuation",{},"continue");async function y(t){return b(await h(t),"initial-prompt.md")}r(y,"goalPath");async function v(t){return x(await l(t),await y(t))}r(v,"readGoal");async function P(t,n){const e=n.trim();e!==""&&$(await l(t),await y(t),e+`
2
+ `)}r(P,"writeGoal");async function lt(t,n){const e=await v(t);if(e!==null&&e.trim()!=="")return!1;const o=n.trim();return o===""?!1:(await P(t,o),!0)}r(lt,"captureGoalIfAbsent");async function g(t){return b(await h(t),"yield-message.md")}r(g,"yieldMessagePath");async function ft(t,n){const e=n.trim();e!==""&&$(await l(t),await g(t),e+`
3
+ `)}r(ft,"writeYieldMessage");async function F(t){const n=x(await l(t),await g(t))?.trim()??"";return n!==""?n:null}r(F,"readYieldMessage");async function ht(t){try{D(await l(t),await g(t))}catch{}}r(ht,"clearYieldMessage");async function K(t){return(await q(t,await h(t))).sort()}r(K,"listContextDir");async function S(t){return await E(t)}r(S,"hasRetainedReports");async function q(t,n){try{return T(await l(t),n).map(e=>e.name)}catch(e){if(e.code==="ENOENT")return[];throw e}}r(q,"agentDirNames");async function mt(t,n){const e=t.node_id,o=await F(e),a=t.run_id?[]:await J(e,n),i=a.map(s=>s.message.messageId),f=a.map(U);let u=null;if(f.length>0){const s=r(c=>{const p=c.data?.cards;return Array.isArray(p)?p.filter(B=>typeof B=="string"):[]},"cardsFor"),m=[];for(const c of f)(s(c).length>0||m.length===0)&&m.push([]),m.at(-1).push(c);u=(await j(m,async c=>[...s(c[0]),(await L(c)).map(p=>p.text).join(`
4
4
 
5
5
  `)].join(`
6
6
 
7
- `)).join(`
7
+ `))).join(`
8
8
 
9
- `)}const c=Y(n),g=c?.guidance===void 0||c.guidance===""?null:c.guidance;return{yieldMsg:r,unreadDigest:u,unreadMessageIds:s,driftGuidance:g}}i(ft,"drainBearings");function q(t,e){const n=R(t).filter(o=>o.active).map(o=>M(o.node_id)).filter(o=>o!==null&&(o.status==="active"||o.status==="idle")),r=[];if(n.length>0){const o=n.length,s=o===1?"it has":"they have",f=o===1?"Its":"Their";r.push(`Awaiting ${o} node${o===1?"":"s"} \u2014 ${s} not finished. ${f} reports will wake you.`);for(const u of n)r.push(` - ${u.name} (${u.node_id}) \u2014 ${u.status}`);r.push("",e??"(no unread reports)")}else r.push("Awaiting 0 nodes."),r.push("",e??"(no unread reports)");return`<feed>
10
- ${r.join(`
11
- `)}
12
- </feed>`}i(q,"feedBlock");function W(t,e){const n=(t??I(e)).trim()||"(no command)";return n.length>120?`${n.slice(0,117)}\u2026`:n}i(W,"jobLabel");function z(t){const e=D(h(t));if(e.length===0)return null;const n=Date.now(),r=e.length===1,o=[`${e.length} background bash job${r?"":"s"} you started ${r?"is":"are"} STILL RUNNING, detached from any turn and unaffected by your refresh. Each one sends you a message when it exits \u2014 that wake is automatic, so do not poll it and do not relaunch the same command.`];for(const s of e)o.push(` - ${s.jobId} \u2014 ${W(s.purpose,s.command)} \xB7 running ${G(n-s.startedAtMs)} \xB7 log ${s.logPath}`);return o.push("","Read output so far: `tail -n 50 <log>` (or `crtr node bash list --tail 20`). Abandon one: `crtr node bash kill <job-id>`."),`<background-jobs>
9
+ `)}const d=await C(e),w=d?.guidance===void 0||d.guidance===""?null:d.guidance;return{yieldMsg:o,unreadDigest:u,unreadMessageIds:i,driftGuidance:w}}r(mt,"drainBearings");async function W(t,n){const e=(await j((await A(t)).filter(a=>a.active),async a=>await R(a.node_id))).filter(a=>a!==null&&(a.status==="active"||a.status==="idle")),o=[];if(e.length>0){const a=e.length,i=a===1?"it has":"they have",f=a===1?"Its":"Their";o.push(`Awaiting ${a} node${a===1?"":"s"} \u2014 ${i} not finished. ${f} reports will wake you.`);for(const u of e)o.push(` - ${u.name} (${u.node_id}) \u2014 ${u.status}`);o.push("",n??"(no unread reports)")}else o.push("Awaiting 0 nodes."),o.push("",n??"(no unread reports)");return`<feed>
13
10
  ${o.join(`
14
11
  `)}
15
- </background-jobs>`}i(z,"backgroundJobsBlock");function ht(t,e,n){const r=t.node_id,o=["You have been revived fresh after a context refresh \u2014 your previous in-memory context is gone, by design. Everything below was just read from disk; it is your full bearings. Rebuild from it and continue toward your goal."];n!==void 0&&o.push(_(n));const s=O(r);if(!(s!==null&&s.trim()!=="")&&!K(r)){const a=j(r);a!==null&&a.trim()!==""&&o.push(`<goal file="${y(r)}">
16
- ${a.trim()}
17
- </goal>`)}const u=F(r).filter(a=>a!=="yield-message.md");o.push(`<context-dir path="${h(r)}">
12
+ </feed>`}r(W,"feedBlock");function z(t,n){const e=(t??G(n)).trim()||"(no command)";return e.length>120?`${e.slice(0,117)}\u2026`:e}r(z,"jobLabel");async function H(t){const n=I(await h(t));if(n.length===0)return null;const e=Date.now(),o=n.length===1,a=[`${n.length} background bash job${o?"":"s"} you started ${o?"is":"are"} STILL RUNNING, detached from any turn and unaffected by your refresh. Each one sends you a message when it exits \u2014 that wake is automatic, so do not poll it and do not relaunch the same command.`];for(const i of n)a.push(` - ${i.jobId} \u2014 ${z(i.purpose,i.command)} \xB7 running ${O(e-i.startedAtMs)} \xB7 log ${i.logPath}`);return a.push("","Read output so far: `tail -n 50 <log>` (or `crtr node bash list --tail 20`). Abandon one: `crtr node bash kill <job-id>`."),`<background-jobs>
13
+ ${a.join(`
14
+ `)}
15
+ </background-jobs>`}r(H,"backgroundJobsBlock");async function pt(t,n,e){const o=t.node_id,a=["You have been revived fresh after a context refresh \u2014 your previous in-memory context is gone, by design. Everything below was just read from disk; it is your full bearings. Rebuild from it and continue toward your goal."];e!==void 0&&a.push(Y(e));const i=await _(o);if(!(i!==null&&i.trim()!=="")&&!await S(o)){const s=await v(o);s!==null&&s.trim()!==""&&a.push(`<goal file="${await y(o)}">
16
+ ${s.trim()}
17
+ </goal>`)}const u=(await K(o)).filter(s=>s!=="yield-message.md");a.push(`<context-dir path="${await h(o)}">
18
18
  ${u.length>0?u.join(`
19
19
  `):"(empty)"}
20
- </context-dir>`);const c=z(r);c!==null&&o.push(c),o.push(q(r,e.unreadDigest)),o.push(e.yieldMsg!==null?`<yield-message>
21
- ${e.yieldMsg.trim()}
22
- </yield-message>`:"<yield-message/>");const g=N(r).length>0;return o.push(g?"If there is work to do, perform it. Otherwise stop \u2014 pipe the result to `crtr push final` through a single-quoted heredoc if the goal is met, or end your turn without a message to stay dormant awaiting your workers.":"If there is work to do, perform it. Otherwise end your turn without writing a message \u2014 the user already has your last reply, and a status recap would only bury it. You are working directly with the user, so stay available and continue when they write back."),e.driftGuidance!==null&&o.push(`<persona-transition>
23
- Your role was changed while you were away. ${e.driftGuidance}
20
+ </context-dir>`);const d=await H(o);d!==null&&a.push(d),a.push(await W(o,n.unreadDigest)),a.push(n.yieldMsg!==null?`<yield-message>
21
+ ${n.yieldMsg.trim()}
22
+ </yield-message>`:"<yield-message/>");const w=(await N(o)).length>0;return a.push(w?"If there is work to do, perform it. Otherwise stop \u2014 pipe the result to `crtr push final` through a single-quoted heredoc if the goal is met, or end your turn without a message to stay dormant awaiting your workers.":"If there is work to do, perform it. Otherwise end your turn without writing a message \u2014 the user already has your last reply, and a status recap would only bury it. You are working directly with the user, so stay available and continue when they write back."),n.driftGuidance!==null&&a.push(`<persona-transition>
23
+ Your role was changed while you were away. ${n.driftGuidance}
24
24
  </persona-transition>`),k("revive",{},`
25
- ${o.join(`
25
+ ${a.join(`
26
26
 
27
27
  `)}
28
- `)}i(ht,"buildReviveKickoff");export{ut as RUNTIME_RESTART_CONTINUATION,ht as buildReviveKickoff,dt as captureGoalIfAbsent,lt as clearYieldMessage,ft as drainBearings,y as goalPath,K as hasRetainedReports,F as listContextDir,j as readGoal,P as readYieldMessage,J as writeGoal,ct as writeYieldMessage,b as yieldMessagePath};
28
+ `)}r(pt,"buildReviveKickoff");export{dt as RUNTIME_RESTART_CONTINUATION,pt as buildReviveKickoff,lt as captureGoalIfAbsent,ht as clearYieldMessage,mt as drainBearings,y as goalPath,S as hasRetainedReports,K as listContextDir,v as readGoal,F as readYieldMessage,P as writeGoal,ft as writeYieldMessage,g as yieldMessagePath};
@@ -31,4 +31,4 @@ export declare function resolveLaunchTarget(req: CreateNodeRequest, options?: {
31
31
  validateKind?: (kind: string) => void | Promise<void>;
32
32
  }): Promise<ResolvedLaunchTarget>;
33
33
  /** The directory a new node is pinned to. */
34
- export declare function resolveNodeCwd(req: CreateNodeRequest, parent: string | undefined, _profileId: string | null, contextCwd: string): string;
34
+ export declare function resolveNodeCwd(req: CreateNodeRequest, parent: string | undefined, _profileId: string | null, contextCwd: string): Promise<string>;
@@ -1 +1 @@
1
- var u=Object.defineProperty;var i=(e,n)=>u(e,"name",{value:n,configurable:!0});import{appSpace as p}from"../layout.js";import{envProfileId as m}from"../../shared/env.js";import{resolve as s}from"node:path";import{getNode as w}from"../canvas/canvas.js";import{usage as v}from"../errors.js";import{assertProfileActive as h}from"../profiles/manifest.js";import{buildLaunchSpecAsync as _,readMergedLaunchConfigAsync as x}from"./launch.js";import{resolveProfileId as y}from"./spawn.js";function k(e,n){return e??n?.manifest.default_kind??"general"}i(k,"resolveCreateKind");const K="developer";function j(e){return e.manifest.default_kind??K}i(j,"resolveRunKind");const N=new Set(["human"]);function M(e){return!N.has(e)}i(M,"isLaunchKind");async function g(e,n=process.cwd(),r=m()||null){const t=Object.keys((await x(n,r)).kinds);if(!t.includes(e))throw v(`unknown kind: ${e}`,{received:e,next:`Valid kinds: ${t.sort().join(", ")}.`})}i(g,"assertLaunchKind");async function R(e,n={}){const r=e.parent??void 0,t=e.cwd??process.cwd(),o=await y(e.profile,r??null,t,{readOnlySelection:n.readOnlyProfileSelection}),a=h(o),d=k(e.kind,a);await n.validateKind?.(d);const c=L({...e,kind:d},r,o,t);n.validateKind===void 0&&await g(d,c,o);const l=e.mode??"base",f=(await _(d,l,{lifecycle:e.root_lifecycle??(e.root===!0?"resident":"terminal"),hasManager:e.root!==!0,...e.model!==void 0?{model:e.model,modelOverride:!0}:{},cwd:c,profileId:o})).launch;return{profileId:o,profile:a,kind:d,mode:l,cwd:c,launch:f}}i(R,"resolveLaunchTarget");function L(e,n,r,t){if(e.pin_cwd!==void 0&&e.pin_cwd!=="")return s(e.pin_cwd);if(n!=null){const o=w(n);if(o!==null)return o.cwd}return e.cwd!==void 0&&e.cwd!==""?s(e.cwd):process.platform==="linux"?p("terminal").files:t}i(L,"resolveNodeCwd");export{K as RUN_DEFAULT_KIND,g as assertLaunchKind,M as isLaunchKind,k as resolveCreateKind,R as resolveLaunchTarget,L as resolveNodeCwd,j as resolveRunKind};
1
+ var u=Object.defineProperty;var i=(e,n)=>u(e,"name",{value:n,configurable:!0});import{appSpace as p}from"../layout.js";import{envProfileId as m}from"../../shared/env.js";import{resolve as s}from"node:path";import{getNode as w}from"../canvas/canvas.js";import{usage as v}from"../errors.js";import{assertProfileActive as h}from"../profiles/manifest.js";import{buildLaunchSpecAsync as _,readMergedLaunchConfigAsync as x}from"./launch.js";import{resolveProfileId as y}from"./spawn.js";function k(e,n){return e??n?.manifest.default_kind??"general"}i(k,"resolveCreateKind");const K="developer";function j(e){return e.manifest.default_kind??K}i(j,"resolveRunKind");const N=new Set(["human"]);function M(e){return!N.has(e)}i(M,"isLaunchKind");async function g(e,n=process.cwd(),r=m()||null){const t=Object.keys((await x(n,r)).kinds);if(!t.includes(e))throw v(`unknown kind: ${e}`,{received:e,next:`Valid kinds: ${t.sort().join(", ")}.`})}i(g,"assertLaunchKind");async function R(e,n={}){const r=e.parent??void 0,t=e.cwd??process.cwd(),o=await y(e.profile,r??null,t,{readOnlySelection:n.readOnlyProfileSelection}),a=h(o),d=k(e.kind,a);await n.validateKind?.(d);const c=await L({...e,kind:d},r,o,t);n.validateKind===void 0&&await g(d,c,o);const l=e.mode??"base",f=(await _(d,l,{lifecycle:e.root_lifecycle??(e.root===!0?"resident":"terminal"),hasManager:e.root!==!0,...e.model!==void 0?{model:e.model,modelOverride:!0}:{},cwd:c,profileId:o})).launch;return{profileId:o,profile:a,kind:d,mode:l,cwd:c,launch:f}}i(R,"resolveLaunchTarget");async function L(e,n,r,t){if(e.pin_cwd!==void 0&&e.pin_cwd!=="")return s(e.pin_cwd);if(n!=null){const o=await w(n);if(o!==null)return o.cwd}return e.cwd!==void 0&&e.cwd!==""?s(e.cwd):process.platform==="linux"?p("terminal").files:t}i(L,"resolveNodeCwd");export{K as RUN_DEFAULT_KIND,g as assertLaunchKind,M as isLaunchKind,k as resolveCreateKind,R as resolveLaunchTarget,L as resolveNodeCwd,j as resolveRunKind};
@@ -1,10 +1,10 @@
1
1
  /** End the node's context session: its ledger holds nothing. */
2
- export declare function clearNodeLedger(nodeId: string): void;
2
+ export declare function clearNodeLedger(nodeId: string): Promise<void>;
3
3
  /** Seed a fork's ledger once with the transcript rows its source holds; no
4
4
  * source → empty. A fork already seeded (at spawn, or by an earlier birth
5
5
  * attempt) keeps its ledger, so a retry after the source is deleted loses nothing. */
6
- export declare function forkNodeLedger(forkId: string, sourceId: string | null): void;
6
+ export declare function forkNodeLedger(forkId: string, sourceId: string | null): Promise<void>;
7
7
  /** Queue one inbox entry for a node revived from done listing the watched
8
8
  * documents that got a newer revision (by someone else) since `since`.
9
9
  * Returns whether a notice was queued. */
10
- export declare function noticeChangedWhileDone(nodeId: string, since: string): boolean;
10
+ export declare function noticeChangedWhileDone(nodeId: string, since: string): Promise<boolean>;
@@ -1,3 +1,3 @@
1
- var y=Object.defineProperty;var i=(e,o)=>y(e,"name",{value:o,configurable:!0});import{withCanvasWrite as u}from"../canvas/db.js";import{changedWhileDone as $}from"../substrate/delivery/deliver.js";import{queueNodeNotice as L}from"../feed/messages.js";import{clearLedger as f,forkLedger as k,hasLedger as N}from"../graph/exposures.js";import{getById as m,getByRowid as j,nodeObject as c}from"../graph/objects.js";function q(e){u(o=>f(o,c(o,e).rowid))}i(q,"clearNodeLedger");function H(e,o){u(n=>{const r=c(n,e);if(N(n,r.rowid))return;const t=o===null?null:m(n,o);t===null||t.type!=="node"?f(n,r.rowid):k(n,t.rowid,r.rowid)})}i(H,"forkNodeLedger");function d(e){return e===null?"?":e.type==="node"?e.id:e.name}i(d,"ownerHandle");function O(e,o){return u(n=>{const r=$(n,c(n,e),o);if(r.length===0)return!1;const t=r.map(({doc:l,from:g,to:w,authors:a})=>{const h=l.owner===null?null:j(n,l.owner),s=a.length===0?"":`, by ${a.map(p=>d(m(n,p))).join(", ")}`;return`- ${d(h)}/${l.name} \u2014 revision ${g??"none"} \u2192 ${w}${s}`});return L(n,e,{body:`Documents you watch changed while you were done:
2
- ${t.join(`
3
- `)}`,label:"documents changed while you were done",tier:"normal",wake:0}),!0})}i(O,"noticeChangedWhileDone");export{q as clearNodeLedger,H as forkNodeLedger,O as noticeChangedWhileDone};
1
+ var $=Object.defineProperty;var i=(e,a)=>$(e,"name",{value:a,configurable:!0});import{withCanvasWrite as w}from"../canvas/db.js";import{changedWhileDone as L}from"../substrate/delivery/deliver.js";import{queueNodeNotice as k}from"../feed/messages.js";import{clearLedger as u,forkLedger as N,hasLedger as j}from"../graph/exposures.js";import{getById as s,getByRowid as x,nodeObject as c}from"../graph/objects.js";import{mapAsync as y}from"../async-array.js";async function H(e){await w(async a=>await u(a,(await c(a,e)).rowid))}i(H,"clearNodeLedger");async function O(e,a){await w(async n=>{const t=await c(n,e);if(await j(n,t.rowid))return;const o=a===null?null:await s(n,a);o===null||o.type!=="node"?await u(n,t.rowid):await N(n,o.rowid,t.rowid)})}i(O,"forkNodeLedger");function f(e){return e===null?"?":e.type==="node"?e.id:e.name}i(f,"ownerHandle");async function R(e,a){return await w(async n=>{const t=await L(n,await c(n,e),a);if(t.length===0)return!1;const o=await y(t,async({doc:r,from:m,to:d,authors:l})=>{const g=r.owner===null?null:await x(n,r.owner),h=l.length===0?"":`, by ${(await y(l,async p=>f(await s(n,p)))).join(", ")}`;return`- ${f(g)}/${r.name} \u2014 revision ${m??"none"} \u2192 ${d}${h}`});return await k(n,e,{body:`Documents you watch changed while you were done:
2
+ ${o.join(`
3
+ `)}`,label:"documents changed while you were done",tier:"normal",wake:0}),!0})}i(R,"noticeChangedWhileDone");export{H as clearNodeLedger,O as forkNodeLedger,R as noticeChangedWhileDone};
@@ -16,7 +16,7 @@ export interface TerminalOutcomeInput {
16
16
  export declare function transition(nodeId: string, event: LifecycleEvent, opts?: {
17
17
  reason?: TerminalReason;
18
18
  outcome?: TerminalOutcomeInput;
19
- }): NodeMeta;
19
+ }): Promise<NodeMeta>;
20
20
  /** Whether this row is a PARKED node — terminalized by the unattended clock
21
21
  * rather than by finishing its own work. The one read of the park marker:
22
22
  * `done` qualified by `intent='parked'`, both written in the same atomic
@@ -1,2 +1,2 @@
1
- var x=Object.defineProperty;var u=(t,e)=>x(t,"name",{value:e,configurable:!0});import{getNode as S,cancelCronsOnWake as J,transitionStatusIntent as b}from"../canvas/index.js";import{composeNodeOutcomeDocument as A}from"./outcome-document.js";import{withCanvasWrite as E}from"../canvas/db.js";import{nodeObject as D}from"../graph/objects.js";import{endMessageSubscriptions as L}from"../graph/watches.js";import{settleNodeObjectWaits as j}from"../canvas/waits.js";import{runStructuredRequestEffects as P,settlePendingStructuredRequestForNodeIn as $}from"../canvas/structured-requests.js";const m="*",q={finish:"finished",park:"parked",cancel:"stranded",crash:"crashed","refresh-launch":null,revive:null},l=["active","idle"],M={finish:{status:"done",intent:"done",from:l},park:{status:"done",intent:"parked",from:l},cancel:{status:"canceled",intent:null,from:m},crash:{status:"dead",from:l},yield:{intent:"refresh",from:l},release:{status:"idle",intent:"idle-release",from:[...l,"done"]},"refresh-launch":{status:"active",intent:"refresh",from:m},revive:{status:"active",intent:null,from:m}};function T(t,e){const r=t.split(`
2
- `)[0]??"";let n=0,c="";for(const d of r){const s=Buffer.byteLength(d,"utf8");if(n+s>e)break;n+=s,c+=d}return c}u(T,"firstLineAtMost");function W(t){if(t===void 0)return null;const e=t.message===void 0?void 0:T(t.message,500),r={...t,...e===void 0?{}:{message:e}},n=JSON.stringify(r);return Buffer.byteLength(n,"utf8")<=4*1024?n:JSON.stringify({schema:"crtr.node-outcome-detail/v1",truncated:!0,...e===void 0?{}:{message:e}})}u(W,"detailJson");function B(t,e){let r,n;return e==="finished"||e==="declined"?(r="done",n="done"):e==="parked"?(r="done",n="parked"):e==="closed"||e==="retired"||e==="stranded"||e==="deadline_exceeded"?(r="canceled",n=null):(r="dead",n=null),{...t,status:r,intent:n,terminal_reason:e}}u(B,"nodeAtOutcome");function H(t,e,r){const n=M[e],c=Object.prototype.hasOwnProperty.call(n,"status"),d=Object.prototype.hasOwnProperty.call(n,"intent"),s=r?.reason??q[e],f={};c&&(f.status=n.status),d&&(f.intent=n.intent??null),s!==void 0&&(f.terminal_reason=s);const a=e==="finish"||e==="park"||e==="cancel"||e==="crash",o=a?S(t):null,p=a&&o?.kind!=="human",h=s,_=a?new Date().toISOString():null,w=W(r?.outcome?.detail),N=p&&o?.run_id!=null&&s!=="parked"&&o.outcome_at!==null&&(l.includes(o.status)||o.outcome_reason==="parked");let k;p&&o!==null&&(o.outcome_at===null||N)&&(k=JSON.stringify(A({node:B(o,h),outcome:{kind:"failure",reason:h,at:_,revision:(o.outcome_revision??0)+1,detailJson:w}})));const y=a?s==="deadline_exceeded"?{intended:"expired",failureReason:"node_deadline_exceeded",failureDetail:r?.outcome?.detail??null}:{intended:"failed",failureReason:s,failureDetail:r?.outcome?.detail??null}:null,O=E(i=>{const g=b(t,f,{fromStatuses:n.from===m?void 0:n.from,requireNoFinalReport:e==="cancel",...p?{outcome:{kind:"failure",reason:h,detailJson:w,at:_,...N?{supersede:!0}:{},...k===void 0?{}:{documentJson:k}}}:{}});a&&g>0&&(L(i,D(i,t),"done"),j(i,t));const R=g===1&&y!==null?$(i,t,y):null;return{changes:g,settlement:R}});if(O.changes===0){const i=S(t);if(i===null)throw new Error(`transition: unknown node ${t}`);if(e==="cancel"&&i.final_report!==null&&i.final_report!==void 0)return i;throw new Error(`illegal lifecycle transition: '${e}' from status='${i.status}' (node ${t})`)}return O.settlement?.changed&&P(O.settlement.row),(e==="finish"||e==="park"||e==="cancel")&&J(t),S(t)}u(H,"transition");function K(t){return t.status==="done"&&t.intent==="parked"}u(K,"isParked");function Q(t){return t?.intent==="idle-release"}u(Q,"hasIdleReleaseIntent");export{Q as hasIdleReleaseIntent,K as isParked,H as transition};
1
+ var x=Object.defineProperty;var a=(t,e)=>x(t,"name",{value:e,configurable:!0});import{getNode as g,cancelCronsOnWake as J,transitionStatusIntent as b}from"../canvas/index.js";import{composeNodeOutcomeDocument as A}from"./outcome-document.js";import{withCanvasWrite as E}from"../canvas/db.js";import{nodeObject as D}from"../graph/objects.js";import{endMessageSubscriptions as L}from"../graph/watches.js";import{settleNodeObjectWaits as j}from"../canvas/waits.js";import{runStructuredRequestEffects as P,settlePendingStructuredRequestForNodeIn as $}from"../canvas/structured-requests.js";const m="*",q={finish:"finished",park:"parked",cancel:"stranded",crash:"crashed","refresh-launch":null,revive:null},u=["active","idle"],M={finish:{status:"done",intent:"done",from:u},park:{status:"done",intent:"parked",from:u},cancel:{status:"canceled",intent:null,from:m},crash:{status:"dead",from:u},yield:{intent:"refresh",from:u},release:{status:"idle",intent:"idle-release",from:[...u,"done"]},"refresh-launch":{status:"active",intent:"refresh",from:m},revive:{status:"active",intent:null,from:m}};function T(t,e){const r=t.split(`
2
+ `)[0]??"";let n=0,c="";for(const d of r){const s=Buffer.byteLength(d,"utf8");if(n+s>e)break;n+=s,c+=d}return c}a(T,"firstLineAtMost");function W(t){if(t===void 0)return null;const e=t.message===void 0?void 0:T(t.message,500),r={...t,...e===void 0?{}:{message:e}},n=JSON.stringify(r);return Buffer.byteLength(n,"utf8")<=4*1024?n:JSON.stringify({schema:"crtr.node-outcome-detail/v1",truncated:!0,...e===void 0?{}:{message:e}})}a(W,"detailJson");function B(t,e){let r,n;return e==="finished"||e==="declined"?(r="done",n="done"):e==="parked"?(r="done",n="parked"):e==="closed"||e==="retired"||e==="stranded"||e==="deadline_exceeded"?(r="canceled",n=null):(r="dead",n=null),{...t,status:r,intent:n,terminal_reason:e}}a(B,"nodeAtOutcome");async function H(t,e,r){const n=M[e],c=Object.prototype.hasOwnProperty.call(n,"status"),d=Object.prototype.hasOwnProperty.call(n,"intent"),s=r?.reason??q[e],f={};c&&(f.status=n.status),d&&(f.intent=n.intent??null),s!==void 0&&(f.terminal_reason=s);const l=e==="finish"||e==="park"||e==="cancel"||e==="crash",o=l?await g(t):null,p=l&&o?.kind!=="human",h=s,S=l?new Date().toISOString():null,y=W(r?.outcome?.detail),_=p&&o?.run_id!=null&&s!=="parked"&&o.outcome_at!==null&&(u.includes(o.status)||o.outcome_reason==="parked");let w;p&&o!==null&&(o.outcome_at===null||_)&&(w=JSON.stringify(await A({node:B(o,h),outcome:{kind:"failure",reason:h,at:S,revision:(o.outcome_revision??0)+1,detailJson:y}})));const N=l?s==="deadline_exceeded"?{intended:"expired",failureReason:"node_deadline_exceeded",failureDetail:r?.outcome?.detail??null}:{intended:"failed",failureReason:s,failureDetail:r?.outcome?.detail??null}:null,k=await E(async i=>{const O=await b(t,f,{fromStatuses:n.from===m?void 0:n.from,requireNoFinalReport:e==="cancel",...p?{outcome:{kind:"failure",reason:h,detailJson:y,at:S,..._?{supersede:!0}:{},...w===void 0?{}:{documentJson:w}}}:{}});l&&O>0&&(await L(i,await D(i,t),"done"),await j(i,t));const R=O===1&&N!==null?await $(i,t,N):null;return{changes:O,settlement:R}});if(k.changes===0){const i=await g(t);if(i===null)throw new Error(`transition: unknown node ${t}`);if(e==="cancel"&&i.final_report!==null&&i.final_report!==void 0)return i;throw new Error(`illegal lifecycle transition: '${e}' from status='${i.status}' (node ${t})`)}return k.settlement?.changed&&P(k.settlement.row),(e==="finish"||e==="park"||e==="cancel")&&await J(t),await g(t)}a(H,"transition");function K(t){return t.status==="done"&&t.intent==="parked"}a(K,"isParked");function Q(t){return t?.intent==="idle-release"}a(Q,"hasIdleReleaseIntent");export{Q as hasIdleReleaseIntent,K as isParked,H as transition};
@@ -1 +1 @@
1
- var f=Object.defineProperty;var n=(e,r)=>f(e,"name",{value:r,configurable:!0});import{existsSync as p}from"node:fs";import{launcherRequest as u}from"../../launcher/client.js";import{LAUNCHER_SOCKET as _}from"../../launcher/spec.js";import{getNode as v}from"../canvas/index.js";import{emitEvent as y}from"../events/emit.js";import{isSafeNodeId as b}from"../canvas/paths.js";const M=1e3,x=1e4,a="*",l={available:n(()=>process.platform==="linux"&&p(_),"available"),request:n((e,r)=>u({operation:"memory.admit",app:e,nodeId:r}),"request")};let c=l;const s=new Map;function L(e){c=e??l,s.clear()}n(L,"stubMemoryAdmissionForTests");async function N(e,r={}){if(!c.available())return{verdict:"admitted"};const o=v(e)?.grantee??"app:terminal",d=r.now??Date.now();if(r.useMemo!==!1)for(const i of[o,a]){const m=s.get(i);if(m!==void 0&&d-m.at<M)return m.verdict}let t;try{t=await c.request(o,e)}catch(i){return y({level:"warn",event:"broker.memory_admission.failed",...b(e)?{node_id:e}:{},error:i}),{verdict:"admitted"}}if(!("verdict"in t))return{verdict:"admitted"};if(t.verdict==="denied"){const i={verdict:"denied",app:o,level:t.level,free_bytes:t.free_bytes,needed_bytes:t.needed_bytes};return s.set(t.level==="app"?o:a,{at:d,verdict:i}),i}return t.verdict==="too_small"?{verdict:"too_small",app:o,max_bytes:t.max_bytes,needed_bytes:t.needed_bytes}:{verdict:"admitted"}}n(N,"admitBrokerMemory");function k(e,r){return[e,a].some(o=>{const d=s.get(o);return d!==void 0&&r-d.at<x})}n(k,"memoryDeniedRecently");export{M as DENIAL_MEMO_MS,x as MEMORY_PRESSURE_MS,N as admitBrokerMemory,k as memoryDeniedRecently,L as stubMemoryAdmissionForTests};
1
+ var f=Object.defineProperty;var n=(e,r)=>f(e,"name",{value:r,configurable:!0});import{existsSync as p}from"node:fs";import{launcherRequest as u}from"../../launcher/client.js";import{LAUNCHER_SOCKET as _}from"../../launcher/spec.js";import{getNode as v}from"../canvas/index.js";import{emitEvent as y}from"../events/emit.js";import{isSafeNodeId as b}from"../canvas/paths.js";const M=1e3,x=1e4,m="*",l={available:n(()=>process.platform==="linux"&&p(_),"available"),request:n((e,r)=>u({operation:"memory.admit",app:e,nodeId:r}),"request")};let c=l;const a=new Map;function L(e){c=e??l,a.clear()}n(L,"stubMemoryAdmissionForTests");async function N(e,r={}){if(!c.available())return{verdict:"admitted"};const o=(await v(e))?.grantee??"app:terminal",d=r.now??Date.now();if(r.useMemo!==!1)for(const i of[o,m]){const s=a.get(i);if(s!==void 0&&d-s.at<M)return s.verdict}let t;try{t=await c.request(o,e)}catch(i){return y({level:"warn",event:"broker.memory_admission.failed",...b(e)?{node_id:e}:{},error:i}),{verdict:"admitted"}}if(!("verdict"in t))return{verdict:"admitted"};if(t.verdict==="denied"){const i={verdict:"denied",app:o,level:t.level,free_bytes:t.free_bytes,needed_bytes:t.needed_bytes};return a.set(t.level==="app"?o:m,{at:d,verdict:i}),i}return t.verdict==="too_small"?{verdict:"too_small",app:o,max_bytes:t.max_bytes,needed_bytes:t.needed_bytes}:{verdict:"admitted"}}n(N,"admitBrokerMemory");function k(e,r){return[e,m].some(o=>{const d=a.get(o);return d!==void 0&&r-d.at<x})}n(k,"memoryDeniedRecently");export{M as DENIAL_MEMO_MS,x as MEMORY_PRESSURE_MS,N as admitBrokerMemory,k as memoryDeniedRecently,L as stubMemoryAdmissionForTests};
@@ -20,7 +20,7 @@ export declare function setModelLive(nodeId: string, spec: string, intent: Model
20
20
  * `launch.modelExact` (the model runs verbatim). `spec` must already be a
21
21
  * concrete `provider/id` (normalizeModel maps tiers/aliases; a bare substring
22
22
  * cannot resolve offline). */
23
- export declare function updateModelRecipe(meta: NodeMeta, spec: string, intent: ModelIntent | undefined, userSelected: boolean): NodeMeta;
23
+ export declare function updateModelRecipe(meta: NodeMeta, spec: string, intent: ModelIntent | undefined, userSelected: boolean): Promise<NodeMeta>;
24
24
  /** Persist a user's model choice into a DORMANT node's durable recipe — the same
25
25
  * write the broker commits on a live switch. */
26
- export declare function persistDormantModel(nodeId: string, spec: string, intent: ModelIntent | undefined): void;
26
+ export declare function persistDormantModel(nodeId: string, spec: string, intent: ModelIntent | undefined): Promise<void>;
@@ -1 +1 @@
1
- var u=Object.defineProperty;var n=(e,o)=>u(e,"name",{value:o,configurable:!0});import{existsSync as c}from"node:fs";import{getNode as s,updateNode as f}from"../canvas/index.js";import{viewSocketPath as p}from"../canvas/paths.js";import{isPidAlive as _}from"../canvas/pid.js";import{oneShotControllerRequest as a}from"./broker-request.js";function y(e){return _(e.pi_pid)&&c(p(e.node_id))}n(y,"isBrokerLive");function L(e,o,t){let d;return a({nodeId:e,what:"the model switch",ackFor:"set_model",frame:n(()=>({type:"set_model",model:o,...t!==void 0?{intent:t}:{}}),"frame"),observe:n(r=>{r.type==="model_changed"&&r.spec!==null&&(d=r.spec)},"observe"),result:n(()=>d??o,"result")})}n(L,"setModelLive");function v(e,o,t,d){const r=e.launch===void 0?void 0:d?(()=>{const{modelIntent:h,modelExact:E,env:m,...l}=e.launch,{CRTR_MODEL_INTENT:x,...i}=m;return t!==void 0?{...l,model:o,modelIntent:t,env:{...i,CRTR_MODEL_INTENT:`${t.family}/${t.strength}`}}:{...l,model:o,modelExact:!0,env:i}})():{...e.launch,model:o};return f(e.node_id,{model_override:o,...r!==void 0?{launch:r}:{}})}n(v,"updateModelRecipe");function S(e,o,t){const d=s(e);d!==null&&v(d,o,t,!0)}n(S,"persistDormantModel");export{y as isBrokerLive,S as persistDormantModel,L as setModelLive,v as updateModelRecipe};
1
+ var u=Object.defineProperty;var n=(e,o)=>u(e,"name",{value:o,configurable:!0});import{existsSync as c}from"node:fs";import{getNode as a,updateNode as s}from"../canvas/index.js";import{viewSocketPath as f}from"../canvas/paths.js";import{isPidAlive as p}from"../canvas/pid.js";import{oneShotControllerRequest as _}from"./broker-request.js";function M(e){return p(e.pi_pid)&&c(f(e.node_id))}n(M,"isBrokerLive");function g(e,o,t){let d;return _({nodeId:e,what:"the model switch",ackFor:"set_model",frame:n(()=>({type:"set_model",model:o,...t!==void 0?{intent:t}:{}}),"frame"),observe:n(r=>{r.type==="model_changed"&&r.spec!==null&&(d=r.spec)},"observe"),result:n(()=>d??o,"result")})}n(g,"setModelLive");async function v(e,o,t,d){const r=e.launch===void 0?void 0:d?(()=>{const{modelIntent:h,modelExact:E,env:m,...i}=e.launch,{CRTR_MODEL_INTENT:x,...l}=m;return t!==void 0?{...i,model:o,modelIntent:t,env:{...l,CRTR_MODEL_INTENT:`${t.family}/${t.strength}`}}:{...i,model:o,modelExact:!0,env:l}})():{...e.launch,model:o};return await s(e.node_id,{model_override:o,...r!==void 0?{launch:r}:{}})}n(v,"updateModelRecipe");async function L(e,o,t){const d=await a(e);d!==null&&await v(d,o,t,!0)}n(L,"persistDormantModel");export{M as isBrokerLive,L as persistDormantModel,g as setModelLive,v as updateModelRecipe};
@@ -18,7 +18,7 @@ export interface NodeSessionRead {
18
18
  * per boot), so it is read from the sidecar the broker captures on every
19
19
  * rebind (`<jobDir>/system-prompt.md`), falling back to the one `launch.ts`
20
20
  * writes at spawn (`<nodeDir>/system-prompt.md`). */
21
- export declare function readNodeSession(nodeId: string): NodeSessionRead;
21
+ export declare function readNodeSession(nodeId: string): Promise<NodeSessionRead>;
22
22
  export interface NodeSnapshotRead {
23
23
  nodeId: string;
24
24
  snapshot: BrokerSnapshot;
@@ -1,3 +1,3 @@
1
- var C=Object.defineProperty;var a=(e,t)=>C(e,"name",{value:t,configurable:!0});import{existsSync as N,readFileSync as j}from"node:fs";import{isBeneathRefusal as F,readFileBeneath as $,readTextBeneathIfExists as x}from"../spaces/open-beneath.js";import{join as p}from"node:path";import{InputError as f}from"../io.js";import{conversationIdFromPath as y,conversationStore as w,ConversationNotFoundError as A}from"../conversation-store/index.js";import{fullName as T,getNode as g}from"../canvas/index.js";import{nodeRunDir as h,nodeRunJobDir as S,sessionPtrPath as k}from"../canvas/paths.js";import{hydratePersistedAdvertisedCommandMessages as v}from"./advertised-command-invocation.js";import{SessionManager as L}from"./broker-sdk.js";import{openModelRegistry as P}from"./model-registry.js";import{BUILTIN_SLASH_COMMANDS as B}from"./pi-vendored.js";import{cycleAwareMessages as J}from"./session-cycles.js";import{projectTranscript as O}from"./session-visibility.js";import{normalizeToolGroupSummaryRecord as E}from"../../shared/tool-groups.js";import{normalizeTurnReplyRecord as U}from"../../shared/turn-replies.js";async function V(e){if(e!==null)try{return(await P()).find(e.provider,e.modelId)}catch{return}}a(V,"resolveRecordedModel");function b(e,t){const o=a(i=>{const n=i?y(i):null;if(n===null)return null;try{return w().header(n).path}catch(l){if(l instanceof A)return null;throw l}},"resolvePath"),s=o(t);if(s!==null)return s;const r=k(e);return N(r)?o(j(r,"utf8").trim()):null}a(b,"resolveSessionFile");function W(e){const t=g(e);if(t===null)throw new f({error:"not_found",message:`no node: ${e}`,field:"id",next:"List nodes with `crtr node inspect list`."});return b(e,t.pi_session_file)}a(W,"readableSessionFile");function z(e,t){return{sessionFile:t,sessionId:e,userMessages:0,assistantMessages:0,toolCalls:0,toolResults:0,totalMessages:0,tokens:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0},cost:0}}a(z,"emptyStats");function D(e,t,o){const s=z(t,o);s.totalMessages=e.length;for(const r of e)if(r.role==="user")s.userMessages++;else if(r.role==="assistant"){s.assistantMessages++;const i=Array.isArray(r.content)?r.content:[];s.toolCalls+=i.filter(l=>l!==null&&typeof l=="object"&&l.type==="toolCall").length;const n=r.usage;n!==void 0&&(s.tokens.input+=n.input??0,s.tokens.output+=n.output??0,s.tokens.cacheRead+=n.cacheRead??0,s.tokens.cacheWrite+=n.cacheWrite??0,s.cost+=n.cost?.total??0)}else r.role==="toolResult"&&s.toolResults++;return s.tokens.total=s.tokens.input+s.tokens.output+s.tokens.cacheRead+s.tokens.cacheWrite,s}a(D,"statsFromMessages");function ge(e){const t=g(e);if(t===null)throw new f({error:"not_found",message:`no node: ${e}`,field:"id",next:"List nodes with `crtr node inspect list`."});const o=b(e,t.pi_session_file);if(o===null)throw new f({error:"no_session",message:`node has no readable session file: ${e}`,field:"id",next:"Choose a node with captured conversation history."});return{nodeId:e,sessionFile:o,sessionJsonl:(()=>{const{header:s,entries:r}=w().read(y(o));return[s,...r].map(i=>`${JSON.stringify(i)}
2
- `).join("")})(),systemPrompt:M(e,p(S(e),"system-prompt.md"))??M(e,p(h(e),"system-prompt.md"))}}a(ge,"readNodeSession");function M(e,t){try{return $(h(e),t).toString("utf8")}catch(o){if(F(o))throw o;return null}}a(M,"readRunFileIfPresent");function G(e){try{const t=x(h(e),p(S(e),"tool-summaries.json"));return E(t===null?null:JSON.parse(t))}catch{return{}}}a(G,"readToolGroupSummaries");function q(e){try{const t=x(h(e),p(S(e),"turn-replies.json"));return U(t===null?null:JSON.parse(t))}catch{return{}}}a(q,"readTurnReplies");async function R(e){const t=g(e);if(t===null)throw new f({error:"not_found",message:`no node: ${e}`,field:"id",next:"List nodes with `crtr node inspect list`."});const o=b(e,t.pi_session_file);if(o===null)throw new f({error:"no_session",message:`node has no readable session file: ${e}`,field:"id",next:"Choose a node with captured conversation history."});const{header:s,entries:r}=w().read(y(o)),i=L.inMemory(s.cwd,void 0,[s,...r]),n=i.buildSessionContext();v(n.messages);const l=J(i);l!==void 0&&v(l.map(({message:c})=>c));const u=l===void 0?void 0:O(l,{boundaryReviewId:t.review_binding?.review_id,sessionEntries:i.getEntries()}),m=u?.map(({message:c})=>c)??n.messages;return{sessionFile:o,messages:m,identified:u,model:n.model,thinkingLevel:n.thinkingLevel,sessionId:i.getSessionId(),sessionName:i.getSessionName()}}a(R,"reconstructTranscript");function d(){throw new f({error:"invalid_cursor",message:"cursor must be a base64url-encoded messages cursor.",field:"cursor",next:"Omit cursor to start from the newest messages."})}a(d,"invalidCursor");function H(e,t){/^[A-Za-z0-9_-]+$/u.test(e)||d();let o;try{const r=Buffer.from(e,"base64url").toString("utf8");Buffer.from(r,"utf8").toString("base64url")!==e&&d(),o=JSON.parse(r)}catch{d()}(typeof o!="object"||o===null||o.v!==1||!Number.isSafeInteger(o.before))&&d();const s=o.before;return(s<0||s>t)&&d(),s}a(H,"decodeMessagesCursor");function Y(e){return Buffer.from(JSON.stringify({v:1,before:e}),"utf8").toString("base64url")}a(Y,"encodeMessagesCursor");async function Z(e){const t=await R(e),o={messages:t.messages,...t.identified===void 0?{}:{messageIds:t.identified.map(({id:s})=>s)},messageVisibility:t.identified?.map(({visibility:s})=>s)??t.messages.map(()=>"visible"),turnVisibility:"visible",stats:D(t.messages,t.sessionId,t.sessionFile),state:{model:await V(t.model),thinkingLevel:t.thinkingLevel,isStreaming:!1,isCompacting:!1,steeringMode:"one-at-a-time",followUpMode:"one-at-a-time",sessionFile:t.sessionFile,sessionId:t.sessionId,sessionName:t.sessionName,autoCompactionEnabled:!0,messageCount:t.messages.length,pendingMessageCount:0},display:{statuses:{},widgets:{},title:void 0},queued:{steering:[],followUp:[]},toolGroupSummaries:G(e),turnReplies:q(e)};return{nodeId:e,snapshot:o,commands:B.map(s=>({...s,source:"builtin"}))}}a(Z,"readNodeSnapshot");async function he(e,{cursor:t,limit:o=200}){if(!Number.isSafeInteger(o)||o<1||o>500)throw new f({error:"invalid_limit",message:"limit must be an integer from 1 through 500.",field:"limit",next:"Use a limit from 1 through 500."});if(W(e)===null)return{messages:[],messageIds:[],messageVisibility:[],nextCursor:null};const{messages:s,identified:r}=await R(e),i=t===void 0?s.length:H(t,s.length);let n=Math.max(0,i-o);for(;n>0&&typeof s[n]=="object"&&s[n]!==null&&s[n].role==="toolResult";)n--;const l=r?.slice(n,i);return{messages:l?.map(({message:u})=>u)??s.slice(n,i),...l===void 0?{}:{messageIds:l.map(({id:u})=>u)},messageVisibility:l?.map(({visibility:u})=>u)??s.slice(n,i).map(()=>"visible"),nextCursor:n===0?null:Y(n)}}a(he,"readNodeMessagesPage");function K(e){return typeof e=="string"?e:Array.isArray(e)?e.filter(t=>typeof t=="object"&&t!==null).filter(t=>t.type==="text"&&typeof t.text=="string").map(t=>t.text).join(""):""}a(K,"textFromContent");function Q(e){switch(e.role){case"user":return"You";case"assistant":return"Agent";case"toolResult":return"Tool result";default:return typeof e.role=="string"?e.role:"Message"}}a(Q,"roleLabel");function X(e){return Array.isArray(e.content)?e.content.filter(t=>typeof t=="object"&&t!==null&&t.type==="toolCall").map(t=>`Tool: ${typeof t.name=="string"?t.name:"call"}`):[]}a(X,"toolSummaries");async function ye(e){const t=g(e);if(t===null)throw new f({error:"not_found",message:`no node: ${e}`,field:"node-id",next:"List nodes with `crtr node inspect list`."});const{snapshot:o}=await Z(e),r=[`# ${T(t)}`,"",`Saved transcript \xB7 ${t.status} \xB7 ${t.lifecycle}`,""];for(const i of o.messages){if(typeof i!="object"||i===null)continue;const n=i;if(n.role==="custom"&&n.display===!1)continue;const l=K(n.content),u=typeof n.text=="string"?n.text:"",m=l.trim()?l:u.trim()?u:"",c=X(n);if(!(!m&&c.length===0)){r.push(`## ${Q(n)}`,""),m&&r.push(m,"");for(const _ of c)r.push(`- ${_}`);c.length&&r.push("")}}return r.length===5&&r.push("_No saved messages._",""),r.join(`
1
+ var C=Object.defineProperty;var a=(e,t)=>C(e,"name",{value:t,configurable:!0});import{existsSync as N,readFileSync as j}from"node:fs";import{isBeneathRefusal as F,readFileBeneath as $,readTextBeneathIfExists as x}from"../spaces/open-beneath.js";import{join as p}from"node:path";import{InputError as c}from"../io.js";import{conversationIdFromPath as y,conversationStore as w,ConversationNotFoundError as A}from"../conversation-store/index.js";import{fullName as T,getNode as g}from"../canvas/index.js";import{nodeRunDir as h,nodeRunJobDir as S,sessionPtrPath as k}from"../canvas/paths.js";import{hydratePersistedAdvertisedCommandMessages as v}from"./advertised-command-invocation.js";import{SessionManager as L}from"./broker-sdk.js";import{openModelRegistry as P}from"./model-registry.js";import{BUILTIN_SLASH_COMMANDS as B}from"./pi-vendored.js";import{cycleAwareMessages as J}from"./session-cycles.js";import{projectTranscript as O}from"./session-visibility.js";import{normalizeToolGroupSummaryRecord as E}from"../../shared/tool-groups.js";import{normalizeTurnReplyRecord as U}from"../../shared/turn-replies.js";async function V(e){if(e!==null)try{return(await P()).find(e.provider,e.modelId)}catch{return}}a(V,"resolveRecordedModel");async function b(e,t){const o=a(async i=>{const n=i?y(i):null;if(n===null)return null;try{return(await w().header(n)).path}catch(l){if(l instanceof A)return null;throw l}},"resolvePath"),s=await o(t);if(s!==null)return s;const r=k(e);return N(r)?await o(j(r,"utf8").trim()):null}a(b,"resolveSessionFile");async function W(e){const t=await g(e);if(t===null)throw new c({error:"not_found",message:`no node: ${e}`,field:"id",next:"List nodes with `crtr node inspect list`."});return await b(e,t.pi_session_file)}a(W,"readableSessionFile");function z(e,t){return{sessionFile:t,sessionId:e,userMessages:0,assistantMessages:0,toolCalls:0,toolResults:0,totalMessages:0,tokens:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0},cost:0}}a(z,"emptyStats");function D(e,t,o){const s=z(t,o);s.totalMessages=e.length;for(const r of e)if(r.role==="user")s.userMessages++;else if(r.role==="assistant"){s.assistantMessages++;const i=Array.isArray(r.content)?r.content:[];s.toolCalls+=i.filter(l=>l!==null&&typeof l=="object"&&l.type==="toolCall").length;const n=r.usage;n!==void 0&&(s.tokens.input+=n.input??0,s.tokens.output+=n.output??0,s.tokens.cacheRead+=n.cacheRead??0,s.tokens.cacheWrite+=n.cacheWrite??0,s.cost+=n.cost?.total??0)}else r.role==="toolResult"&&s.toolResults++;return s.tokens.total=s.tokens.input+s.tokens.output+s.tokens.cacheRead+s.tokens.cacheWrite,s}a(D,"statsFromMessages");async function ge(e){const t=await g(e);if(t===null)throw new c({error:"not_found",message:`no node: ${e}`,field:"id",next:"List nodes with `crtr node inspect list`."});const o=await b(e,t.pi_session_file);if(o===null)throw new c({error:"no_session",message:`node has no readable session file: ${e}`,field:"id",next:"Choose a node with captured conversation history."});return{nodeId:e,sessionFile:o,sessionJsonl:await(async()=>{const{header:s,entries:r}=await w().read(y(o));return[s,...r].map(i=>`${JSON.stringify(i)}
2
+ `).join("")})(),systemPrompt:M(e,p(S(e),"system-prompt.md"))??M(e,p(h(e),"system-prompt.md"))}}a(ge,"readNodeSession");function M(e,t){try{return $(h(e),t).toString("utf8")}catch(o){if(F(o))throw o;return null}}a(M,"readRunFileIfPresent");function G(e){try{const t=x(h(e),p(S(e),"tool-summaries.json"));return E(t===null?null:JSON.parse(t))}catch{return{}}}a(G,"readToolGroupSummaries");function q(e){try{const t=x(h(e),p(S(e),"turn-replies.json"));return U(t===null?null:JSON.parse(t))}catch{return{}}}a(q,"readTurnReplies");async function R(e){const t=await g(e);if(t===null)throw new c({error:"not_found",message:`no node: ${e}`,field:"id",next:"List nodes with `crtr node inspect list`."});const o=await b(e,t.pi_session_file);if(o===null)throw new c({error:"no_session",message:`node has no readable session file: ${e}`,field:"id",next:"Choose a node with captured conversation history."});const{header:s,entries:r}=await w().read(y(o)),i=L.inMemory(s.cwd,void 0,[s,...r]),n=i.buildSessionContext();v(n.messages);const l=J(i);l!==void 0&&v(l.map(({message:f})=>f));const u=l===void 0?void 0:O(l,{boundaryReviewId:t.review_binding?.review_id,sessionEntries:i.getEntries()}),m=u?.map(({message:f})=>f)??n.messages;return{sessionFile:o,messages:m,identified:u,model:n.model,thinkingLevel:n.thinkingLevel,sessionId:i.getSessionId(),sessionName:i.getSessionName()}}a(R,"reconstructTranscript");function d(){throw new c({error:"invalid_cursor",message:"cursor must be a base64url-encoded messages cursor.",field:"cursor",next:"Omit cursor to start from the newest messages."})}a(d,"invalidCursor");function H(e,t){/^[A-Za-z0-9_-]+$/u.test(e)||d();let o;try{const r=Buffer.from(e,"base64url").toString("utf8");Buffer.from(r,"utf8").toString("base64url")!==e&&d(),o=JSON.parse(r)}catch{d()}(typeof o!="object"||o===null||o.v!==1||!Number.isSafeInteger(o.before))&&d();const s=o.before;return(s<0||s>t)&&d(),s}a(H,"decodeMessagesCursor");function Y(e){return Buffer.from(JSON.stringify({v:1,before:e}),"utf8").toString("base64url")}a(Y,"encodeMessagesCursor");async function Z(e){const t=await R(e),o={messages:t.messages,...t.identified===void 0?{}:{messageIds:t.identified.map(({id:s})=>s)},messageVisibility:t.identified?.map(({visibility:s})=>s)??t.messages.map(()=>"visible"),turnVisibility:"visible",stats:D(t.messages,t.sessionId,t.sessionFile),state:{model:await V(t.model),thinkingLevel:t.thinkingLevel,isStreaming:!1,isCompacting:!1,steeringMode:"one-at-a-time",followUpMode:"one-at-a-time",sessionFile:t.sessionFile,sessionId:t.sessionId,sessionName:t.sessionName,autoCompactionEnabled:!0,messageCount:t.messages.length,pendingMessageCount:0},display:{statuses:{},widgets:{},title:void 0},queued:{steering:[],followUp:[]},toolGroupSummaries:G(e),turnReplies:q(e)};return{nodeId:e,snapshot:o,commands:B.map(s=>({...s,source:"builtin"}))}}a(Z,"readNodeSnapshot");async function he(e,{cursor:t,limit:o=200}){if(!Number.isSafeInteger(o)||o<1||o>500)throw new c({error:"invalid_limit",message:"limit must be an integer from 1 through 500.",field:"limit",next:"Use a limit from 1 through 500."});if(await W(e)===null)return{messages:[],messageIds:[],messageVisibility:[],nextCursor:null};const{messages:s,identified:r}=await R(e),i=t===void 0?s.length:H(t,s.length);let n=Math.max(0,i-o);for(;n>0&&typeof s[n]=="object"&&s[n]!==null&&s[n].role==="toolResult";)n--;const l=r?.slice(n,i);return{messages:l?.map(({message:u})=>u)??s.slice(n,i),...l===void 0?{}:{messageIds:l.map(({id:u})=>u)},messageVisibility:l?.map(({visibility:u})=>u)??s.slice(n,i).map(()=>"visible"),nextCursor:n===0?null:Y(n)}}a(he,"readNodeMessagesPage");function K(e){return typeof e=="string"?e:Array.isArray(e)?e.filter(t=>typeof t=="object"&&t!==null).filter(t=>t.type==="text"&&typeof t.text=="string").map(t=>t.text).join(""):""}a(K,"textFromContent");function Q(e){switch(e.role){case"user":return"You";case"assistant":return"Agent";case"toolResult":return"Tool result";default:return typeof e.role=="string"?e.role:"Message"}}a(Q,"roleLabel");function X(e){return Array.isArray(e.content)?e.content.filter(t=>typeof t=="object"&&t!==null&&t.type==="toolCall").map(t=>`Tool: ${typeof t.name=="string"?t.name:"call"}`):[]}a(X,"toolSummaries");async function ye(e){const t=await g(e);if(t===null)throw new c({error:"not_found",message:`no node: ${e}`,field:"node-id",next:"List nodes with `crtr node inspect list`."});const{snapshot:o}=await Z(e),r=[`# ${T(t)}`,"",`Saved transcript \xB7 ${t.status} \xB7 ${t.lifecycle}`,""];for(const i of o.messages){if(typeof i!="object"||i===null)continue;const n=i;if(n.role==="custom"&&n.display===!1)continue;const l=K(n.content),u=typeof n.text=="string"?n.text:"",m=l.trim()?l:u.trim()?u:"",f=X(n);if(!(!m&&f.length===0)){r.push(`## ${Q(n)}`,""),m&&r.push(m,"");for(const _ of f)r.push(`- ${_}`);f.length&&r.push("")}}return r.length===5&&r.push("_No saved messages._",""),r.join(`
3
3
  `)}a(ye,"transcriptMarkdown");export{he as readNodeMessagesPage,ge as readNodeSession,Z as readNodeSnapshot,ye as transcriptMarkdown};
@@ -1,5 +1,5 @@
1
- import type { DatabaseSync } from 'node:sqlite';
2
1
  import { type NodeMeta, type Mode, type Lifecycle, type LaunchSpec, type ManagedWorktree, type OutcomeDeliveryBinding, type ReviewBinding } from '../canvas/index.js';
2
+ import type { CanvasDb } from '../canvas/db.js';
3
3
  /** Explicitly set the resolved install id. crtrd calls this once at boot,
4
4
  * immediately after `resolveInstallId()` — see crtrd.ts — so a provisioning
5
5
  * mismatch fails the daemon loudly at STARTUP rather than lazily on first
@@ -15,7 +15,7 @@ export declare function newJobId(): string;
15
15
  * minted node id is a globally-unique NAME that also names the canvas that
16
16
  * minted it (see the unified-chat/addressing design's "ID scheme"). crtrd is
17
17
  * the sole node minter. */
18
- export declare function newNodeId(): string;
18
+ export declare function newNodeId(): Promise<string>;
19
19
  /** Thrown when a caller-specified `--node-id` (or its API twin `node_id`)
20
20
  * already names a live node. Distinguishable from every other spawn failure
21
21
  * so a caller can treat it as "attach instead of create" per the unified
@@ -32,13 +32,13 @@ export declare class NodeIdConflictError extends Error {
32
32
  * valid); the duplicate check is advisory only — a concurrent create can
33
33
  * still win the race between this check and the synchronous check-then-
34
34
  * create below, which remains the SOLE authoritative decider. */
35
- export declare function preflightNodeId(nodeId: string): void;
35
+ export declare function preflightNodeId(nodeId: string): Promise<void>;
36
36
  /** The root of a node's spine: walk the `parent` column up to `parent == null`.
37
37
  * Cycle-guarded (parents must not cycle, but never loop forever). Lives in the
38
38
  * node layer (not placement) so the env-builder and placement both reach it
39
39
  * without an import cycle — `CRTR_SUBTREE` is emitted as `rootOfSpine(nodeId)`
40
40
  * at every launch site. */
41
- export declare function rootOfSpine(nodeId: string): string;
41
+ export declare function rootOfSpine(nodeId: string): Promise<string>;
42
42
  export interface NodeContext {
43
43
  nodeId: string | null;
44
44
  kind: string | null;
@@ -111,7 +111,7 @@ export interface SpawnNodeOpts {
111
111
  /** Run identity set on an app root; managed children inherit it. */
112
112
  run?: Pick<NodeMeta, 'grantee' | 'sub' | 'grant_id' | 'client_id' | 'metadata_json' | 'run_id' | 'event_cursor' | 'usage_json'>;
113
113
  /** Additional rows committed atomically with the newborn node. */
114
- withinCreate?: (db: DatabaseSync, row: NodeMeta) => void;
114
+ withinCreate?: (db: CanvasDb, row: NodeMeta) => Promise<void> | void;
115
115
  /** Managed worktree already created for this node, if any. */
116
116
  managedWorktree?: ManagedWorktree;
117
117
  /** Absolute wall-clock deadline persisted with the row at birth. */
@@ -129,7 +129,7 @@ export interface SpawnNodeOpts {
129
129
  nodeId?: string;
130
130
  }
131
131
  /** The node that owns the conversation a fork copies, or null when no node does. */
132
- export declare function forkSourceNode(sourceFile: string): NodeMeta | null;
132
+ export declare function forkSourceNode(sourceFile: string): Promise<NodeMeta | null>;
133
133
  /** Create a node on the canvas and wire its spawn-time edges.
134
134
  *
135
135
  * For a child (parent given): the parent auto-subscribes ACTIVE to the child
@@ -1 +1 @@
1
- var J=Object.defineProperty;var a=(e,t)=>J(e,"name",{value:t,configurable:!0});import{envHomeOverride as K,envRuntimeHomeOverride as X,INBOX_BETWEEN_TURNS_ENV as z,SCOPES_FILE_ENV as V,scopeAllowed as C}from"../../shared/env.js";import{isOwnMemoryScope as Y,validateScopes as Q}from"../scopes.js";import{activeGrant as B,terminalGrant as k}from"../grants/mirror.js";import{grantSnapshotMissing as Z}from"../../daemon/readiness.js";import{appendRunEvent as ee}from"../runs/events.js";import{readConfig as S}from"../config.js";import{InputError as T}from"../io.js";import{ApiError as w}from"../../api/errors.js";import{assertGranteeRunsHere as ne}from"./unsandboxed.js";import{randomBytes as re}from"node:crypto";import{existsSync as P}from"node:fs";import{resolve as te,relative as ie,isAbsolute as H,join as oe,sep as le}from"node:path";import{appSpace as ae}from"../layout.js";import{scopesFilePath as se}from"../canvas/paths.js";import{createNode as de,assertRunNotDeleting as ue,conversationOwner as ce,getNode as c,getRow as fe}from"../canvas/index.js";import{ensureAppSpace as pe}from"../spaces/space.js";import{LAUNCHER_SOCKET as L}from"../../launcher/spec.js";import{resolveInstallId as me}from"../canvas/install-id.js";import{isAppRun as _e}from"../canvas/app-run.js";import{canvasDbPath as ge,contextDir as we}from"../canvas/paths.js";import{conversationIdFromPath as he}from"../conversation-store/index.js";import{usage as U}from"../errors.js";import{assertProfileAvailableForBirth as ve}from"../profiles/deletion-reservation.js";import{loadExactProfileManifest as Re}from"../profiles/manifest.js";import{admitNodeCreate as Ee}from"../command-hooks/lifecycle-create.js";import{getById as ye,nodeObject as I,ownerForGrantee as Ce}from"../graph/objects.js";import{recordActedOn as Ie}from"../graph/edges.js";import{recordWatch as Ne,copyWatchesForFork as ke}from"../graph/watches.js";import{publish as Se}from"../graph/events.js";let O;const j=new Map;function pn(e){O=e}a(pn,"setInstallId");function Te(){if(O!==void 0)return O;const e=ge(),t=j.get(e);if(t!==void 0)return t;const o=me();return j.set(e,o),o}a(Te,"installId");function Oe(){return`${Date.now().toString(36)}-${re(4).toString("hex")}`}a(Oe,"newJobId");function xe(){return`${Te()}-${Oe()}`}a(xe,"newNodeId");const x=128,De=/^[a-z0-9-]+$/;class q extends Error{static{a(this,"NodeIdConflictError")}nodeId;constructor(t){super(`node already exists: ${t}`),this.nodeId=t,this.name="NodeIdConflictError"}}function D(e){if(e.length===0||e.length>x)throw U(`invalid --node-id '${e}': must be 1-${x} characters`,{next:`Pass an id-safe string (lowercase letters, digits, hyphens) of at most ${x} characters.`});if(!De.test(e))throw U(`invalid --node-id '${e}': must contain only lowercase letters, digits, and hyphens (e.g. 'remote42', 'my-node-1')`,{next:"Use only lowercase letters, digits, and hyphens."})}a(D,"validateNodeIdFormat");function mn(e){if(D(e),c(e)!==null)throw new q(e)}a(mn,"preflightNodeId");function be(e){if(D(e),c(e)!==null)throw new q(e);return e}a(be,"validatedExplicitNodeId");function _n(e){let t=e;const o=new Set;for(;;){if(o.has(t))return t;o.add(t);const s=fe(t);if(s===null||s.parent==null)return t;t=s.parent}}a(_n,"rootOfSpine");function gn(){const e=process.env;return{nodeId:e.CRTR_NODE_ID??null,kind:e.CRTR_KIND??null,mode:e.CRTR_MODE??null}}a(gn,"currentNodeContext");function Ae(e){return _e(e)}a(Ae,"inboxBetweenTurns");function wn(e){const t={CRTR_NODE_ID:e.node_id,CRTR_KIND:e.kind,CRTR_MODE:e.mode,CRTR_LIFECYCLE:e.lifecycle,CRTR_NODE_CWD:e.cwd,CRTR_CONTEXT_DIR:we(e.node_id,e.grantee),CRTR_CYCLES:(e.cycles??0).toString(),CRTR_PROFILE_ID:e.profile_id??"",PI_CLAUDE_OAUTH_REINJECT_SCOPE:"never"};e.parent&&(t.CRTR_PARENT_NODE_ID=e.parent),e.run_id&&(t.CRTR_RUN_ID=e.run_id),Ae(e)&&(t[z]="1"),e.scopes!==null&&e.scopes!==void 0&&(t[V]=se(e.node_id)),t.CRTR_GRANTEE=e.grantee??"app:terminal";const o=K();o!==void 0&&o!==""&&(t.CRTR_HOME=o);const s=X();s!==void 0&&s!==""&&(t.CRTR_RUNTIME_HOME=s);const f=process.env.CRTR_SUBTREE;return f!==void 0&&f!==""&&(t.CRTR_SUBTREE=f),{...t,...e.launch?.env??{}}}a(wn,"nodeEnv");function Me(e){const t=he(e),o=t===null?null:ce(t);return o===null?null:c(o)}a(Me,"forkSourceNode");async function hn(e){const t=e.nodeId!==void 0?(D(e.nodeId),e.nodeId):xe(),o=e.parent??null,s=o===null,f=e.spawnedBy??o,m=e.creator??null,b=e.mode??"base",N=e.lifecycle??(s?"resident":"terminal"),h=e.run===void 0?k():null,n={node_id:t,name:e.name??e.kind,description:e.description,cycles:0,created:new Date().toISOString(),cwd:e.cwd,host_kind:"broker",profile_id:e.profile_id??null,kind:e.kind,mode:b,lifecycle:N,persona_ack:{kind:e.kind,mode:b,lifecycle:N},status:"active",parent:o,spawned_by:f,creator:m,fork_from:e.forkFrom,fork_source_file:e.forkSourceFile,review_binding:e.reviewBinding,model_override:e.modelOverride??null,scopes:e.scopes??null,isolated:e.isolated===!0,grantee:e.run?.grantee??"app:terminal",sub:e.run?.sub??h?.sub??null,grant_id:e.run?.grant_id??h?.id??null,client_id:e.run?.client_id??null,metadata_json:s?e.run?.metadata_json??null:null,run_id:s?t:e.run?.run_id??null,event_cursor:s?e.run?.event_cursor??1:null,usage_json:s?e.run?.usage_json??JSON.stringify({input_tokens:0,output_tokens:0,cache_read_tokens:0,cache_write_tokens:0,cost_usd:0}):null,passive_default:e.passiveDefault??!1,...e.managedWorktree!==void 0?{managed_worktree:e.managedWorktree}:{},intent:null,deadline_at:e.deadlineAt??null,pi_session_id:null,pi_session_file:null,launch:e.launch},E=e.scopes===void 0?void 0:Q(e.scopes),v=o===null?null:c(o);if(o!==null&&v===null)throw new Error(`cannot spawn under unknown parent node: ${o}`);if(v?.run_id&&c(v.run_id)?.deleting_at)throw new Error("run is deleting");const u=m===null?null:c(m);if(m!==null&&u===null)throw new Error(`cannot spawn from unknown creator node: ${m}`);if(u?.run_id&&c(u.run_id)?.deleting_at)throw new Error("run is deleting");const A=e.forkSourceFile==null?null:Me(e.forkSourceFile),M=e.replaces==null?null:c(e.replaces),_=v??A??M??u??(f===null?null:c(f)),$=[v,u,A,M,f===null?null:c(f)].some(r=>r?.isolated===!0||r?.run_id!=null&&c(r.run_id)?.isolated===!0);if($&&e.isolated===!1)throw new w(403,"isolated_run","isolation cannot be turned off under an isolated run",{param:"isolated"});if(n.isolated=$||e.isolated===!0,_!==null){const r=u??_;if(u&&_.grantee&&u.grantee&&u.grantee!==_.grantee)throw new w(403,"other_app_run","cannot create under another app's node");const i=u&&u!==_?[_,u]:[_],d=[],g=new Set;for(const l of i){l.scopes!==null&&l.scopes!==void 0&&d.push(l.scopes);const p=l.grantee==="app:terminal"?k():l.grant_id?B(l.grant_id):null;if(p){const R=[...p.resolved];g.add(R),d.push(R)}else if(!(l.grantee==="app:terminal"&&!S("user").runtime?.issuer)){const R=[];g.add(R),d.push(R)}}const y=a(l=>Y(l,r.grantee==="user:local"?"app:terminal":r.grantee??"app:terminal"),"ownMemory"),F=a((l,p)=>y(p)&&g.has(l)||C(l,p),"allowed");if(E!==void 0&&!E.every(l=>d.every(p=>F(p,l))))throw new T({error:"unknown_scope",message:"child scopes must be covered by the creating node, its source and their current grants",received:E,field:"scopes",next:"Request only scopes the creating node currently holds."});if(n.scopes=E??(i.every(l=>l.scopes==null)&&i.every(l=>l.grant_id===r.grant_id&&l.sub===r.sub)?null:i.length===1?_.scopes??null:[...new Set(d.flat().filter(l=>d.every(p=>F(p,l))))]),n.scopes?.includes("crtr:act")&&!C(n.scopes,"crtr:llm"))throw new T({error:"invalid_scope",message:"crtr:act requires crtr:llm",received:n.scopes,field:"scopes",next:"Include crtr:llm or omit crtr:act."});n.grantee=r.grantee==="user:local"?"app:terminal":r.grantee,n.sub=r.sub??(n.grantee==="app:terminal"?h?.sub:null)??null,n.grant_id=r.grant_id??(n.grantee==="app:terminal"?h?.id:null)??null,n.client_id=r.client_id,n.run_id=s?t:r.run_id??null}if(ne(n.grantee),e.run===void 0&&n.grantee==="app:terminal"&&S("user").runtime?.issuer&&h===null)throw Z()?new w(503,"runtime_starting","the first grant snapshot from the directory has not committed"):new w(403,"scope_missing","terminal grant is not active");if(n.isolated){if(process.platform!=="linux"||!P(L))throw new w(400,"isolated_unavailable","isolated nodes require the Linux root launcher");if(e.managedWorktree!==void 0)throw new w(400,"invalid_request","isolated nodes cannot use a worktree",{param:"worktree"});const r=oe(ae(n.grantee??"app:terminal").nodes,t),i=ie(r,te(n.cwd));if(!H(n.cwd)||i===".."||i.startsWith(`..${le}`)||H(i))throw new w(400,"invalid_request","isolated node cwd must be inside its own folder",{param:"cwd"})}if(n.profile_id){const r=Re(n.profile_id).manifest.grantee??"app:terminal";if(r!==n.grantee){const i=`crtr:memory:rw:${r}:profile:${n.profile_id}`,d=n.grantee==="app:terminal"?k():n.grant_id?B(n.grant_id):null;if(!(n.grantee==="app:terminal"&&!S("user").runtime?.issuer)&&(!d||d.grantee!==n.grantee||!C(d.resolved,i))||!C(n.scopes,i))throw new T({error:"scope_missing",message:`missing scope ${i}`,received:n.profile_id,field:"profile",next:"Select a profile covered by this run and its current grant."})}}if(ve(n.profile_id??null),!n.grantee)throw new Error("node creation requires an app");const W=await Ee({kind:n.kind,mode:n.mode,cwd:n.cwd,profile:n.profile_id??null,root:s,parentId:o,requestingNodeId:m,lifecycle:N,replaces:e.replaces??null},n.grantee),G=a((r,i)=>{const d=I(r,i.node_id),g=m??o??e.actor??f??null,y=g!==null&&ye(r,g)?.type==="node"?I(r,g):Ce(r,e.run===void 0?"user:local":i.grantee);Ie(r,y,d),o!==null&&e.subscribe!==!1&&Ne(r,I(r,o),d,"spawn"),e.forkSourceNode&&ke(r,I(r,e.forkSourceNode),d),Se(r,{event:"created",object:d,actor:y,attrs:{name:i.name,kind:i.kind,creator:m??null}})},"recordBirth");try{e.nodeId!==void 0&&be(e.nodeId),await e.beforeCreate?.(),(process.platform!=="linux"||P(L))&&await pe(n.grantee??"app:terminal"),de(n,{outcomeDelivery:e.outcomeDelivery,withinCreate:a((r,i)=>{i.run_id&&i.run_id!==i.node_id&&ue(r,i.run_id),s&&e.run===void 0&&ee(r,t,t,"run.started",{scopes:i.scopes??null,payer:"user",usage:JSON.parse(i.usage_json)}),e.withinCreate?.(r,i),G(r,i)},"withinCreate")})}finally{W()}return n}a(hn,"spawnNode");export{q as NodeIdConflictError,gn as currentNodeContext,Me as forkSourceNode,Ae as inboxBetweenTurns,Oe as newJobId,xe as newNodeId,wn as nodeEnv,mn as preflightNodeId,_n as rootOfSpine,pn as setInstallId,hn as spawnNode};
1
+ var K=Object.defineProperty;var l=(e,t)=>K(e,"name",{value:t,configurable:!0});import{envHomeOverride as X,envRuntimeHomeOverride as z,INBOX_BETWEEN_TURNS_ENV as V,SCOPES_FILE_ENV as Y,scopeAllowed as C}from"../../shared/env.js";import{isOwnMemoryScope as Q,validateScopes as Z}from"../scopes.js";import{activeGrant as B,terminalGrant as k}from"../grants/mirror.js";import{grantSnapshotMissing as ee}from"../../daemon/readiness.js";import{appendRunEvent as ne}from"../runs/events.js";import{readConfig as S}from"../config.js";import{InputError as T}from"../io.js";import{ApiError as g}from"../../api/errors.js";import{assertGranteeRunsHere as re}from"./unsandboxed.js";import{randomBytes as te}from"node:crypto";import{existsSync as P}from"node:fs";import{resolve as ie,relative as ae,isAbsolute as H,join as oe,sep as le}from"node:path";import{appSpace as se}from"../layout.js";import{scopesFilePath as de}from"../canvas/paths.js";import{createNode as ce,assertRunNotDeleting as ue,conversationOwner as fe,getNode as u,getRow as pe}from"../canvas/index.js";import{ensureAppSpace as me}from"../spaces/space.js";import{LAUNCHER_SOCKET as L}from"../../launcher/spec.js";import{resolveInstallId as _e}from"../canvas/install-id.js";import{isAppRun as we}from"../canvas/app-run.js";import{canvasDbPath as ge,contextDir as he}from"../canvas/paths.js";import{conversationIdFromPath as ve}from"../conversation-store/index.js";import{usage as U}from"../errors.js";import{assertProfileAvailableForBirth as Re}from"../profiles/deletion-reservation.js";import{loadExactProfileManifest as ye}from"../profiles/manifest.js";import{admitNodeCreate as Ee}from"../command-hooks/lifecycle-create.js";import{getById as Ce,nodeObject as I,ownerForGrantee as Ie}from"../graph/objects.js";import{recordActedOn as Ne}from"../graph/edges.js";import{recordWatch as ke,copyWatchesForFork as Se}from"../graph/watches.js";import{publish as Te}from"../graph/events.js";import{someAsync as Oe}from"../async-array.js";let O;const j=new Map;function _n(e){O=e}l(_n,"setInstallId");async function xe(){if(O!==void 0)return O;const e=ge(),t=j.get(e);if(t!==void 0)return t;const a=await _e();return j.set(e,a),a}l(xe,"installId");function De(){return`${Date.now().toString(36)}-${te(4).toString("hex")}`}l(De,"newJobId");async function be(){return`${await xe()}-${De()}`}l(be,"newNodeId");const x=128,Ae=/^[a-z0-9-]+$/;class q extends Error{static{l(this,"NodeIdConflictError")}nodeId;constructor(t){super(`node already exists: ${t}`),this.nodeId=t,this.name="NodeIdConflictError"}}function D(e){if(e.length===0||e.length>x)throw U(`invalid --node-id '${e}': must be 1-${x} characters`,{next:`Pass an id-safe string (lowercase letters, digits, hyphens) of at most ${x} characters.`});if(!Ae.test(e))throw U(`invalid --node-id '${e}': must contain only lowercase letters, digits, and hyphens (e.g. 'remote42', 'my-node-1')`,{next:"Use only lowercase letters, digits, and hyphens."})}l(D,"validateNodeIdFormat");async function wn(e){if(D(e),await u(e)!==null)throw new q(e)}l(wn,"preflightNodeId");async function Me(e){if(D(e),await u(e)!==null)throw new q(e);return e}l(Me,"validatedExplicitNodeId");async function gn(e){let t=e;const a=new Set;for(;;){if(a.has(t))return t;a.add(t);const s=await pe(t);if(s===null||s.parent==null)return t;t=s.parent}}l(gn,"rootOfSpine");function hn(){const e=process.env;return{nodeId:e.CRTR_NODE_ID??null,kind:e.CRTR_KIND??null,mode:e.CRTR_MODE??null}}l(hn,"currentNodeContext");function $e(e){return we(e)}l($e,"inboxBetweenTurns");function vn(e){const t={CRTR_NODE_ID:e.node_id,CRTR_KIND:e.kind,CRTR_MODE:e.mode,CRTR_LIFECYCLE:e.lifecycle,CRTR_NODE_CWD:e.cwd,CRTR_CONTEXT_DIR:he(e.node_id,e.grantee),CRTR_CYCLES:(e.cycles??0).toString(),CRTR_PROFILE_ID:e.profile_id??"",PI_CLAUDE_OAUTH_REINJECT_SCOPE:"never"};e.parent&&(t.CRTR_PARENT_NODE_ID=e.parent),e.run_id&&(t.CRTR_RUN_ID=e.run_id),$e(e)&&(t[V]="1"),e.scopes!==null&&e.scopes!==void 0&&(t[Y]=de(e.node_id)),t.CRTR_GRANTEE=e.grantee??"app:terminal";const a=X();a!==void 0&&a!==""&&(t.CRTR_HOME=a);const s=z();s!==void 0&&s!==""&&(t.CRTR_RUNTIME_HOME=s);const f=process.env.CRTR_SUBTREE;return f!==void 0&&f!==""&&(t.CRTR_SUBTREE=f),{...t,...e.launch?.env??{}}}l(vn,"nodeEnv");async function Fe(e){const t=ve(e),a=t===null?null:await fe(t);return a===null?null:await u(a)}l(Fe,"forkSourceNode");async function Rn(e){const t=e.nodeId!==void 0?(D(e.nodeId),e.nodeId):await be(),a=e.parent??null,s=a===null,f=e.spawnedBy??a,m=e.creator??null,b=e.mode??"base",N=e.lifecycle??(s?"resident":"terminal"),h=e.run===void 0?await k():null,n={node_id:t,name:e.name??e.kind,description:e.description,cycles:0,created:new Date().toISOString(),cwd:e.cwd,host_kind:"broker",profile_id:e.profile_id??null,kind:e.kind,mode:b,lifecycle:N,persona_ack:{kind:e.kind,mode:b,lifecycle:N},status:"active",parent:a,spawned_by:f,creator:m,fork_from:e.forkFrom,fork_source_file:e.forkSourceFile,review_binding:e.reviewBinding,model_override:e.modelOverride??null,scopes:e.scopes??null,isolated:e.isolated===!0,grantee:e.run?.grantee??"app:terminal",sub:e.run?.sub??h?.sub??null,grant_id:e.run?.grant_id??h?.id??null,client_id:e.run?.client_id??null,metadata_json:s?e.run?.metadata_json??null:null,run_id:s?t:e.run?.run_id??null,event_cursor:s?e.run?.event_cursor??1:null,usage_json:s?e.run?.usage_json??JSON.stringify({input_tokens:0,output_tokens:0,cache_read_tokens:0,cache_write_tokens:0,cost_usd:0}):null,passive_default:e.passiveDefault??!1,...e.managedWorktree!==void 0?{managed_worktree:e.managedWorktree}:{},intent:null,deadline_at:e.deadlineAt??null,pi_session_id:null,pi_session_file:null,launch:e.launch},y=e.scopes===void 0?void 0:Z(e.scopes),v=a===null?null:await u(a);if(a!==null&&v===null)throw new Error(`cannot spawn under unknown parent node: ${a}`);if(v?.run_id&&(await u(v.run_id))?.deleting_at)throw new Error("run is deleting");const c=m===null?null:await u(m);if(m!==null&&c===null)throw new Error(`cannot spawn from unknown creator node: ${m}`);if(c?.run_id&&(await u(c.run_id))?.deleting_at)throw new Error("run is deleting");const A=e.forkSourceFile==null?null:await Fe(e.forkSourceFile),M=e.replaces==null?null:await u(e.replaces),_=v??A??M??c??(f===null?null:await u(f)),W=[v,c,A,M,f===null?null:await u(f)],$=await Oe(W,async r=>r?.isolated===!0||r?.run_id!=null&&(await u(r.run_id))?.isolated===!0);if($&&e.isolated===!1)throw new g(403,"isolated_run","isolation cannot be turned off under an isolated run",{param:"isolated"});if(n.isolated=$||e.isolated===!0,_!==null){const r=c??_;if(c&&_.grantee&&c.grantee&&c.grantee!==_.grantee)throw new g(403,"other_app_run","cannot create under another app's node");const i=c&&c!==_?[_,c]:[_],d=[],w=new Set;for(const o of i){o.scopes!==null&&o.scopes!==void 0&&d.push(o.scopes);const p=o.grantee==="app:terminal"?await k():o.grant_id?await B(o.grant_id):null;if(p){const R=[...p.resolved];w.add(R),d.push(R)}else if(!(o.grantee==="app:terminal"&&!S("user").runtime?.issuer)){const R=[];w.add(R),d.push(R)}}const E=l(o=>Q(o,r.grantee==="user:local"?"app:terminal":r.grantee??"app:terminal"),"ownMemory"),F=l((o,p)=>E(p)&&w.has(o)||C(o,p),"allowed");if(y!==void 0&&!y.every(o=>d.every(p=>F(p,o))))throw new T({error:"unknown_scope",message:"child scopes must be covered by the creating node, its source and their current grants",received:y,field:"scopes",next:"Request only scopes the creating node currently holds."});if(n.scopes=y??(i.every(o=>o.scopes==null)&&i.every(o=>o.grant_id===r.grant_id&&o.sub===r.sub)?null:i.length===1?_.scopes??null:[...new Set(d.flat().filter(o=>d.every(p=>F(p,o))))]),n.scopes?.includes("crtr:act")&&!C(n.scopes,"crtr:llm"))throw new T({error:"invalid_scope",message:"crtr:act requires crtr:llm",received:n.scopes,field:"scopes",next:"Include crtr:llm or omit crtr:act."});n.grantee=r.grantee==="user:local"?"app:terminal":r.grantee,n.sub=r.sub??(n.grantee==="app:terminal"?h?.sub:null)??null,n.grant_id=r.grant_id??(n.grantee==="app:terminal"?h?.id:null)??null,n.client_id=r.client_id,n.run_id=s?t:r.run_id??null}if(re(n.grantee),e.run===void 0&&n.grantee==="app:terminal"&&S("user").runtime?.issuer&&h===null)throw await ee()?new g(503,"runtime_starting","the first grant snapshot from the directory has not committed"):new g(403,"scope_missing","terminal grant is not active");if(n.isolated){if(process.platform!=="linux"||!P(L))throw new g(400,"isolated_unavailable","isolated nodes require the Linux root launcher");if(e.managedWorktree!==void 0)throw new g(400,"invalid_request","isolated nodes cannot use a worktree",{param:"worktree"});const r=oe(se(n.grantee??"app:terminal").nodes,t),i=ae(r,ie(n.cwd));if(!H(n.cwd)||i===".."||i.startsWith(`..${le}`)||H(i))throw new g(400,"invalid_request","isolated node cwd must be inside its own folder",{param:"cwd"})}if(n.profile_id){const r=ye(n.profile_id).manifest.grantee??"app:terminal";if(r!==n.grantee){const i=`crtr:memory:rw:${r}:profile:${n.profile_id}`,d=n.grantee==="app:terminal"?await k():n.grant_id?await B(n.grant_id):null;if(!(n.grantee==="app:terminal"&&!S("user").runtime?.issuer)&&(!d||d.grantee!==n.grantee||!C(d.resolved,i))||!C(n.scopes,i))throw new T({error:"scope_missing",message:`missing scope ${i}`,received:n.profile_id,field:"profile",next:"Select a profile covered by this run and its current grant."})}}if(Re(n.profile_id??null),!n.grantee)throw new Error("node creation requires an app");const G=await Ee({kind:n.kind,mode:n.mode,cwd:n.cwd,profile:n.profile_id??null,root:s,parentId:a,requestingNodeId:m,lifecycle:N,replaces:e.replaces??null},n.grantee),J=l(async(r,i)=>{const d=await I(r,i.node_id),w=m??a??e.actor??f??null,E=w!==null&&(await Ce(r,w))?.type==="node"?await I(r,w):await Ie(r,e.run===void 0?"user:local":i.grantee);await Ne(r,E,d),a!==null&&e.subscribe!==!1&&await ke(r,await I(r,a),d,"spawn"),e.forkSourceNode&&await Se(r,await I(r,e.forkSourceNode),d),await Te(r,{event:"created",object:d,actor:E,attrs:{name:i.name,kind:i.kind,creator:m??null}})},"recordBirth");try{e.nodeId!==void 0&&await Me(e.nodeId),await e.beforeCreate?.(),(process.platform!=="linux"||P(L))&&await me(n.grantee??"app:terminal"),await ce(n,{outcomeDelivery:e.outcomeDelivery,withinCreate:l(async(r,i)=>{i.run_id&&i.run_id!==i.node_id&&await ue(r,i.run_id),s&&e.run===void 0&&await ne(r,t,t,"run.started",{scopes:i.scopes??null,payer:"user",usage:JSON.parse(i.usage_json)}),await e.withinCreate?.(r,i),await J(r,i)},"withinCreate")})}finally{G()}return n}l(Rn,"spawnNode");export{q as NodeIdConflictError,hn as currentNodeContext,Fe as forkSourceNode,$e as inboxBetweenTurns,De as newJobId,be as newNodeId,vn as nodeEnv,wn as preflightNodeId,gn as rootOfSpine,_n as setInstallId,Rn as spawnNode};
@@ -56,4 +56,4 @@ export declare function composeNodeOutcomeDocument(args: {
56
56
  finalReport?: string | null;
57
57
  /** Lets the outcome transaction supply a parsed result without a second read. */
58
58
  structuredResult?: unknown;
59
- }): NodeOutcomeDocumentV1;
59
+ }): Promise<NodeOutcomeDocumentV1>;
@@ -1 +1 @@
1
- var a=Object.defineProperty;var s=(t,e)=>a(t,"name",{value:e,configurable:!0});import{contextDir as f}from"../canvas/node-agent-paths.js";import{readOutputResult as m}from"./structured-output.js";const p=256*1024;function y(t,e){try{return m(t,e)}catch{return}}s(y,"structuredResult");function _(t){if(t===null)return null;try{return JSON.parse(t)}catch{return null}}s(_,"parseDetail");function c(t){if(Buffer.byteLength(t,"utf8")<=1024)return t;const n="\u2026";let r=Buffer.byteLength(n,"utf8"),l="";for(const i of t){const d=Buffer.byteLength(i,"utf8");if(r+d>1024)break;r+=d,l+=i}return`${l}${n}`}s(c,"truncateDescription");function k(t){const{node:e,outcome:n}=t,r=_(n.detailJson),l=t.finalReport??e.final_report??"",i=c(e.name),d=e.description===void 0?void 0:c(e.description),o=n.kind==="result"?t.structuredResult===void 0?y(e.node_id,e.grantee):t.structuredResult:void 0,u={schema:"crtr.node-outcome/v1",outcomeId:`${e.node_id}:${n.revision}`,nodeId:e.node_id,revision:n.revision,kind:n.kind,reason:n.reason,settledAt:n.at,node:{name:i,...d===void 0?{}:{description:d},kind:e.kind,mode:e.mode,lifecycle:e.lifecycle,status:e.status,terminalReason:e.terminal_reason??null,cwd:e.cwd,createdAt:e.created,parent:e.parent??null,spawnedBy:e.spawned_by??null},...n.kind==="result"?{result:{finalReport:{name:`${e.node_id}/${l}`},...o===void 0?{}:{structuredResult:o}}}:{failure:{message:r?.message??null,faultKind:r?.fault_kind??null,errorClass:r?.error_class??null,respawnFailures:r?.respawn_failures??null,deadline:r?.deadline===void 0?null:{deadlineAt:r.deadline.deadline_at,elapsedMs:r.deadline.elapsed_ms},declined:r?.declined??null}}};return Buffer.byteLength(JSON.stringify(u),"utf8")>p&&u.result?.structuredResult!==void 0&&(delete u.result.structuredResult,u.result.structuredResultOmitted=!0,u.result.structuredResultPath=`${f(e.node_id,e.grantee)}/result.json`),u}s(k,"composeNodeOutcomeDocument");export{k as composeNodeOutcomeDocument};
1
+ var c=Object.defineProperty;var s=(t,e)=>c(t,"name",{value:e,configurable:!0});import{contextDir as f}from"../canvas/node-agent-paths.js";import{readOutputResult as m}from"./structured-output.js";const p=256*1024;function y(t,e){try{return m(t,e)}catch{return}}s(y,"structuredResult");function _(t){if(t===null)return null;try{return JSON.parse(t)}catch{return null}}s(_,"parseDetail");function a(t){if(Buffer.byteLength(t,"utf8")<=1024)return t;const n="\u2026";let r=Buffer.byteLength(n,"utf8"),l="";for(const i of t){const d=Buffer.byteLength(i,"utf8");if(r+d>1024)break;r+=d,l+=i}return`${l}${n}`}s(a,"truncateDescription");async function k(t){const{node:e,outcome:n}=t,r=_(n.detailJson),l=t.finalReport??e.final_report??"",i=a(e.name),d=e.description===void 0?void 0:a(e.description),o=n.kind==="result"?t.structuredResult===void 0?y(e.node_id,e.grantee):t.structuredResult:void 0,u={schema:"crtr.node-outcome/v1",outcomeId:`${e.node_id}:${n.revision}`,nodeId:e.node_id,revision:n.revision,kind:n.kind,reason:n.reason,settledAt:n.at,node:{name:i,...d===void 0?{}:{description:d},kind:e.kind,mode:e.mode,lifecycle:e.lifecycle,status:e.status,terminalReason:e.terminal_reason??null,cwd:e.cwd,createdAt:e.created,parent:e.parent??null,spawnedBy:e.spawned_by??null},...n.kind==="result"?{result:{finalReport:{name:`${e.node_id}/${l}`},...o===void 0?{}:{structuredResult:o}}}:{failure:{message:r?.message??null,faultKind:r?.fault_kind??null,errorClass:r?.error_class??null,respawnFailures:r?.respawn_failures??null,deadline:r?.deadline===void 0?null:{deadlineAt:r.deadline.deadline_at,elapsedMs:r.deadline.elapsed_ms},declined:r?.declined??null}}};return Buffer.byteLength(JSON.stringify(u),"utf8")>p&&u.result?.structuredResult!==void 0&&(delete u.result.structuredResult,u.result.structuredResultOmitted=!0,u.result.structuredResultPath=`${await f(e.node_id,e.grantee)}/result.json`),u}s(k,"composeNodeOutcomeDocument");export{k as composeNodeOutcomeDocument};
@@ -12,10 +12,10 @@ export interface PersonaDriftResult {
12
12
  guidance: string;
13
13
  }
14
14
  /** Build only the non-document framing for a fresh-context transition. */
15
- export declare function transitionGuidance(nodeId: string, from: Persona, to: Persona): string;
15
+ export declare function transitionGuidance(nodeId: string, from: Persona, to: Persona): Promise<string>;
16
16
  /** Compare the live persona with the last acknowledged context delivery.
17
17
  * `guidance` contains only fresh-context framing; current snapshots supply its
18
18
  * documents. An absent or pre-kind acknowledgment cannot fabricate drift. */
19
- export declare function personaDrift(nodeId: string): PersonaDriftResult | null;
19
+ export declare function personaDrift(nodeId: string): Promise<PersonaDriftResult | null>;
20
20
  /** Commit the persona state whose context delivery is complete. */
21
- export declare function commitPersonaAck(nodeId: string, to: Persona): void;
21
+ export declare function commitPersonaAck(nodeId: string, to: Persona): Promise<void>;