@north-light/cli 0.3.560 → 0.3.562

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 (573) hide show
  1. package/dist/api/client.d.ts +27 -4
  2. package/dist/api/client.js +3 -3
  3. package/dist/api/contract.d.ts +1 -1
  4. package/dist/api/contract.js +1 -1
  5. package/dist/api/dto/bash-jobs.d.ts +5 -1
  6. package/dist/api/dto/broker-ops.d.ts +25 -1
  7. package/dist/api/dto/charges.d.ts +9 -2
  8. package/dist/api/dto/delivery.d.ts +26 -2
  9. package/dist/api/dto/execution-start.d.ts +57 -0
  10. package/dist/api/dto/execution-start.js +0 -0
  11. package/dist/api/dto/modelauth.d.ts +5 -0
  12. package/dist/api/dto/node-records.d.ts +16 -0
  13. package/dist/api/dto/objects.d.ts +1 -1
  14. package/dist/api/dto/reports.d.ts +0 -3
  15. package/dist/api/dto/run-events.d.ts +7 -1
  16. package/dist/api/dto/settings.d.ts +55 -0
  17. package/dist/api/dto/settings.js +0 -0
  18. package/dist/api/index.d.ts +2 -0
  19. package/dist/api/index.js +1 -1
  20. package/dist/api/routes.d.ts +11 -0
  21. package/dist/api/routes.js +1 -1
  22. package/dist/builtin-memory/crouter-sdk/release-notes.md +4 -0
  23. package/dist/cli.js +7 -7
  24. package/dist/clients/attach/chrome/bash-jobs.d.ts +11 -1
  25. package/dist/clients/attach/chrome/bash-jobs.js +1 -1
  26. package/dist/clients/attach/chrome/canvas-panels.d.ts +1 -1
  27. package/dist/clients/attach/chrome/roster.js +6 -4
  28. package/dist/clients/attach/overlays/auth.js +2 -2
  29. package/dist/clients/attach/render/chat-view.js +1 -1
  30. package/dist/clients/attach/viewer.js +550 -567
  31. package/dist/commands/canvas-config.js +2 -2
  32. package/dist/commands/canvas-use.js +1 -1
  33. package/dist/commands/human.js +2 -2
  34. package/dist/commands/node/bash.js +3 -3
  35. package/dist/commands/node/create.js +2 -2
  36. package/dist/commands/person-settings.d.ts +1 -0
  37. package/dist/commands/person-settings.js +1 -0
  38. package/dist/commands/pkg/market-manage.d.ts +2 -2
  39. package/dist/commands/pkg/market-manage.js +1 -1
  40. package/dist/commands/pkg/plugin-manage.js +13 -13
  41. package/dist/commands/pkg/shared.js +1 -1
  42. package/dist/commands/profile/default.js +1 -1
  43. package/dist/commands/push.js +2 -3
  44. package/dist/commands/sys/config.js +1 -1
  45. package/dist/commands/sys/connect.js +1 -1
  46. package/dist/commands/sys/context/sysprompt.js +2 -2
  47. package/dist/commands/sys/doctor.js +1 -1
  48. package/dist/commands/sys/panels/broker-limits-panel.js +1 -1
  49. package/dist/commands/sys/panels/keybindings-panel.js +1 -1
  50. package/dist/commands/sys/panels/models-panel.d.ts +8 -2
  51. package/dist/commands/sys/panels/models-panel.js +1 -1
  52. package/dist/commands/sys/panels/prefs-panel.d.ts +1 -0
  53. package/dist/commands/sys/panels/prefs-panel.js +1 -1
  54. package/dist/commands/sys/panels/profiles-panel.js +1 -1
  55. package/dist/commands/sys/panels/provider-panel.d.ts +4 -0
  56. package/dist/commands/sys/panels/provider-panel.js +1 -1
  57. package/dist/commands/sys/provider-login.js +5 -5
  58. package/dist/commands/sys/setup-core.js +3 -3
  59. package/dist/commands/sys/setup-settings-runner.js +1 -1
  60. package/dist/commands/sys/spend.js +3 -3
  61. package/dist/commands/sys/update.js +1 -1
  62. package/dist/core/auth-file.d.ts +11 -19
  63. package/dist/core/auth-file.js +1 -2
  64. package/dist/core/auto-update.d.ts +1 -1
  65. package/dist/core/auto-update.js +4 -4
  66. package/dist/core/bash-jobs.d.ts +29 -71
  67. package/dist/core/bash-jobs.js +9 -10
  68. package/dist/core/blobs/directory.d.ts +3 -0
  69. package/dist/core/blobs/directory.js +1 -0
  70. package/dist/core/blobs/fault.d.ts +3 -0
  71. package/dist/core/blobs/fault.js +1 -0
  72. package/dist/core/blobs/index.d.ts +21 -0
  73. package/dist/core/blobs/index.js +1 -0
  74. package/dist/core/blobs/r2.d.ts +9 -0
  75. package/dist/core/blobs/r2.js +4 -0
  76. package/dist/core/bootstrap.d.ts +1 -1
  77. package/dist/core/bootstrap.js +2 -2
  78. package/dist/core/canvas/canvas.d.ts +9 -7
  79. package/dist/core/canvas/canvas.js +8 -8
  80. package/dist/core/canvas/crons.d.ts +3 -2
  81. package/dist/core/canvas/crons.js +3 -3
  82. package/dist/core/canvas/daemon-owner.d.ts +5 -0
  83. package/dist/core/canvas/daemon-owner.js +1 -1
  84. package/dist/core/canvas/db.d.ts +10 -9
  85. package/dist/core/canvas/db.js +4 -4
  86. package/dist/core/canvas/executions.d.ts +100 -4
  87. package/dist/core/canvas/executions.js +1 -1
  88. package/dist/core/canvas/export-sqlite.js +1 -1
  89. package/dist/core/canvas/focuses.d.ts +4 -0
  90. package/dist/core/canvas/focuses.js +1 -1
  91. package/dist/core/canvas/history.js +9 -9
  92. package/dist/core/canvas/managed-worktree-sweep-candidates.d.ts +2 -1
  93. package/dist/core/canvas/managed-worktree-sweep-candidates.js +3 -2
  94. package/dist/core/canvas/node-tokens.d.ts +1 -4
  95. package/dist/core/canvas/node-tokens.js +3 -3
  96. package/dist/core/canvas/paths.d.ts +0 -1
  97. package/dist/core/canvas/paths.js +1 -1
  98. package/dist/core/canvas/person-state.d.ts +26 -0
  99. package/dist/core/canvas/person-state.js +1 -0
  100. package/dist/core/canvas/person.d.ts +3 -10
  101. package/dist/core/canvas/person.js +7 -7
  102. package/dist/core/canvas/reconciler-leases.d.ts +12 -0
  103. package/dist/core/canvas/reconciler-leases.js +8 -0
  104. package/dist/core/canvas/recovery.d.ts +4 -0
  105. package/dist/core/canvas/recovery.js +1 -1
  106. package/dist/core/canvas/schema-pg/003-fleet-removals.sql +1 -1
  107. package/dist/core/canvas/schema-pg/005-fleet-blobs.sql +13 -0
  108. package/dist/core/canvas/schema-pg/006-job-rows.sql +20 -0
  109. package/dist/core/canvas/schema-pg/007-ledger-check.sql +117 -0
  110. package/dist/core/canvas/schema-version.d.ts +1 -1
  111. package/dist/core/canvas/schema-version.js +1 -1
  112. package/dist/core/canvas/sessions.d.ts +8 -11
  113. package/dist/core/canvas/sessions.js +1 -4
  114. package/dist/core/canvas/tree.d.ts +4 -2
  115. package/dist/core/canvas/tree.js +6 -6
  116. package/dist/core/canvas/types.d.ts +7 -0
  117. package/dist/core/command-hooks/transport/exec-lifecycle.js +1 -1
  118. package/dist/core/command-plugins/bundle.d.ts +1 -1
  119. package/dist/core/command-plugins/bundle.js +1 -1
  120. package/dist/core/command-plugins/compose.d.ts +1 -1
  121. package/dist/core/command-plugins/discovery.d.ts +0 -1
  122. package/dist/core/command-plugins/discovery.js +1 -1
  123. package/dist/core/command-plugins/help-addenda.js +1 -1
  124. package/dist/core/command-plugins/presence.d.ts +2 -0
  125. package/dist/core/command-plugins/presence.js +1 -1
  126. package/dist/core/config.d.ts +16 -15
  127. package/dist/core/config.js +1 -1
  128. package/dist/core/conversation-store/client-worker.js +1 -1
  129. package/dist/core/conversation-store/client.js +2 -2
  130. package/dist/core/conversation-store/index.d.ts +9 -11
  131. package/dist/core/conversation-store/index.js +1 -1
  132. package/dist/core/conversation-store/patch.js +1 -1
  133. package/dist/core/conversation-store/row-store.d.ts +14 -0
  134. package/dist/core/conversation-store/row-store.js +13 -0
  135. package/dist/core/directory/join.js +1 -1
  136. package/dist/core/env-name.d.ts +1 -0
  137. package/dist/core/env-name.js +1 -1
  138. package/dist/core/environment-recipe.d.ts +15 -0
  139. package/dist/core/environment-recipe.js +1 -0
  140. package/dist/core/environments.js +1 -1
  141. package/dist/core/events/emit.js +2 -2
  142. package/dist/core/events/run-event-chunks.d.ts +25 -0
  143. package/dist/core/events/run-event-chunks.js +5 -0
  144. package/dist/core/feed/messages.js +5 -5
  145. package/dist/core/grants/mirror.d.ts +15 -0
  146. package/dist/core/grants/mirror.js +15 -3
  147. package/dist/core/grants/on-sync.d.ts +9 -5
  148. package/dist/core/grants/on-sync.js +1 -1
  149. package/dist/core/grants/remove.d.ts +1 -6
  150. package/dist/core/grants/remove.js +1 -1
  151. package/dist/core/grants/sync.js +1 -1
  152. package/dist/core/grants/watch.d.ts +15 -9
  153. package/dist/core/grants/watch.js +1 -1
  154. package/dist/core/graph/custom.js +8 -8
  155. package/dist/core/graph/jobs.d.ts +83 -5
  156. package/dist/core/graph/jobs.js +11 -2
  157. package/dist/core/graph/kinds/job.js +2 -2
  158. package/dist/core/graph/names.js +7 -7
  159. package/dist/core/graph/objects.d.ts +5 -1
  160. package/dist/core/graph/objects.js +11 -11
  161. package/dist/core/graph/reader.d.ts +3 -0
  162. package/dist/core/graph/reader.js +3 -3
  163. package/dist/core/graph/repo-sync/identity.d.ts +3 -1
  164. package/dist/core/graph/repo-sync/identity.js +1 -1
  165. package/dist/core/graph/repo-sync/repos.d.ts +1 -1
  166. package/dist/core/graph/repo-sync/repos.js +2 -2
  167. package/dist/core/graph/repo-sync/sync.js +2 -2
  168. package/dist/core/installed-plugins.js +1 -1
  169. package/dist/core/keybindings/persistence.d.ts +1 -1
  170. package/dist/core/keybindings/persistence.js +1 -1
  171. package/dist/core/layout-migrate/loose-keys.d.ts +1 -1
  172. package/dist/core/layout-migrate/loose-keys.js +1 -1
  173. package/dist/core/ledger/account.d.ts +12 -0
  174. package/dist/core/ledger/account.js +2 -0
  175. package/dist/core/ledger/charges.d.ts +2 -2
  176. package/dist/core/ledger/charges.js +1 -1
  177. package/dist/core/ledger/check.d.ts +5 -1
  178. package/dist/core/ledger/check.js +1 -7
  179. package/dist/core/ledger/chunks.d.ts +8 -0
  180. package/dist/core/ledger/chunks.js +2 -0
  181. package/dist/core/ledger/index.d.ts +2 -1
  182. package/dist/core/ledger/index.js +1 -1
  183. package/dist/core/ledger/infra-allowance.d.ts +9 -0
  184. package/dist/core/ledger/infra-allowance.js +1 -0
  185. package/dist/core/ledger/limits.js +3 -3
  186. package/dist/core/ledger/payer.d.ts +1 -1
  187. package/dist/core/ledger/payer.js +1 -1
  188. package/dist/core/ledger/read.d.ts +14 -4
  189. package/dist/core/ledger/read.js +2 -3
  190. package/dist/core/ledger/totals.d.ts +5 -16
  191. package/dist/core/ledger/totals.js +4 -4
  192. package/dist/core/ledger/types.d.ts +12 -3
  193. package/dist/core/llm/run.js +2 -2
  194. package/dist/core/managed-providers.d.ts +72 -0
  195. package/dist/core/managed-providers.js +1 -0
  196. package/dist/core/model-auth/api-credential-store.d.ts +10 -0
  197. package/dist/core/model-auth/api-credential-store.js +1 -0
  198. package/dist/core/model-auth/daemon-login.d.ts +1 -1
  199. package/dist/core/model-auth/daemon-login.js +1 -1
  200. package/dist/core/model-auth/flows.d.ts +5 -4
  201. package/dist/core/model-auth/flows.js +1 -1
  202. package/dist/core/model-auth/handoff-jti.d.ts +3 -4
  203. package/dist/core/model-auth/handoff-jti.js +1 -1
  204. package/dist/core/model-auth/readiness.js +1 -1
  205. package/dist/core/model-config.d.ts +1 -1
  206. package/dist/core/model-config.js +1 -1
  207. package/dist/core/model-routes-pool.d.ts +14 -0
  208. package/dist/core/model-routes-pool.js +1 -0
  209. package/dist/core/model-routes.d.ts +11 -16
  210. package/dist/core/model-routes.js +1 -1
  211. package/dist/core/peer/ingest.d.ts +2 -0
  212. package/dist/core/peer/ingest.js +1 -1
  213. package/dist/core/peer/stubs.d.ts +8 -0
  214. package/dist/core/peer/stubs.js +1 -1
  215. package/dist/core/permissions/evaluator.d.ts +7 -2
  216. package/dist/core/permissions/evaluator.js +2 -2
  217. package/dist/core/plugin-env.js +1 -1
  218. package/dist/core/pool-credential-store.d.ts +2 -5
  219. package/dist/core/pool-credential-store.js +1 -1
  220. package/dist/core/profiles/app-env-store.d.ts +5 -5
  221. package/dist/core/profiles/app-env-store.js +1 -2
  222. package/dist/core/profiles/default-binding.d.ts +5 -5
  223. package/dist/core/profiles/default-binding.js +1 -1
  224. package/dist/core/profiles/env-store.d.ts +10 -21
  225. package/dist/core/profiles/env-store.js +1 -2
  226. package/dist/core/profiles/manifest.d.ts +14 -18
  227. package/dist/core/profiles/manifest.js +1 -1
  228. package/dist/core/profiles/relocate.js +1 -1
  229. package/dist/core/profiles/select.js +21 -21
  230. package/dist/core/provider-credential.d.ts +1 -1
  231. package/dist/core/provider-credential.js +1 -1
  232. package/dist/core/provider-management.d.ts +3 -4
  233. package/dist/core/provider-management.js +1 -1
  234. package/dist/core/providers/bundles.js +2 -2
  235. package/dist/core/providers/call.d.ts +3 -34
  236. package/dist/core/providers/description.d.ts +34 -0
  237. package/dist/core/providers/description.js +0 -0
  238. package/dist/core/providers/token-cache.d.ts +14 -14
  239. package/dist/core/providers/token-cache.js +1 -1
  240. package/dist/core/review/companion.js +1 -1
  241. package/dist/core/runs/activity.d.ts +1 -1
  242. package/dist/core/runs/activity.js +1 -1
  243. package/dist/core/runs/events.d.ts +7 -5
  244. package/dist/core/runs/events.js +2 -6
  245. package/dist/core/runs/operations.d.ts +1 -1
  246. package/dist/core/runs/operations.js +6 -6
  247. package/dist/core/runtime/bearings.js +1 -1
  248. package/dist/core/runtime/broker/attachments-fetch.d.ts +5 -0
  249. package/dist/core/runtime/broker/attachments-fetch.js +1 -0
  250. package/dist/core/runtime/broker/bash-job-launch.d.ts +4 -2
  251. package/dist/core/runtime/broker/bash-job-launch.js +1 -1
  252. package/dist/core/runtime/broker/boot-state.d.ts +9 -0
  253. package/dist/core/runtime/broker/boot-state.js +1 -0
  254. package/dist/core/runtime/broker/cli-relay.d.ts +2 -1
  255. package/dist/core/runtime/broker/cli-relay.js +1 -1
  256. package/dist/core/runtime/broker/client-registry.d.ts +3 -3
  257. package/dist/core/runtime/broker/daemon-ops.d.ts +10 -1
  258. package/dist/core/runtime/broker/daemon-ops.js +1 -1
  259. package/dist/core/runtime/broker/fault-retry.d.ts +2 -0
  260. package/dist/core/runtime/broker/fault-retry.js +1 -1
  261. package/dist/core/runtime/broker/frame-engine-control.js +1 -1
  262. package/dist/core/runtime/broker/held-deferred-inbox.d.ts +3 -0
  263. package/dist/core/runtime/broker/held-deferred-inbox.js +1 -1
  264. package/dist/core/runtime/broker/job-reporter.d.ts +18 -0
  265. package/dist/core/runtime/broker/job-reporter.js +2 -0
  266. package/dist/core/runtime/broker/model-adapter.d.ts +3 -0
  267. package/dist/core/runtime/broker/model-adapter.js +3 -2
  268. package/dist/core/runtime/broker/signal-stream.js +1 -1
  269. package/dist/core/runtime/broker/spilled-body.d.ts +5 -0
  270. package/dist/core/runtime/broker/spilled-body.js +1 -0
  271. package/dist/core/runtime/broker/summaries-post.d.ts +5 -0
  272. package/dist/core/runtime/broker/summaries-post.js +1 -0
  273. package/dist/core/runtime/broker/tool-groups.d.ts +3 -0
  274. package/dist/core/runtime/broker/tool-groups.js +1 -1
  275. package/dist/core/runtime/broker/turn-replies.d.ts +1 -0
  276. package/dist/core/runtime/broker/turn-replies.js +1 -1
  277. package/dist/core/runtime/broker-persona-guidance.js +2 -2
  278. package/dist/core/runtime/broker.js +1 -1
  279. package/dist/core/runtime/deliver-live.js +1 -1
  280. package/dist/core/runtime/first-boot-rows.d.ts +8 -0
  281. package/dist/core/runtime/first-boot-rows.js +2 -0
  282. package/dist/core/runtime/fleet.d.ts +13 -12
  283. package/dist/core/runtime/front-door-login.js +1 -1
  284. package/dist/core/runtime/front-door.js +6 -6
  285. package/dist/core/runtime/headless-pi.js +1 -1
  286. package/dist/core/runtime/host.d.ts +14 -3
  287. package/dist/core/runtime/host.js +3 -3
  288. package/dist/core/runtime/invocation.d.ts +6 -0
  289. package/dist/core/runtime/kickoff.d.ts +2 -14
  290. package/dist/core/runtime/kickoff.js +17 -19
  291. package/dist/core/runtime/launch-config-worker.js +1 -1
  292. package/dist/core/runtime/launch.js +2 -2
  293. package/dist/core/runtime/model-registry.js +1 -1
  294. package/dist/core/runtime/node-read.d.ts +4 -6
  295. package/dist/core/runtime/node-read.js +3 -3
  296. package/dist/core/runtime/nodes.js +1 -1
  297. package/dist/core/runtime/outcome-document.d.ts +0 -1
  298. package/dist/core/runtime/outcome-document.js +1 -1
  299. package/dist/core/runtime/output-result.d.ts +15 -0
  300. package/dist/core/runtime/output-result.js +5 -0
  301. package/dist/core/runtime/placement.d.ts +17 -1
  302. package/dist/core/runtime/placement.js +1 -1
  303. package/dist/core/runtime/provider-credential-gate.d.ts +6 -2
  304. package/dist/core/runtime/provider-credential-gate.js +2 -2
  305. package/dist/core/runtime/recovery-hold.d.ts +21 -2
  306. package/dist/core/runtime/recovery-hold.js +2 -1
  307. package/dist/core/runtime/recycle.js +1 -1
  308. package/dist/core/runtime/reset.js +1 -1
  309. package/dist/core/runtime/revive.d.ts +2 -2
  310. package/dist/core/runtime/revive.js +2 -2
  311. package/dist/core/runtime/runner/blaxel/client.d.ts +81 -0
  312. package/dist/core/runtime/runner/blaxel/client.js +1 -0
  313. package/dist/core/runtime/runner/blaxel/image-build.d.ts +74 -0
  314. package/dist/core/runtime/runner/blaxel/image-build.js +5 -0
  315. package/dist/core/runtime/runner/blaxel/runner.d.ts +41 -0
  316. package/dist/core/runtime/runner/blaxel/runner.js +3 -0
  317. package/dist/core/runtime/runner/index.d.ts +8 -0
  318. package/dist/core/runtime/runner/index.js +1 -0
  319. package/dist/core/runtime/runner/process.d.ts +11 -0
  320. package/dist/core/runtime/runner/process.js +1 -0
  321. package/dist/core/runtime/runner/types.d.ts +95 -0
  322. package/dist/core/runtime/runner/types.js +0 -0
  323. package/dist/core/runtime/situational-context.d.ts +3 -6
  324. package/dist/core/runtime/situational-context.js +2 -2
  325. package/dist/core/runtime/situational-live.js +1 -1
  326. package/dist/core/runtime/spawn-env-rows.d.ts +5 -0
  327. package/dist/core/runtime/spawn-env-rows.js +1 -0
  328. package/dist/core/runtime/spawn-env.d.ts +4 -18
  329. package/dist/core/runtime/spawn-env.js +1 -1
  330. package/dist/core/runtime/spawn.js +2 -2
  331. package/dist/core/runtime/stop-guard.d.ts +1 -1
  332. package/dist/core/runtime/stop-guard.js +2 -8
  333. package/dist/core/runtime/structured-output.d.ts +0 -67
  334. package/dist/core/runtime/structured-output.js +3 -8
  335. package/dist/core/runtime/tmux-driver.d.ts +8 -0
  336. package/dist/core/runtime/tmux-driver.js +6 -6
  337. package/dist/core/runtime/view-socket.d.ts +20 -0
  338. package/dist/core/runtime/view-socket.js +3 -1
  339. package/dist/core/runtime/warm-pool.d.ts +13 -1
  340. package/dist/core/runtime/warm-pool.js +1 -1
  341. package/dist/core/scoped-state/legacy-profiles.d.ts +11 -0
  342. package/dist/core/scoped-state/legacy-profiles.js +1 -0
  343. package/dist/core/scoped-state/materialized-plugins.d.ts +18 -0
  344. package/dist/core/scoped-state/materialized-plugins.js +1 -0
  345. package/dist/core/scoped-state/migrate.d.ts +8 -1
  346. package/dist/core/scoped-state/migrate.js +3 -3
  347. package/dist/core/scoped-state/person-rows.d.ts +10 -0
  348. package/dist/core/scoped-state/person-rows.js +6 -0
  349. package/dist/core/scoped-state/person-store.d.ts +72 -0
  350. package/dist/core/scoped-state/person-store.js +1 -0
  351. package/dist/core/secrets/blaxel-launch.d.ts +24 -0
  352. package/dist/core/secrets/blaxel-launch.js +4 -0
  353. package/dist/core/secrets/blaxel-register.d.ts +2 -0
  354. package/dist/core/secrets/blaxel-register.js +1 -0
  355. package/dist/core/secrets/env-rows.d.ts +17 -0
  356. package/dist/core/secrets/env-rows.js +4 -0
  357. package/dist/core/secrets/environment-owner.d.ts +8 -0
  358. package/dist/core/secrets/environment-owner.js +1 -0
  359. package/dist/core/secrets/environment-secrets.d.ts +14 -0
  360. package/dist/core/secrets/environment-secrets.js +1 -0
  361. package/dist/core/secrets/index.d.ts +2 -0
  362. package/dist/core/secrets/index.js +1 -0
  363. package/dist/core/secrets/key.d.ts +3 -0
  364. package/dist/core/secrets/key.js +2 -0
  365. package/dist/core/secrets/seal.d.ts +18 -0
  366. package/dist/core/secrets/seal.js +1 -0
  367. package/dist/core/spaces/mounts.d.ts +1 -1
  368. package/dist/core/spaces/mounts.js +1 -1
  369. package/dist/core/spaces/process.d.ts +1 -1
  370. package/dist/core/spaces/stop.d.ts +7 -5
  371. package/dist/core/spaces/stop.js +2 -2
  372. package/dist/core/spaces/users.d.ts +2 -1
  373. package/dist/core/spaces/users.js +1 -1
  374. package/dist/core/storage/attachments.d.ts +11 -8
  375. package/dist/core/storage/attachments.js +1 -1
  376. package/dist/core/storage/tables.d.ts +4 -0
  377. package/dist/core/storage/tables.js +3 -3
  378. package/dist/core/subscription-state.d.ts +34 -72
  379. package/dist/core/subscription-state.js +1 -4
  380. package/dist/core/substrate/delivery/plan.js +1 -1
  381. package/dist/core/user-settings.js +1 -1
  382. package/dist/daemon/api/app-listener.js +10 -10
  383. package/dist/daemon/api/auth/person-bearer.d.ts +14 -0
  384. package/dist/daemon/api/auth/person-bearer.js +1 -0
  385. package/dist/daemon/api/bridge.js +4 -4
  386. package/dist/daemon/api/document-listener.js +3 -3
  387. package/dist/daemon/api/environment-of.d.ts +18 -0
  388. package/dist/daemon/api/environment-of.js +5 -0
  389. package/dist/daemon/api/handlers/analytics.js +1 -1
  390. package/dist/daemon/api/handlers/app-profiles.d.ts +2 -2
  391. package/dist/daemon/api/handlers/app-profiles.js +1 -1
  392. package/dist/daemon/api/handlers/bash-jobs.js +1 -1
  393. package/dist/daemon/api/handlers/bash.js +1 -1
  394. package/dist/daemon/api/handlers/broker-ops.d.ts +3 -0
  395. package/dist/daemon/api/handlers/broker-ops.js +1 -1
  396. package/dist/daemon/api/handlers/broker-recovery.js +1 -1
  397. package/dist/daemon/api/handlers/broker-signals.d.ts +0 -3
  398. package/dist/daemon/api/handlers/broker-signals.js +2 -2
  399. package/dist/daemon/api/handlers/canvas.js +4 -4
  400. package/dist/daemon/api/handlers/charges.d.ts +1 -1
  401. package/dist/daemon/api/handlers/charges.js +1 -1
  402. package/dist/daemon/api/handlers/conversations.d.ts +2 -0
  403. package/dist/daemon/api/handlers/conversations.js +3 -0
  404. package/dist/daemon/api/handlers/crons.js +1 -1
  405. package/dist/daemon/api/handlers/daemon.js +1 -1
  406. package/dist/daemon/api/handlers/delivery.d.ts +1 -1
  407. package/dist/daemon/api/handlers/delivery.js +1 -1
  408. package/dist/daemon/api/handlers/docs.js +1 -1
  409. package/dist/daemon/api/handlers/exec.js +1 -1
  410. package/dist/daemon/api/handlers/execution-start.d.ts +2 -0
  411. package/dist/daemon/api/handlers/execution-start.js +2 -0
  412. package/dist/daemon/api/handlers/files.js +1 -1
  413. package/dist/daemon/api/handlers/git-credential.d.ts +11 -0
  414. package/dist/daemon/api/handlers/git-credential.js +1 -0
  415. package/dist/daemon/api/handlers/hook-exec.d.ts +1 -1
  416. package/dist/daemon/api/handlers/hook-exec.js +1 -1
  417. package/dist/daemon/api/handlers/human-requests.js +1 -1
  418. package/dist/daemon/api/handlers/inbox.js +1 -1
  419. package/dist/daemon/api/handlers/messages.js +1 -1
  420. package/dist/daemon/api/handlers/model-config.js +1 -1
  421. package/dist/daemon/api/handlers/modelauth.d.ts +1 -1
  422. package/dist/daemon/api/handlers/modelauth.js +1 -1
  423. package/dist/daemon/api/handlers/node-events.d.ts +6 -0
  424. package/dist/daemon/api/handlers/node-events.js +3 -3
  425. package/dist/daemon/api/handlers/node-outcomes.js +1 -1
  426. package/dist/daemon/api/handlers/node-records.js +3 -2
  427. package/dist/daemon/api/handlers/nodes.js +1 -1
  428. package/dist/daemon/api/handlers/objects.js +3 -3
  429. package/dist/daemon/api/handlers/profiles.js +1 -1
  430. package/dist/daemon/api/handlers/providers.js +1 -1
  431. package/dist/daemon/api/handlers/reports.js +9 -13
  432. package/dist/daemon/api/handlers/reviews.js +1 -1
  433. package/dist/daemon/api/handlers/runs.js +1 -1
  434. package/dist/daemon/api/handlers/settings.d.ts +2 -0
  435. package/dist/daemon/api/handlers/settings.js +1 -0
  436. package/dist/daemon/api/handlers/structured-requests.js +1 -1
  437. package/dist/daemon/api/handlers/vendor-status.d.ts +1 -1
  438. package/dist/daemon/api/handlers/vendor-status.js +1 -1
  439. package/dist/daemon/api/handlers/worktree.js +1 -1
  440. package/dist/daemon/api/map.d.ts +2 -2
  441. package/dist/daemon/api/map.js +2 -2
  442. package/dist/daemon/api/operations.js +1 -1
  443. package/dist/daemon/api/reader.d.ts +8 -1
  444. package/dist/daemon/api/reader.js +1 -1
  445. package/dist/daemon/api/router.d.ts +4 -2
  446. package/dist/daemon/api/router.js +1 -1
  447. package/dist/daemon/api/server.d.ts +15 -3
  448. package/dist/daemon/api/server.js +1 -1
  449. package/dist/daemon/api/vendor-signin.d.ts +2 -1
  450. package/dist/daemon/api/vendor-signin.js +20 -20
  451. package/dist/daemon/api/viewer-presence.d.ts +20 -6
  452. package/dist/daemon/api/viewer-presence.js +2 -1
  453. package/dist/daemon/broker-signals/bus.d.ts +48 -11
  454. package/dist/daemon/broker-signals/bus.js +1 -1
  455. package/dist/daemon/cron/armed-context.js +1 -1
  456. package/dist/daemon/cron/lease-recovery.js +1 -1
  457. package/dist/daemon/cron/live-runs.d.ts +6 -0
  458. package/dist/daemon/cron/live-runs.js +1 -1
  459. package/dist/daemon/cron/run-socket.js +1 -1
  460. package/dist/daemon/cron-run.js +2 -2
  461. package/dist/daemon/crtrd-cli.js +1 -1
  462. package/dist/daemon/crtrd.d.ts +10 -0
  463. package/dist/daemon/crtrd.js +18 -17
  464. package/dist/daemon/delivery/run-delivery.d.ts +1 -1
  465. package/dist/daemon/delivery/run-delivery.js +1 -1
  466. package/dist/daemon/due-sources.d.ts +1 -1
  467. package/dist/daemon/due-sources.js +1 -1
  468. package/dist/daemon/due.js +7 -6
  469. package/dist/daemon/fleet.d.ts +6 -6
  470. package/dist/daemon/fleet.js +9 -9
  471. package/dist/daemon/park-activity.d.ts +2 -1
  472. package/dist/daemon/park-activity.js +1 -1
  473. package/dist/daemon/park-pending.d.ts +20 -13
  474. package/dist/daemon/park-pending.js +3 -1
  475. package/dist/daemon/profile-delete.js +1 -1
  476. package/dist/daemon/reconcilers/bash-deadline.d.ts +15 -10
  477. package/dist/daemon/reconcilers/bash-deadline.js +1 -3
  478. package/dist/daemon/reconcilers/broker-supervision.d.ts +13 -3
  479. package/dist/daemon/reconcilers/broker-supervision.js +4 -4
  480. package/dist/daemon/reconcilers/cron-lane.d.ts +0 -1
  481. package/dist/daemon/reconcilers/cron-lane.js +1 -1
  482. package/dist/daemon/reconcilers/fault-retry-backstop.d.ts +2 -9
  483. package/dist/daemon/reconcilers/fault-retry-backstop.js +1 -1
  484. package/dist/daemon/reconcilers/grant-effects.d.ts +8 -0
  485. package/dist/daemon/reconcilers/grant-effects.js +1 -0
  486. package/dist/daemon/reconcilers/grove-instance-sweep.d.ts +1 -3
  487. package/dist/daemon/reconcilers/grove-instance-sweep.js +1 -1
  488. package/dist/daemon/reconcilers/ledger-r2.d.ts +27 -0
  489. package/dist/daemon/reconcilers/ledger-r2.js +7 -0
  490. package/dist/daemon/reconcilers/ledger-sandbox.d.ts +55 -0
  491. package/dist/daemon/reconcilers/ledger-sandbox.js +9 -0
  492. package/dist/daemon/reconcilers/ledger-storage.d.ts +22 -0
  493. package/dist/daemon/reconcilers/ledger-storage.js +5 -0
  494. package/dist/daemon/reconcilers/live-obligation.d.ts +3 -2
  495. package/dist/daemon/reconcilers/live-obligation.js +1 -1
  496. package/dist/daemon/reconcilers/managed-worktree-sweep.d.ts +0 -5
  497. package/dist/daemon/reconcilers/managed-worktree-sweep.js +1 -1
  498. package/dist/daemon/reconcilers/node-deadline.d.ts +2 -1
  499. package/dist/daemon/reconcilers/node-deadline.js +1 -1
  500. package/dist/daemon/reconcilers/node-lifecycle/freeze-lane.d.ts +1 -2
  501. package/dist/daemon/reconcilers/node-lifecycle/freeze-lane.js +1 -1
  502. package/dist/daemon/reconcilers/node-lifecycle/remote-wake.d.ts +31 -0
  503. package/dist/daemon/reconcilers/node-lifecycle/remote-wake.js +1 -0
  504. package/dist/daemon/reconcilers/node-lifecycle/requested-stops.d.ts +5 -0
  505. package/dist/daemon/reconcilers/node-lifecycle/requested-stops.js +2 -0
  506. package/dist/daemon/reconcilers/node-lifecycle/tick.js +1 -1
  507. package/dist/daemon/reconcilers/pending-review-submit.js +1 -1
  508. package/dist/daemon/reconcilers/recipe-image.d.ts +49 -0
  509. package/dist/daemon/reconcilers/recipe-image.js +7 -0
  510. package/dist/daemon/reconcilers/row-claim.d.ts +19 -0
  511. package/dist/daemon/reconcilers/row-claim.js +2 -0
  512. package/dist/daemon/reconcilers/storage-due-work.d.ts +18 -3
  513. package/dist/daemon/reconcilers/storage-due-work.js +2 -1
  514. package/dist/daemon/reconcilers/storage-maintenance.d.ts +5 -13
  515. package/dist/daemon/reconcilers/storage-maintenance.js +1 -1
  516. package/dist/daemon/reconcilers/structured-request-lane.js +1 -1
  517. package/dist/daemon/reconcilers/throttled-lane.d.ts +11 -0
  518. package/dist/daemon/reconcilers/throttled-lane.js +1 -0
  519. package/dist/daemon/review/finish.js +1 -1
  520. package/dist/daemon/run-notices.d.ts +3 -0
  521. package/dist/daemon/run-notices.js +1 -1
  522. package/dist/daemon/runs/append-section.d.ts +4 -1
  523. package/dist/daemon/runs/append-section.js +2 -2
  524. package/dist/daemon/runs/observer.d.ts +3 -2
  525. package/dist/daemon/runs/observer.js +3 -2
  526. package/dist/daemon/runs/view-transport.d.ts +19 -0
  527. package/dist/daemon/runs/view-transport.js +1 -0
  528. package/dist/daemon/structured-requests/boot.d.ts +2 -1
  529. package/dist/daemon/structured-requests/boot.js +1 -1
  530. package/dist/daemon/structured-requests/effects.d.ts +4 -3
  531. package/dist/daemon/structured-requests/effects.js +1 -1
  532. package/dist/daemon/structured-requests/notifier.d.ts +2 -0
  533. package/dist/daemon/structured-requests/notifier.js +1 -1
  534. package/dist/daemon/structured-requests/sidecar.d.ts +4 -3
  535. package/dist/daemon/structured-requests/sidecar.js +1 -1
  536. package/dist/launcher/validate.js +1 -1
  537. package/dist/migrations/004-canvas-documents/index.js +2 -2
  538. package/dist/pi-extensions/broker-local.d.ts +3 -3
  539. package/dist/pi-extensions/broker-local.js +1 -2
  540. package/dist/pi-extensions/canvas-bash-valve.js +6 -6
  541. package/dist/pi-extensions/canvas-context-intro.js +2 -2
  542. package/dist/pi-extensions/canvas-elapsed.js +2 -2
  543. package/dist/pi-extensions/canvas-goal-capture.js +1 -1
  544. package/dist/pi-extensions/canvas-inbox-watcher.js +2 -2
  545. package/dist/pi-extensions/canvas-review-boundary.d.ts +11 -1
  546. package/dist/pi-extensions/canvas-review-boundary.js +3 -3
  547. package/dist/pi-extensions/canvas-stophook.js +1 -1
  548. package/dist/pi-extensions/canvas-structured-output.d.ts +5 -3
  549. package/dist/pi-extensions/canvas-structured-output.js +6 -11
  550. package/dist/pi-extensions/canvas-tool-guide.d.ts +9 -2
  551. package/dist/pi-extensions/canvas-tool-guide.js +6 -6
  552. package/dist/shared/inbox-entry-body.js +7 -7
  553. package/dist/types.d.ts +12 -0
  554. package/docs/sdk/release-notes.md +4 -0
  555. package/package.json +7 -4
  556. package/packages/crouter-identity/package.json +1 -1
  557. package/runtime.lock.json +13 -13
  558. package/scripts/git-credential-crtr +33 -0
  559. package/scripts/sandbox-bootstrap.sh +54 -0
  560. package/scripts/sandbox-start.mjs +320 -0
  561. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.d.ts +0 -78
  562. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.js +0 -1179
  563. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.ts +0 -1406
  564. package/dist/core/conversation-store/file-store.d.ts +0 -37
  565. package/dist/core/conversation-store/file-store.js +0 -9
  566. package/dist/core/conversation-store/listener.d.ts +0 -4
  567. package/dist/core/conversation-store/listener.js +0 -8
  568. package/dist/core/scoped-state/profiles.d.ts +0 -27
  569. package/dist/core/scoped-state/profiles.js +0 -1
  570. package/dist/core/scoped-state/providers.d.ts +0 -24
  571. package/dist/core/scoped-state/providers.js +0 -1
  572. package/dist/core/scoped-state/settings.d.ts +0 -28
  573. package/dist/core/scoped-state/settings.js +0 -1
@@ -1 +1 @@
1
- var E=Object.defineProperty;var s=(e,t)=>E(e,"name",{value:t,configurable:!0});import{envModelIntent as _,envNodeCwd as N,envProfileId as O}from"../../shared/env.js";import{join as C}from"node:path";import{InMemoryCredentialStore as $}from"@earendil-works/pi-ai";import{PoolCredentialStore as B}from"../pool-credential-store.js";import{secretsDir as H}from"../layout.js";import{APP_FAMILY as g,expandModelCandidates as W,modelRequestFromConfig as A,selectInitialModelRoute as Y}from"../model-routes.js";import{defaultModelLaddersConfig as z}from"../../types.js";import{stripThinkingSuffix as G}from"./model-selection.js";import{configureBrokerModelRuntime as J}from"./broker/model-adapter.js";import{currentNodeToken as K}from"./broker/node-token.js";function Q(e){for(let t=e.length-1;t>=0;t--){const n=e[t];if(n?.role!=="assistant")continue;if(typeof n.content=="string")return n.content.trim();if(!Array.isArray(n.content))continue;const c=n.content.map(i=>{const l=i;return l.type==="text"&&typeof l.text=="string"?l.text:""}).join("").trim();if(c!=="")return c}return""}s(Q,"lastAssistantText");function U(e,t){const n=_();if(!(n===void 0||!n.startsWith(`${g}/`)))return t?{modelRequest:A(e.modelSpec,n,!1),intent:n}:{modelRequest:{kind:"logical",family:g,strength:"light",spec:G(z().anthropic.light)},intent:`${g}/light`}}s(U,"appPaidRequest");async function y(e,t,n,c){let i,l=!1,d=!1,x;const M=s(o=>{i===void 0||l||(l=!0,o&&i.abort().catch(()=>{}),i.dispose())},"disposeSession"),F=new Promise(o=>{x=setTimeout(()=>{d=!0,M(!0),o(t)},e.timeoutMs)}),j=(async()=>{try{const o=await import("@earendil-works/pi-coding-agent"),m=K()!==void 0;if(d)return t;const u=N()??process.cwd(),f=O(),h=o.getAgentDir(),w=await o.ModelRuntime.create({credentials:m?new $:new B(C(H(),"auth.json")),modelsPath:C(h,"models.json")}),S=m?U(e,n):void 0;if(m&&J(w,S?.intent),d)return t;const I=await o.createAgentSessionServices({cwd:u,agentDir:h,modelRuntime:w,settingsManager:o.SettingsManager.inMemory(),resourceLoaderOptions:{noExtensions:!0,noContextFiles:!0,noSkills:!0,noPromptTemplates:!0,noThemes:!0,systemPrompt:e.systemPrompt,...m?{}:{extensionFactories:[(await import("../../builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.js")).createProviderRotationExtension({modelIntent:e.modelIntent,nodeCwd:u,profileId:f})]}}});if(d)return t;const p=S?.modelRequest??A(e.modelSpec,e.modelIntent,!1);if(p===void 0)return t;const P=new o.ModelRegistry(I.modelRuntime),R=m?W(p,u,f).map(a=>P.find(a.providerId,a.modelId)).find(a=>a!==void 0):Y(p,P,{cwd:u,profileId:f}).selected?.model;if(R===void 0)return t;let T;const r=e.tool,L=r===void 0?void 0:o.defineTool({name:r.name,label:r.label,description:r.description,parameters:r.parameters,...r.constrainedSampling===void 0?{}:{constrainedSampling:r.constrainedSampling},async execute(a,D){return T=D,{content:[{type:"text",text:"Recorded."}],details:{recorded:!0},terminate:!0}}}),v=o.SessionManager.inMemory(u,e.sessionId===void 0?void 0:{id:e.sessionId});for(const a of e.seedMessages??[])v.appendMessage(a);return{session:i}=await o.createAgentSessionFromServices({services:I,sessionManager:v,model:R,thinkingLevel:"off",...r===void 0?e.toolPolicy==="builtin"?{}:{noTools:"all"}:{tools:[r.name],customTools:[L]}}),d||(await i.bindExtensions({}),d)?t:(await i.prompt(e.userPrompt),d?t:c(i,T))}catch{return t}finally{M(!1)}})();try{return await Promise.race([j,F])}finally{clearTimeout(x)}}s(y,"runHeadless");function re(e){return y(e,null,!1,(t,n)=>n)}s(re,"headlessToolCall");function se(e){return y(e,"",!1,t=>Q(t.messages))}s(se,"headlessText");function de(e){return y(e,"failed",!0,()=>"completed")}s(de,"headlessTurn");export{se as headlessText,re as headlessToolCall,de as headlessTurn};
1
+ var j=Object.defineProperty;var s=(e,t)=>j(e,"name",{value:t,configurable:!0});import{envModelIntent as _,envNodeCwd as D,envProfileId as E}from"../../shared/env.js";import{join as N}from"node:path";import{InMemoryCredentialStore as O}from"@earendil-works/pi-ai";import{APP_FAMILY as c,expandModelCandidates as $,modelRequestFromConfig as I}from"../model-routes.js";import{defaultModelLaddersConfig as B}from"../../types.js";import{stripThinkingSuffix as H}from"./model-selection.js";import{configureBrokerModelRuntime as W}from"./broker/model-adapter.js";import{currentNodeToken as Y}from"./broker/node-token.js";function z(e){for(let t=e.length-1;t>=0;t--){const n=e[t];if(n?.role!=="assistant")continue;if(typeof n.content=="string")return n.content.trim();if(!Array.isArray(n.content))continue;const m=n.content.map(i=>{const u=i;return u.type==="text"&&typeof u.text=="string"?u.text:""}).join("").trim();if(m!=="")return m}return""}s(z,"lastAssistantText");function G(e,t){const n=_();if(!(n===void 0||!n.startsWith(`${c}/`)))return t?{modelRequest:I(e.modelSpec,n,!1),intent:n}:{modelRequest:{kind:"logical",family:c,strength:"light",spec:H(B().anthropic.light)},intent:`${c}/light`}}s(G,"appPaidRequest");async function f(e,t,n,m){let i,u=!1,d=!1,p;const g=s(o=>{i===void 0||u||(u=!0,o&&i.abort().catch(()=>{}),i.dispose())},"disposeSession"),R=new Promise(o=>{p=setTimeout(()=>{d=!0,g(!0),o(t)},e.timeoutMs)}),v=(async()=>{try{const o=await import("@earendil-works/pi-coding-agent");if(Y()===void 0||d)return t;const l=D()??process.cwd(),C=E(),y=o.getAgentDir(),x=await o.ModelRuntime.create({credentials:new O,modelsPath:N(y,"models.json")}),M=G(e,n);if(W(x,M?.intent),d)return t;const h=await o.createAgentSessionServices({cwd:l,agentDir:y,modelRuntime:x,settingsManager:o.SettingsManager.inMemory(),resourceLoaderOptions:{noExtensions:!0,noContextFiles:!0,noSkills:!0,noPromptTemplates:!0,noThemes:!0,systemPrompt:e.systemPrompt}});if(d)return t;const w=M?.modelRequest??I(e.modelSpec,e.modelIntent,!1);if(w===void 0)return t;const A=new o.ModelRegistry(h.modelRuntime),S=(await $(w,l,C)).map(a=>A.find(a.providerId,a.modelId)).find(a=>a!==void 0);if(S===void 0)return t;let T;const r=e.tool,F=r===void 0?void 0:o.defineTool({name:r.name,label:r.label,description:r.description,parameters:r.parameters,...r.constrainedSampling===void 0?{}:{constrainedSampling:r.constrainedSampling},async execute(a,L){return T=L,{content:[{type:"text",text:"Recorded."}],details:{recorded:!0},terminate:!0}}}),P=o.SessionManager.inMemory(l,e.sessionId===void 0?void 0:{id:e.sessionId});for(const a of e.seedMessages??[])P.appendMessage(a);return{session:i}=await o.createAgentSessionFromServices({services:h,sessionManager:P,model:S,thinkingLevel:"off",...r===void 0?e.toolPolicy==="builtin"?{}:{noTools:"all"}:{tools:[r.name],customTools:[F]}}),d||(await i.bindExtensions({}),d)?t:(await i.prompt(e.userPrompt),d?t:m(i,T))}catch{return t}finally{g(!1)}})();try{return await Promise.race([v,R])}finally{clearTimeout(p)}}s(f,"runHeadless");function b(e){return f(e,null,!1,(t,n)=>n)}s(b,"headlessToolCall");function ee(e){return f(e,"",!1,t=>z(t.messages))}s(ee,"headlessText");function te(e){return f(e,"failed",!0,()=>"completed")}s(te,"headlessTurn");export{ee as headlessText,b as headlessToolCall,te as headlessTurn};
@@ -6,6 +6,7 @@ export interface LaunchPlacement {
6
6
  cwd: string;
7
7
  name: string;
8
8
  resuming: boolean;
9
+ launchJson?: string;
9
10
  }
10
11
  /** A handle to a node's running engine container. The broker host supervises via
11
12
  * the broker pid recorded as pi_pid; no tmux placement coords exist (the engine
@@ -28,6 +29,8 @@ export interface TeardownOptions {
28
29
  * close handler passes its response's `close` so the caller's own broker relay
29
30
  * outlives the response even when the handler awaits I/O after queuing. */
30
31
  startAfter?: Promise<unknown>;
32
+ /** Why the stop was requested; stored on the live execution row (`stop_reason`). */
33
+ reason?: string;
31
34
  }
32
35
  /** The only completion signal a caller may use for post-teardown work. A false
33
36
  * result means the original engine tree could not be confirmed dead, so no
@@ -51,12 +54,20 @@ export interface Host {
51
54
  * reaches around the abstraction. */
52
55
  signal(nodeId: string, sig: NodeJS.Signals): Promise<void>;
53
56
  }
57
+ /** The launch recipe stored in `executions.launch_json`: the invocation, the
58
+ * config snapshot, the node's `scopes` (null when unnarrowed) and the scrubbed
59
+ * `models` object (null when the operator has no models.json) — everything a
60
+ * runner on another machine needs to rebuild the broker's run dir and agent dir. */
61
+ export declare function brokerLaunchJson(nodeId: string, inv: PiInvocation, cwd: string): Promise<string>;
54
62
  /** Validate the broker launch recipe before we detach a child process. This is
55
63
  * the fast-fail seam for known module/path errors: a bad engine resolve or a
56
64
  * missing plain session path throws here, before spawn(). */
57
- export declare function preflightBrokerLaunch(nodeId: string, inv: PiInvocation, cwd: string): Promise<void>;
58
- /** Queue broker teardown for the next turn, or until `opts.startAfter` settles. Completion includes
59
- * any post-teardown work, which lets the daemon drain it during shutdown. */
65
+ export declare function preflightBrokerLaunch(nodeId: string, inv: PiInvocation, cwd: string, launchJson?: string): Promise<void>;
66
+ /** Record the stop on the node's live execution row, then tear the broker down in this process: on the next event-loop
67
+ * turn, or once `opts.startAfter` settles. The row is what survives this process: when it dies before the teardown
68
+ * completes, the node-lifecycle claim holder enacts the stop from `stop_requested_at` / `stop_after_turn`
69
+ * (`enactRequestedStops`). Completion includes any post-teardown work, which lets the daemon drain it during shutdown;
70
+ * that work is this call's closure and does not outlive the process. */
60
71
  export declare function requestBrokerTeardown(nodeId: string, opts?: TeardownOptions, after?: () => Promise<void>): Promise<TeardownResult>;
61
72
  /** Isolated brokers require the Linux launcher; direct host spawn cannot enforce their filesystem or network policy. */
62
73
  export declare function isolatedBrokerLauncherAvailable(): boolean;
@@ -1,3 +1,3 @@
1
- var Pe=Object.defineProperty;var u=(e,t)=>Pe(e,"name",{value:t,configurable:!0});import{assertGranteeRunsHere as Re}from"./unsandboxed.js";import{spawn as xe}from"node:child_process";import{mkdirSync as ue,existsSync as j,unlinkSync as fe,openSync as F,closeSync as N,writeSync as Oe,chmodSync as Te,lstatSync as De}from"node:fs";import{ensureAppSpace as Ne}from"../spaces/space.js";import{sandboxCacheEnv as Ae}from"../spaces/cache-env.js";import{compileLaunch as Ce,launchStillGranted as Le}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 Be}from"./package-health.js";import{existsBeneath as V,readFileBeneath as $e,readTextBeneathIfExists as je,setModeBeneath as P,withDirBeneath as X,writeFileBeneath as G}from"../spaces/open-beneath.js";import{dirname as Q,join as w,resolve as Fe,isAbsolute as Me}from"node:path";import{fileURLToPath as me}from"node:url";import{connectViewSocket as Ge}from"./view-socket.js";import{appSpace as K}from"../layout.js";import{readConfig as Ke,readMergedLaunchConfig as He}from"../config.js";import{readRotationConfig as Je}from"../subscription-state.js";import{getNode as _}from"../canvas/index.js";import{scopesFilePath as Y,crtrHome as pe,nodeRunDir as Z,nodeRunJobDir as qe,jobDir as Ue,viewSocketPath as We,nodeAgentDir as ze,contextDir as Ve,nodeHome as Xe}from"../canvas/paths.js";import{encodeFrame as he}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 we,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 E}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 ge,storeAddress as dr}from"../conversation-store/index.js";import{takeNodeToken as mr}from"../canvas/node-tokens.js";import{personId as pr}from"../canvas/person.js";function H(){const e=Q(me(import.meta.url));return w(e,"broker-cli.js")}u(H,"resolveBrokerEntry");const hr="@earendil-works/pi-coding-agent";function wr(e,t){const n=w(Be(),"models.json"),r=w(t,"models.json"),o=je(Q(n),n);if(o===null)return;const d=JSON.parse(o),s=u(f=>Array.isArray(f)?f.map(s):f===null||typeof f!="object"?f:Object.fromEntries(Object.entries(f).filter(([i])=>!/^(apiKey|authorization|headers|token|secret)$/i.test(i)).map(([i,m])=>[i,s(m)])),"scrub"),c=`${JSON.stringify(s(d),null,2)}
2
- `;if(n===r&&o!==c){if(JSON.stringify(d)!==JSON.stringify(s(d)))throw new Error("terminal models.json contains credentials; move them into daemon secrets");P(e,r,432);return}G(e,r,c,{atomic:!0,mode:432}),P(e,r,432)}u(wr,"writeBrokerModels");function Ee(e){return e.env.CRTR_BROKER_ENGINE??lr()}u(Ee,"resolveEngineSpec");function ke(e){return e.includes("/")||e.endsWith(".jsonl")}u(ke,"isPlainLaunchSessionPath");function gr(e,t){return Me(e)?e:Fe(t,e)}u(gr,"resolvePlainLaunchPath");async function Er(e,t,n,r){if(n==="--session"&&!ke(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(!ke(r))return;const o=gr(r,t),d=ur(o);try{if(d===null)throw new ge(o);await fr().header(d)}catch(s){if(!(s instanceof ge))throw s;const c=n==="--session"?"session file":"fork source";throw new Error(`[broker] refusing to launch ${e}: launch recipe references missing ${c} '${r}' (${o})`)}}u(Er,"preflightLaunchSessionArg");async function kr(e,t,n){const r=Z(e);ue(r,{recursive:!0}),process.platform==="linux"&&j(z)&&De(r).uid===process.getuid()&&Te(r,504);const o=w(r,"broker-launch.json"),d={user:Ke("user"),launch:He(n,t.env.CRTR_PROFILE_ID||null),rotation:Je()};G(r,o,JSON.stringify({...t,configSnapshot:d}),{atomic:!0}),t.env.CRTR_SCOPES_FILE!==void 0&&G(r,Y(e),JSON.stringify((await _(e))?.scopes??[]),{atomic:!0});const s=$e(r,o).toString("utf8"),c=JSON.parse(s);if(!Array.isArray(c.argv))throw new Error(`[broker] refusing to launch ${e}: broker-launch.json is missing the argv array`);const f=Ee(t);try{const l=import.meta.resolve(f);if(l.startsWith("file:")&&!j(me(l)))throw new Error(`resolved to missing file ${l}`)}catch(l){throw new Error(`[broker] refusing to launch ${e}: cannot resolve broker engine '${f}' from ${H()} \u2014 ${l.message}`)}const i=c.argv,m=[];for(let l=0;l<i.length;l++){const R=i[l];if(R==="-e"){const A=i[++l];A!==void 0&&m.push(A);continue}if(R!=="--session"&&R!=="--fork")continue;const O=i[++l];O!==void 0&&await Er(e,n,R,O)}try{er(m)}catch(l){throw new Error(`[broker] refusing to launch ${e}: ${l.message}`)}}u(kr,"preflightBrokerLaunch");const vr=2e3,_r=2e3,yr=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(yr,r)))}return!0}u(J,"waitForTreeExit");async function Sr(e,t,n){return e.length===0?{confirmed:!0}:n&&await J(e,vr)?{confirmed:!0}:(we(e,"SIGTERM",t),await J(e,_r)?{confirmed:!0}:(we(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");async function ve(e,t){const n=await _(e),r=n?.pi_pid,o=r!=null?Ie(r,n?.pi_pid_identity??null,t.excludePid):null;return o?.reused===!0&&E({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(ve,"prepareBrokerTeardown");async function _e(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(f=>{r||(r=!0,t(f))},"settle"),d=u(()=>{try{fe(We(e.nodeId))}catch{}},"cleanupSocket"),s=u(f=>{Sr(e.tree,e.identities,f).then(o,i=>o({confirmed:!1,error:i instanceof Error?i:new Error(String(i))}))},"finish"),c=Ge(e.nodeId);c.once("error",()=>{n||(d(),s(!1))}),c.once("connect",()=>{n=!0;try{c.write(he({type:"hello",role:"controller",client_id:`daemon-shutdown-${process.pid}`})),c.write(he({type:"shutdown"}))}catch{}c.end(),d(),s(!0)})})}u(_e,"runPreparedBrokerTeardown");const q=new Map;async function nt(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 d=new Promise(i=>{o=i}),s={completion:d,resolve:o,after:n===void 0?[]:[n]};q.set(e,s);let c;try{c=await ve(e,t)}catch(i){const m={confirmed:!1,error:i instanceof Error?i:new Error(String(i))};return q.delete(e),E({level:"error",event:"broker.teardown.unconfirmed",node_id:e,error:m.error}),s.resolve(m),d}const f=u(()=>{q.delete(e),_e(c).then(async i=>{if(i.confirmed)for(const m of s.after)try{await m()}catch(l){E({level:"error",event:"broker.teardown.after_failed",node_id:e,error:l})}else E({level:"error",event:"broker.teardown.unconfirmed",node_id:e,error:i.error});s.resolve(i)},i=>{const m={confirmed:!1,error:i instanceof Error?i:new Error(String(i))};E({level:"error",event:"broker.teardown.unconfirmed",node_id:e,error:m.error}),s.resolve(m)})},"run");return t.startAfter===void 0?setImmediate(f):t.startAfter.then(f,f),d}u(nt,"requestBrokerTeardown");function ye(){return process.platform==="linux"&&j(z)}u(ye,"isolatedBrokerLauncherAvailable");const ot={async launch(e,t,n){if(Re((await _(e))?.grantee),(await _(e))?.isolated===!0&&!ye())throw new Error("isolated broker requires the Linux root launcher");await kr(e,t,n.cwd);const r=nr();if(!r.reserveSlot(e))throw or(ir().automaticReviveCap,r.size());let o=null,d,s=!1;try{const c=Ue(e);ue(c,{recursive:!0}),o=F(w(c,"broker.log"),"a");const f=Ee(t),i={...Qe(t),CRTR_BROKER_ENGINE:f,CRTR_STORE_ADDRESS:dr()};if(f!==hr){const a=t.env.NODE_OPTIONS??process.env.NODE_OPTIONS;a!==void 0&&(i.NODE_OPTIONS=a)}cr()===void 0&&ar(e);const m=(await _(e))?.run_id;if(m){const a=await _(m);if(!a||a.deleting_at)throw new Error("run is deleting")}const l=t.env.CRTR_EXECUTION_ID;if(!l)throw new Error("broker launch has no execution id");const R=mr(l),O=ye();if((await _(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 a=await _(e);if(!a)throw new Error(`missing node ${e}`);const h=a.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 Ne(h);Object.assign(i,Ae(h));const S={uid:process.getuid(),gid:y.gid},g=Z(e);for(const[p,k]of[[K(h).nodes,ze(e,h)],[K(h).nodes,Ve(e,h)],[g,qe(e)]])X(p,k,()=>{},!0),P(p,k,1528,S);P(g,w(g,"broker-launch.json"),416,S),V(g,Y(e))&&P(g,Y(e),416,S);const te=w(g,"system-prompt.md");V(g,te)&&P(g,te,432,S);for(const p of["output-schema.json","situational-context.md"]){const k=w(g,p);V(g,k)&&P(g,k,432,S)}const ne=a.isolated===!0,b=Xe(e,h,ne);ne&&(X(K(h).nodes,b,()=>{},!0),P(K(h).nodes,b,1528,S),i.HOME=b,i.PI_CODING_AGENT_DIR=w(b,".pi","agent"));const W=w(b,".pi","agent");X(b,W,()=>{},!0),wr(b,W);const oe=w(W,"settings.json"),Se=w(Q(H()),"../../builtin-pi-packages/pi-crtr-extensions");G(b,oe,`${JSON.stringify({packages:[Se]})}
3
- `,{atomic:!0,mode:432}),P(b,oe,432);const ie=w(Z(e),`token-${l}`),L=F(ie,"wx+",384);fe(ie),Oe(L,R);const se=[F(`/proc/self/fd/${L}`,"r"),F(`/proc/self/fd/${L}`,"r")];N(L);const ae={nodeId:e,app:h,sub:a.sub??pr(),grantId:a.grant_id??null,scopes:a.scopes??null,isolated:a.isolated===!0,...a.isolated===!0?{cwd:a.cwd}:{},command:[process.execPath,H(),"--canvas-home",pe(),"--epoch",r.epoch(),e],env:Object.fromEntries(Object.entries({...i,...a.isolated===!0?{PWD:a.cwd}:{}}).filter(p=>p[1]!==void 0)),auditMissing:u(p=>E({level:"warn",event:"broker.mount.missing",node_id:e,fields:{source:p}}),"auditMissing")};try{let p;for(const D of se){const B=await de(),v=await Ce(ae);v.broker=!0;const $=await M({operation:"launch",spec:v},[D]);if(!("pid"in $))throw new Error("launcher did not return a pid");if(await de()===B||await Le(ae,v)){p=$.pid;break}E({level:"info",event:"broker.launch.regranted",node_id:e,fields:{pid:$.pid}}),await M({operation:"stop",pid:$.pid,signal:"SIGKILL"}).catch(()=>{})}if(p===void 0)throw new Error("grant changed during every launch attempt");const k=p,be=Date.now(),ce=new Promise(D=>{const B=setInterval(()=>{I(k)||(clearInterval(B),M({operation:"exit.status",pid:k}).then(v=>"oomKilled"in v&&v.oomKilled,()=>!1).then(v=>{E({level:v?"warn":"info",event:"broker.exited",node_id:e,fields:{pid:k,uptime_ms:Date.now()-be,oom_killed:v}}),D({code:null,signal:null,...v?{oomKilled:!0}:{}})}))},250);B.unref()});N(o),o=null;const le={pid:k,exited:ce};return r.register(e,le),s=!0,ce.then(async D=>await r.onChildExit(e,D,l)),le}finally{for(const p of se)N(p)}}const A=await Ye(),T=xe(A,[H(),"--canvas-home",pe(),"--epoch",r.epoch(),e],{cwd:n.cwd,detached:!0,stdio:["ignore",o,o,"pipe"],env:i});d=T;const C=T.stdio[3];if(!C||!("end"in C))throw new Error("broker token pipe did not open");C.on("error",a=>E({event:"broker.token_pipe.failed",level:"error",node_id:e,error:a})),C.end(R),N(o),o=null;const ee=Date.now(),re=new Promise(a=>{let h=!1;const x=u(y=>{h||(h=!0,a(y))},"finish");T.once("exit",(y,S)=>{E({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=>{E({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),s=!0,re.then(async a=>await r.onChildExit(e,a,l))),U}catch(c){if(!s&&d?.pid!=null)try{d.kill("SIGTERM")}catch{}throw c}finally{s||r.releaseReservation(e),o!==null&&N(o)}},async isAlive(e){return I((typeof e=="string"?await _(e):e)?.pi_pid)},async teardown(e,t={}){try{return _e(await ve(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 _(e))?.pi_pid;if(n!=null)try{process.kill(n,t)}catch{}}};export{ot as headlessBrokerHost,ye as isolatedBrokerLauncherAvailable,kr as preflightBrokerLaunch,nt as requestBrokerTeardown};
1
+ var Pe=Object.defineProperty;var a=(e,t)=>Pe(e,"name",{value:t,configurable:!0});import{assertGranteeRunsHere as xe}from"./unsandboxed.js";import{spawn as Te}from"node:child_process";import{mkdirSync as le,existsSync as j,unlinkSync as ue,openSync as G,closeSync as D,writeSync as Oe,chmodSync as Ne,lstatSync as De}from"node:fs";import{ensureAppSpace as Ce}from"../spaces/space.js";import{sandboxCacheEnv as Le}from"../spaces/cache-env.js";import{compileLaunch as Ae,launchStillGranted as Be}from"../spaces/mounts.js";import{grantsGeneration as fe}from"../grants/mirror.js";import{LAUNCHER_SOCKET as q}from"../../launcher/spec.js";import{launcherRequest as F}from"../../launcher/client.js";import{piAgentDir as de}from"./package-health.js";import{existsBeneath as z,readFileBeneath as $e,readTextBeneathIfExists as je,setModeBeneath as b,withDirBeneath as V,writeFileBeneath as M}from"../spaces/open-beneath.js";import{dirname as X,join as p,resolve as Ge,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 Ke,readMergedLaunchConfig as Je}from"../config.js";import{loadRotationConfig as He}from"../subscription-state.js";import{getNode as w}from"../canvas/index.js";import{withCanvasWrite as Ue}from"../canvas/db.js";import{requestExecutionStop as We}from"../canvas/executions.js";import{scopesFilePath as Q,crtrHome as pe,nodeRunDir as Y,nodeRunJobDir as qe,jobDir as ze,viewSocketPath as Ve,nodeAgentDir as Xe,contextDir as Qe,nodeHome as Ye}from"../canvas/paths.js";import{encodeFrame as he}from"./broker-protocol.js";import{buildBrokerEnv as Ze}from"./spawn-env-rows.js";import{hostExecPathFresh as Ie}from"./branded-host.js";import{isPidAlive as Z,killProcessTreePids as we,isAnyPidAlive as er,captureTeardownSnapshot as rr}from"../canvas/pid.js";import{assertMandatoryCanvasExtensions as tr}from"./canvas-extensions.js";import{appMemoryFull as nr,appMemoryTooSmall as or,boundFleet as ir,brokerCapReached as sr,brokerThresholdsForDaemon as ar}from"./fleet.js";import{admitBrokerMemory as cr}from"./memory-admission.js";import{emitEvent as g}from"../events/emit.js";import{bindBrokerEventSource as lr,eventSource as ur}from"../events/source.js";import{envBrokerEngine as fr}from"../../shared/env.js";import{conversationIdFromPath as dr,conversationStore as mr,ConversationNotFoundError as ge}from"../conversation-store/index.js";import{mintNodeToken as pr}from"../canvas/node-tokens.js";import{personId as hr}from"../canvas/person.js";function J(){const e=X(me(import.meta.url));return p(e,"broker-cli.js")}a(J,"resolveBrokerEntry");const wr="@earendil-works/pi-coding-agent";function Ee(){const e=p(de(),"models.json"),t=je(X(e),e);if(t===null)return null;const o=JSON.parse(t),n=a(r=>Array.isArray(r)?r.map(n):r===null||typeof r!="object"?r:Object.fromEntries(Object.entries(r).filter(([s])=>!/^(apiKey|authorization|headers|token|secret)$/i.test(s)).map(([s,c])=>[s,n(c)])),"scrub");return{text:t,clean:`${JSON.stringify(n(o),null,2)}
2
+ `,credentialed:JSON.stringify(o)!==JSON.stringify(n(o))}}a(Ee,"scrubbedBrokerModels");function gr(e,t){const o=p(de(),"models.json"),n=p(t,"models.json"),r=Ee();if(r!==null){if(o===n&&r.text!==r.clean){if(r.credentialed)throw new Error("terminal models.json contains credentials; move them into daemon secrets");b(e,n,432);return}M(e,n,r.clean,{atomic:!0,mode:432}),b(e,n,432)}}a(gr,"writeBrokerModels");function _e(e){return e.env.CRTR_BROKER_ENGINE??fr()}a(_e,"resolveEngineSpec");function ke(e){return e.includes("/")||e.endsWith(".jsonl")}a(ke,"isPlainLaunchSessionPath");function Er(e,t){return Fe(e)?e:Ge(t,e)}a(Er,"resolvePlainLaunchPath");async function _r(e,t,o,n){if(o==="--session"&&!ke(n))throw new Error(`[broker] refusing to launch ${e}: launch recipe passes bare --session id '${n}' \u2014 the broker fatally rejects bare ids; pass the .jsonl path instead.`);if(!ke(n))return;const r=Er(n,t),s=dr(r);try{if(s===null)throw new ge(r);await mr().header(s)}catch(c){if(!(c instanceof ge))throw c;const l=o==="--session"?"session file":"fork source";throw new Error(`[broker] refusing to launch ${e}: launch recipe references missing ${l} '${n}' (${r})`)}}a(_r,"preflightLaunchSessionArg");async function kr(e,t,o){const n=Ee();return JSON.stringify({...t,configSnapshot:{user:Ke("user"),launch:Je(o,t.env.CRTR_PROFILE_ID||null),rotation:await He()},scopes:(await w(e))?.scopes??null,models:n===null?null:JSON.parse(n.clean)})}a(kr,"brokerLaunchJson");async function vr(e,t,o,n){const r=Y(e);le(r,{recursive:!0}),process.platform==="linux"&&j(q)&&De(r).uid===process.getuid()&&Ne(r,504);const s=p(r,"broker-launch.json");M(r,s,n??await kr(e,t,o),{atomic:!0}),t.env.CRTR_SCOPES_FILE!==void 0&&M(r,Q(e),JSON.stringify((await w(e))?.scopes??[]),{atomic:!0});const c=$e(r,s).toString("utf8"),l=JSON.parse(c);if(!Array.isArray(l.argv))throw new Error(`[broker] refusing to launch ${e}: broker-launch.json is missing the argv array`);const k=_e(t);try{const u=import.meta.resolve(k);if(u.startsWith("file:")&&!j(me(u)))throw new Error(`resolved to missing file ${u}`)}catch(u){throw new Error(`[broker] refusing to launch ${e}: cannot resolve broker engine '${k}' from ${J()} \u2014 ${u.message}`)}const f=l.argv,O=[];for(let u=0;u<f.length;u++){const R=f[u];if(R==="-e"){const C=f[++u];C!==void 0&&O.push(C);continue}if(R!=="--session"&&R!=="--fork")continue;const x=f[++u];x!==void 0&&await _r(e,o,R,x)}try{tr(O)}catch(u){throw new Error(`[broker] refusing to launch ${e}: ${u.message}`)}}a(vr,"preflightBrokerLaunch");const yr=2e3,Sr=2e3,br=150;async function H(e,t){const o=Date.now()+t;for(;er(e);){const n=o-Date.now();if(n<=0)return!1;await new Promise(r=>setTimeout(r,Math.min(br,n)))}return!0}a(H,"waitForTreeExit");async function Rr(e,t,o){return e.length===0?{confirmed:!0}:o&&await H(e,yr)?{confirmed:!0}:(we(e,"SIGTERM",t),await H(e,Sr)?{confirmed:!0}:(we(e,"SIGKILL",t),await H(e,5e3)?{confirmed:!0}:{confirmed:!1,error:new Error(`broker process tree for ${e.join(", ")} remained alive after SIGKILL`)}))}a(Rr,"terminateBrokerTree");async function ve(e,t){const o=await w(e),n=o?.pi_pid,r=n!=null?rr(n,o?.pi_pid_identity??null,t.excludePid):null;return r?.reused===!0&&g({level:"warn",event:"broker.teardown.pid_reuse_refused",node_id:e,fields:{recorded_pid:n,expected_identity:o?.pi_pid_identity??null}}),{tree:r?.tree??[],identities:r?.identities??null,nodeId:e,launcherPid:j(q)&&r?.tree.includes(n)?n:null}}a(ve,"prepareBrokerTeardown");async function ye(e){if(e.launcherPid!==null){try{await F({operation:"stop",pid:e.launcherPid})}catch(t){return Z(e.launcherPid)?{confirmed:!1,error:t instanceof Error?t:new Error(String(t))}:{confirmed:!0}}return await H([e.launcherPid],5e3)?{confirmed:!0}:{confirmed:!1,error:new Error(`launcher pid ${e.launcherPid} remained alive`)}}return new Promise(t=>{let o=!1,n=!1;const r=a(k=>{n||(n=!0,t(k))},"settle"),s=a(()=>{try{ue(Ve(e.nodeId))}catch{}},"cleanupSocket"),c=a(k=>{Rr(e.tree,e.identities,k).then(r,f=>r({confirmed:!1,error:f instanceof Error?f:new Error(String(f))}))},"finish"),l=Me(e.nodeId);l.once("error",()=>{o||(s(),c(!1))}),l.once("connect",()=>{o=!0;try{l.write(he({type:"hello",role:"controller",client_id:`daemon-shutdown-${process.pid}`})),l.write(he({type:"shutdown"}))}catch{}l.end(),s(),c(!0)})})}a(ye,"runPreparedBrokerTeardown");async function at(e,t={},o){let n;try{await We(e,{afterTurn:t.startAfter!==void 0,reason:t.reason??"teardown"}),n=await ve(e,t)}catch(r){const s={confirmed:!1,error:r instanceof Error?r:new Error(String(r))};return g({level:"error",event:"broker.teardown.unconfirmed",node_id:e,error:s.error}),s}return await new Promise(r=>{const s=a(()=>{ye(n).then(async c=>{if(c.confirmed){if(o!==void 0)try{await o()}catch(l){g({level:"error",event:"broker.teardown.after_failed",node_id:e,error:l})}}else g({level:"error",event:"broker.teardown.unconfirmed",node_id:e,error:c.error});r(c)},c=>{const l={confirmed:!1,error:c instanceof Error?c:new Error(String(c))};g({level:"error",event:"broker.teardown.unconfirmed",node_id:e,error:l.error}),r(l)})},"run");t.startAfter===void 0?setImmediate(s):t.startAfter.then(s,s)})}a(at,"requestBrokerTeardown");function Se(){return process.platform==="linux"&&j(q)}a(Se,"isolatedBrokerLauncherAvailable");const ct={async launch(e,t,o){if(xe((await w(e))?.grantee),(await w(e))?.isolated===!0&&!Se())throw new Error("isolated broker requires the Linux root launcher");await vr(e,t,o.cwd,o.launchJson);const n=ir();if(!await n.reserveSlot(e))throw sr(ar().automaticReviveCap,await n.occupancy());let r=null,s,c=!1;try{const l=ze(e);le(l,{recursive:!0}),r=G(p(l,"broker.log"),"a");const k=_e(t),f={...await Ze(t),CRTR_BROKER_ENGINE:k};if(k!==wr){const i=t.env.NODE_OPTIONS??process.env.NODE_OPTIONS;i!==void 0&&(f.NODE_OPTIONS=i);const d=t.env.CRTR_TEST_PG_URL??process.env.CRTR_TEST_PG_URL;d!==void 0&&(f.CRTR_TEST_PG_URL=d)}ur()===void 0&&lr(e);const O=(await w(e))?.run_id;if(O){const i=await w(O);if(!i||i.deleting_at)throw new Error("run is deleting")}const u=t.env.CRTR_EXECUTION_ID;if(!u)throw new Error("broker launch has no execution id");const R=await Ue(i=>pr(i,u,e,new Date().toISOString())),x=Se();if((await w(e))?.isolated===!0&&!x)throw new Error("isolated broker requires the Linux root launcher");if(process.platform==="linux"&&process.env.CRTR_LAUNCHER_SOCKET&&!x)throw new Error("root launcher socket is unavailable; refusing an unsandboxed broker");if(x){const i=await w(e);if(!i)throw new Error(`missing node ${e}`);const d=i.grantee??"app:terminal",P=await cr(e,{useMemo:!1});if(P.verdict==="denied")throw nr(P);if(P.verdict==="too_small")throw or(P);const v=await Ce(d);Object.assign(f,Le(d));const y={uid:process.getuid(),gid:v.gid},h=Y(e);for(const[m,E]of[[K(d).nodes,Xe(e,d)],[K(d).nodes,Qe(e,d)],[h,qe(e)]])V(m,E,()=>{},!0),b(m,E,1528,y);b(h,p(h,"broker-launch.json"),416,y),z(h,Q(e))&&b(h,Q(e),416,y);const re=p(h,"system-prompt.md");z(h,re)&&b(h,re,432,y);for(const m of["output-schema.json","situational-context.md"]){const E=p(h,m);z(h,E)&&b(h,E,432,y)}const te=i.isolated===!0,S=Ye(e,d,te);te&&(V(K(d).nodes,S,()=>{},!0),b(K(d).nodes,S,1528,y),f.HOME=S,f.PI_CODING_AGENT_DIR=p(S,".pi","agent"));const W=p(S,".pi","agent");V(S,W,()=>{},!0),gr(S,W);const ne=p(W,"settings.json"),be=p(X(J()),"../../builtin-pi-packages/pi-crtr-extensions");M(S,ne,`${JSON.stringify({packages:[be]})}
3
+ `,{atomic:!0,mode:432}),b(S,ne,432);const oe=p(Y(e),`token-${u}`),A=G(oe,"wx+",384);ue(oe),Oe(A,R);const ie=[G(`/proc/self/fd/${A}`,"r"),G(`/proc/self/fd/${A}`,"r")];D(A);const se={nodeId:e,app:d,sub:i.sub??hr(),grantId:i.grant_id??null,scopes:i.scopes??null,isolated:i.isolated===!0,...i.isolated===!0?{cwd:i.cwd}:{},command:[process.execPath,J(),"--canvas-home",pe(),"--epoch",n.epoch(),e],env:Object.fromEntries(Object.entries({...f,...i.isolated===!0?{PWD:i.cwd}:{}}).filter(m=>m[1]!==void 0)),auditMissing:a(m=>g({level:"warn",event:"broker.mount.missing",node_id:e,fields:{source:m}}),"auditMissing")};try{let m;for(const N of ie){const B=await fe(),_=await Ae(se);_.broker=!0;const $=await F({operation:"launch",spec:_},[N]);if(!("pid"in $))throw new Error("launcher did not return a pid");if(await fe()===B||await Be(se,_)){m=$.pid;break}g({level:"info",event:"broker.launch.regranted",node_id:e,fields:{pid:$.pid}}),await F({operation:"stop",pid:$.pid,signal:"SIGKILL"}).catch(()=>{})}if(m===void 0)throw new Error("grant changed during every launch attempt");const E=m,Re=Date.now(),ae=new Promise(N=>{const B=setInterval(()=>{Z(E)||(clearInterval(B),F({operation:"exit.status",pid:E}).then(_=>"oomKilled"in _&&_.oomKilled,()=>!1).then(_=>{g({level:_?"warn":"info",event:"broker.exited",node_id:e,fields:{pid:E,uptime_ms:Date.now()-Re,oom_killed:_}}),N({code:null,signal:null,..._?{oomKilled:!0}:{}})}))},250);B.unref()});D(r),r=null;const ce={pid:E,exited:ae};return n.register(e,ce),c=!0,ae.then(async N=>await n.onChildExit(e,N,u)),ce}finally{for(const m of ie)D(m)}}const C=await Ie(),T=Te(C,[J(),"--canvas-home",pe(),"--epoch",n.epoch(),e],{cwd:o.cwd,detached:!0,stdio:["ignore",r,r,"pipe"],env:f});s=T;const L=T.stdio[3];if(!L||!("end"in L))throw new Error("broker token pipe did not open");L.on("error",i=>g({event:"broker.token_pipe.failed",level:"error",node_id:e,error:i})),L.end(R),D(r),r=null;const I=Date.now(),ee=new Promise(i=>{let d=!1;const P=a(v=>{d||(d=!0,i(v))},"finish");T.once("exit",(v,y)=>{g({level:v===0?"info":"warn",event:"broker.exited",node_id:e,fields:{code:v,signal:y,uptime_ms:Date.now()-I}}),P({code:v,signal:y})}),T.once("error",v=>{g({level:"error",event:"broker.launch.failed",node_id:e,error:v,fields:{uptime_ms:Date.now()-I}}),P({code:null,signal:null})})});T.unref();const U={pid:T.pid??null,exited:ee};return U.pid!==null&&(n.register(e,U),c=!0,ee.then(async i=>await n.onChildExit(e,i,u))),U}catch(l){if(!c&&s?.pid!=null)try{s.kill("SIGTERM")}catch{}throw l}finally{c||n.releaseReservation(e),r!==null&&D(r)}},async isAlive(e){return Z((typeof e=="string"?await w(e):e)?.pi_pid)},async teardown(e,t={}){try{return ye(await ve(e,t))}catch(o){return Promise.resolve({confirmed:!1,error:o instanceof Error?o:new Error(String(o))})}},async signal(e,t){const o=(await w(e))?.pi_pid;if(o!=null)try{process.kill(o,t)}catch{}}};export{kr as brokerLaunchJson,ct as headlessBrokerHost,Se as isolatedBrokerLauncherAvailable,vr as preflightBrokerLaunch,at as requestBrokerTeardown};
@@ -6,4 +6,10 @@ export interface PiInvocation {
6
6
  argv: string[];
7
7
  /** env to merge into the process. */
8
8
  env: Record<string, string>;
9
+ /** `LaunchSpec.worktree`, carried into `launch_json` for the sandbox start script (D102). */
10
+ worktree?: {
11
+ repository: string;
12
+ branch: string;
13
+ base: string;
14
+ };
9
15
  }
@@ -3,26 +3,14 @@ import { type WakeOrigin } from './bearings.js';
3
3
  /** The runtime-restart continuation exactly as delivered. `revive.ts` injects
4
4
  * it as the prompt of a strict resume that follows a cleanly aborted turn. */
5
5
  export declare const RUNTIME_RESTART_CONTINUATION: string;
6
- /** The goal file — the prompt/task a node was spawned with, persisted at birth
7
- * so a fresh revive can re-read its mandate. */
6
+ /** The original spawning prompt, retained in the node row. */
8
7
  export declare function goalPath(nodeId: string): Promise<string>;
9
8
  export declare function readGoal(nodeId: string): Promise<string | null>;
10
- /** Persist the spawning prompt as the node's goal. No-op for an empty prompt
11
- * (e.g. a bare root). Idempotent enough — call once at spawn/boot. */
12
9
  export declare function writeGoal(nodeId: string, text: string): Promise<void>;
13
- /** Write the goal ONLY if the node has none yet. This is how a bare root (no
14
- * spawn prompt) acquires its mandate: the first real user message becomes the
15
- * goal. Returns true when it wrote one, false when a goal already existed or
16
- * the text was empty. Guarded so a later message never clobbers the mandate. */
10
+ /** A concurrent first user message must never overwrite the first goal. */
17
11
  export declare function captureGoalIfAbsent(nodeId: string, text: string): Promise<boolean>;
18
- /** The yield-message file — a short note `crtr node yield` records for the next
19
- * fresh/cycling revive ("on wake, do X"). It remains durable through failed
20
- * launch attempts and is cleared only when session_start confirms a boot. */
21
- export declare function yieldMessagePath(nodeId: string): Promise<string>;
22
12
  export declare function writeYieldMessage(nodeId: string, text: string): Promise<void>;
23
- /** Read the pending yield message without mutating its confirmation state. */
24
13
  export declare function readYieldMessage(nodeId: string): Promise<string | null>;
25
- /** Idempotently commit delivery of the yield message after a confirmed boot. */
26
14
  export declare function clearYieldMessage(nodeId: string): Promise<void>;
27
15
  /** List the node's context/ dir (filenames, sorted). Empty when absent. */
28
16
  export declare function listContextDir(nodeId: string): Promise<string[]>;
@@ -1,28 +1,26 @@
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(`
1
+ var E=Object.defineProperty;var r=(t,e)=>E(t,"name",{value:e,configurable:!0});import{join as _}from"node:path";import{getNode as $,subscriptionsOf as R,subscribersOf as j}from"../canvas/index.js";import{contextDir as w,nodeAgentDir as k}from"../canvas/node-agent-paths.js";import{hasReportDocuments as x}from"../feed/reports.js";import{readdirBeneath as T}from"../spaces/open-beneath.js";import{openDb as c}from"../canvas/db.js";import{bashJobCommandLine as A,bashJobPaths as D,formatBashElapsed as I}from"../bash-jobs.js";import{runningJobs as N}from"../graph/jobs.js";import{readRoadmap as v}from"./roadmap.js";import{buildWakeBearings as M}from"./bearings.js";import{personaDrift as L}from"./persona.js";import{coalesce as O,nodeMailEntry as U}from"../feed/inbox.js";import{claimKickoffMail as B}from"../canvas/deliveries.js";import{formatCard as y}from"../../shared/generated-context.js";import{mapAsync as g}from"../async-array.js";const dt=y("restart-continuation",{},"continue");async function S(t){return _(await w(t),"initial-prompt.md")}r(S,"goalPath");async function G(t){return(await(await c()).prepare("SELECT initial_prompt FROM nodes WHERE node_id = ?").get(t))?.initial_prompt??null}r(G,"readGoal");async function ut(t,e){const n=e.trim();n!==""&&await(await c()).prepare("UPDATE nodes SET initial_prompt = ? WHERE node_id = ?").run(n+`
2
+ `,t)}r(ut,"writeGoal");async function ct(t,e){const n=e.trim();return n===""?!1:(await(await c()).prepare("UPDATE nodes SET initial_prompt = ? WHERE node_id = ? AND (initial_prompt IS NULL OR trim(initial_prompt) = '')").run(n+`
3
+ `,t)).changes===1}r(ct,"captureGoalIfAbsent");async function lt(t,e){const n=e.trim();n!==""&&await(await c()).prepare("UPDATE nodes SET yield_note = ? WHERE node_id = ?").run(n+`
4
+ `,t)}r(lt,"writeYieldMessage");async function W(t){return(await(await c()).prepare("SELECT yield_note FROM nodes WHERE node_id = ?").get(t))?.yield_note?.trim()||null}r(W,"readYieldMessage");async function pt(t){await(await c()).prepare("UPDATE nodes SET yield_note = NULL WHERE node_id = ?").run(t)}r(pt,"clearYieldMessage");async function ft(t){return(await H(t,await w(t))).sort()}r(ft,"listContextDir");async function C(t){return await x(t)}r(C,"hasRetainedReports");async function H(t,e){try{return T(await k(t),e).map(n=>n.name)}catch(n){if(n.code==="ENOENT")return[];throw n}}r(H,"agentDirNames");async function mt(t,e){const n=t.node_id,a=await W(n),o=t.run_id?[]:await B(n,e),s=o.map(f=>f.message.messageId),i=o.map(U);let d=null;if(i.length>0){const f=r(u=>{const h=u.data?.cards;return Array.isArray(h)?h.filter(b=>typeof b=="string"):[]},"cardsFor"),m=[];for(const u of i)(f(u).length>0||m.length===0)&&m.push([]),m.at(-1).push(u);d=(await g(m,async u=>[...f(u[0]),(await O(u)).map(h=>h.text).join(`
4
5
 
5
6
  `)].join(`
6
7
 
7
8
  `))).join(`
8
9
 
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>
10
- ${o.join(`
11
- `)}
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>
10
+ `)}const l=await L(n),p=l?.guidance===void 0||l.guidance===""?null:l.guidance;return{yieldMsg:a,unreadDigest:d,unreadMessageIds:s,driftGuidance:p}}r(mt,"drainBearings");async function P(t,e){const n=(await g((await R(t)).filter(o=>o.active),async o=>await $(o.node_id))).filter(o=>o!==null&&(o.status==="active"||o.status==="idle")),a=[];if(n.length>0){const o=n.length,s=o===1?"it has":"they have",i=o===1?"Its":"Their";a.push(`Awaiting ${o} node${o===1?"":"s"} \u2014 ${s} not finished. ${i} reports will wake you.`);for(const d of n)a.push(` - ${d.name} (${d.node_id}) \u2014 ${d.status}`);a.push("",e??"(no unread reports)")}else a.push("Awaiting 0 nodes."),a.push("",e??"(no unread reports)");return`<feed>
13
11
  ${a.join(`
14
12
  `)}
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
- ${u.length>0?u.join(`
19
- `):"(empty)"}
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
- </persona-transition>`),k("revive",{},`
25
- ${a.join(`
13
+ </feed>`}r(P,"feedBlock");function Y(t,e){const n=(t??A(e)).trim()||"(no command)";return n.length>120?`${n.slice(0,117)}\u2026`:n}r(Y,"jobLabel");async function J(t){const e=await w(t),n=await N(await c(),t);if(n.length===0)return null;const a=Date.now(),o=n.length===1,s=[`${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)s.push(` - ${i.jobId} \u2014 ${Y(i.purpose,i.command)} \xB7 running ${I(a-i.startedAtMs)} \xB7 log ${D(e,i.jobId).jobLog}`);return s.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>
14
+ ${s.join(`
15
+ `)}
16
+ </background-jobs>`}r(J,"backgroundJobsBlock");async function ht(t,e,n){const a=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(M(n));const s=await v(a);if(!(s!==null&&s.trim()!=="")&&!await C(a)){const p=await G(a);p!==null&&p.trim()!==""&&o.push(`<goal file="${await S(a)}">
17
+ ${p.trim()}
18
+ </goal>`)}const d=await J(a);d!==null&&o.push(d),o.push(await P(a,e.unreadDigest)),o.push(e.yieldMsg!==null?`<yield-message>
19
+ ${e.yieldMsg.trim()}
20
+ </yield-message>`:"<yield-message/>");const l=(await j(a)).length>0;return o.push(l?"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>
21
+ Your role was changed while you were away. ${e.driftGuidance}
22
+ </persona-transition>`),y("revive",{},`
23
+ ${o.join(`
26
24
 
27
25
  `)}
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};
26
+ `)}r(ht,"buildReviveKickoff");export{dt as RUNTIME_RESTART_CONTINUATION,ht as buildReviveKickoff,ct as captureGoalIfAbsent,pt as clearYieldMessage,mt as drainBearings,S as goalPath,C as hasRetainedReports,ft as listContextDir,G as readGoal,W as readYieldMessage,ut as writeGoal,lt as writeYieldMessage};
@@ -1 +1 @@
1
- import{readMergedLaunchConfig as o}from"../config.js";process.once("message",e=>{try{process.send?.({config:o(e.cwd,e.profileId)})}catch(r){process.send?.({error:r instanceof Error?r.message:String(r)})}});
1
+ import{readMergedLaunchConfig as n}from"../config.js";import{setPersonId as e}from"../canvas/person-state.js";import{installPersonSnapshot as p}from"../scoped-state/person-store.js";process.once("message",r=>{try{r.person!==void 0&&r.snapshot!==void 0&&(e(r.person),p(r.person,r.snapshot)),process.send?.({config:n(r.cwd,r.profileId)})}catch(o){process.send?.({error:o instanceof Error?o.message:String(o)})}});
@@ -1,3 +1,3 @@
1
- var V=Object.defineProperty;var s=(e,r)=>V(e,"name",{value:r,configurable:!0});import{envProfileId as T}from"../../shared/env.js";import{mkdirSync as M}from"node:fs";import{join as U}from"node:path";import{readMergedLaunchConfig as D}from"../config.js";import{fork as F}from"node:child_process";import{fileURLToPath as $}from"node:url";import{freshChildNodeExecPath as G,recheckChildNode as K}from"./branded-host.js";import{LAUNCH_SYSTEM_PROMPT as W}from"./launch-prompt.js";import{nodeEnv as X}from"./nodes.js";import{editorLabel as B}from"../canvas/index.js";import{CANVAS_EXTENSIONS as ye,CANVAS_STOPHOOK_PATH as ve,CANVAS_INBOX_WATCHER_PATH as Le,CANVAS_RECAP_PATH as Re,CANVAS_GOAL_CAPTURE_PATH as be,CANVAS_PASSIVE_CONTEXT_PATH as He,CANVAS_CONTEXT_INTRO_PATH as Ve,CANVAS_TOOL_GUIDE_PATH as Me,CANVAS_DOC_SUBSTRATE_PATH as Ue,CANVAS_STRUCTURED_OUTPUT_PATH as De,CANVAS_BASH_VALVE_PATH as Fe}from"./canvas-extensions.js";import{nodeRunDir as j}from"../canvas/paths.js";import{writeFileBeneath as z}from"../spaces/open-beneath.js";import{projectOutputSchema as Y}from"./structured-output.js";import{CANVAS_EXTENSIONS as Q,mergeCanvasExtensions as P,assertMandatoryCanvasExtensions as J}from"./canvas-extensions.js";import{modelLadders as a,defaultProvider as C,STRENGTH_ALIASES as p,MODEL_PROVIDER_KEYS as x,MODEL_STRENGTHS as A,THINKING_SUFFIXES as Z,stripThinkingSuffix as m}from"./model-selection.js";import{OPENAI_PROVIDER_ENV as Ge,configuredLadderProviders as Ke,inferPortableModelSelection as We}from"./model-selection.js";function k(e,r=a()){return r[e]}s(k,"ladderFor");const S={light:0,medium:1,strong:2,ultra:3};function q(e,r,n){const t=m(e);for(const o of[!0,!1]){const i=o?A:[...A].sort((c,u)=>S[c]-S[u]);for(const c of n)for(const u of i){const f=r[c][u];if(!(o?f!==e:m(f)!==t))return{provider:c,strength:u}}}return null}s(q,"findLadderCell");function N(e){const r=e.lastIndexOf("/"),n=r===-1?void 0:e.slice(0,r),t=r===-1?e:e.slice(r+1),o=p[t];return o!==void 0?o:n!==void 0&&n!=="anthropic"?null:t==="opus"?"strong":t==="sonnet"?"medium":t==="haiku"?"light":null}s(N,"modelTokenStrength");function w(e,r=a()){const n=N(e);return n!==null?n:q(_(e,r),r,x)?.strength??null}s(w,"resolvedModelStrength");function ee(e){return e==="review"||e.startsWith("review/")||e.includes("/reviewers/")}s(ee,"isReviewQualityKind");function ne(e,r,n,t=a()){if(r===void 0)return n;if(!ee(e)||n===void 0)return r;const o=w(r,t),i=w(n,t);return o===null||i===null?r:S[o]<S[i]?n:r}s(ne,"floorReviewModel");function I(e){if(e.includes("/")){const r=e.lastIndexOf("/"),n=e.slice(0,r),t=e.slice(r+1);return n!==""&&(p[t]!==void 0||n==="anthropic"&&(t==="opus"||t==="sonnet"||t==="haiku"))}return p[e]!==void 0||e==="opus"||e==="sonnet"||e==="haiku"}s(I,"isPortableModelToken");function O(e,r=a()){const n=N(e);if(n!==null)return e.includes("/")?{family:e.slice(0,e.lastIndexOf("/")),strength:n}:e==="opus"||e==="sonnet"||e==="haiku"?{family:"anthropic",strength:n}:{family:C(r),strength:n}}s(O,"logicalModelIntent");function Te(e,r=a()){return I(e)?O(e,r):void 0}s(Te,"explicitModelIntent");function _(e,r=a()){if(e.includes("/")){const t=e.indexOf("/"),o=e.slice(0,t),i=e.slice(t+1),c=p[i];if(c!==void 0&&(o==="anthropic"||o==="openai"))return k(o,r)[c];if(o==="anthropic"){if(i==="opus")return r.anthropic.strong;if(i==="sonnet")return r.anthropic.medium;if(i==="haiku")return r.anthropic.light}return e}const n=p[e];return n!==void 0?k(C(r),r)[n]:e==="opus"?r.anthropic.strong:e==="sonnet"?r.anthropic.medium:e==="haiku"?r.anthropic.light:e}s(_,"normalizeModel");function y(e){const r=e.lastIndexOf(":");if(r<=0)return;const n=e.slice(r+1);return Z.has(n)?n:void 0}s(y,"thinkingSuffixOf");function re(e=x){const r=e.length>0?e:x,n=a(),t=[];for(const o of A)for(const i of r)t.push(n[i][o]);return t}s(re,"interleavedLadderCycle");function Pe(e,r=1,n){const t=re(n),o=_(e),i=m(o),c=y(o);let u=t.findIndex(f=>m(f)===i&&y(f)===c);return u===-1&&(u=t.findIndex(f=>m(f)===i)),u===-1?t[0]:t[(u+r+t.length)%t.length]}s(Pe,"nextLadderModel");function v(e,r,n,t){const o=t.kinds[e],i=t.modelLadders,c=r==="orchestrator"?o?.orchestratorModel??o?.model:o?.model,u=n.modelExact===!0?n.model:ne(e,n.model,c,i),f=n.modelExact===!0||n.modelOverride===!0&&n.model!==void 0&&!I(n.model),l=n.modelExact===!0?u:u!==void 0?_(u,i):void 0,h=f?void 0:n.modelIntent??(u!==void 0?O(u,i):void 0);return{launch:{model:l,modelIntent:h,modelExact:f?!0:void 0,tools:o?.tools??[],extensions:P([...Q,...o?.extensions??[]]),systemPrompt:W,env:{...n.extraEnv??{},...h?{CRTR_MODEL_INTENT:`${h.family}/${h.strength}`}:{}}},lifecycle:n.lifecycle}}s(v,"buildLaunchSpecFromMerged");function Ce(e,r,n){return v(e,r,n,D(n.cwd??process.cwd(),n.profileId!==void 0?n.profileId:T()||null))}s(Ce,"buildLaunchSpec");async function ke(e,r,n){const t=n.cwd??process.cwd(),o=n.profileId!==void 0?n.profileId:T()||null,i=await oe(t,o);return v(e,r,n,i)}s(ke,"buildLaunchSpecAsync");const L=15e3;function te(e,r,n){const t=r!==null?`was killed by ${r}`:`exited with code ${e}`,o=n.trim().split(`
1
+ var V=Object.defineProperty;var s=(e,r)=>V(e,"name",{value:r,configurable:!0});import{envProfileId as T}from"../../shared/env.js";import{readMergedLaunchConfig as M}from"../config.js";import{fork as U}from"node:child_process";import{fileURLToPath as D}from"node:url";import{personId as $,PersonUnresolvedError as F,PersonOutsideRequestError as G}from"../canvas/person-state.js";import{currentSnapshot as K,PersonSettingsNotLoadedError as W}from"../scoped-state/person-store.js";import{freshChildNodeExecPath as X,recheckChildNode as B}from"./branded-host.js";import{LAUNCH_SYSTEM_PROMPT as j}from"./launch-prompt.js";import{nodeEnv as z}from"./nodes.js";import{editorLabel as Y}from"../canvas/index.js";import{CANVAS_EXTENSIONS as Ne,CANVAS_STOPHOOK_PATH as Ie,CANVAS_INBOX_WATCHER_PATH as Oe,CANVAS_RECAP_PATH as ve,CANVAS_GOAL_CAPTURE_PATH as Le,CANVAS_PASSIVE_CONTEXT_PATH as ye,CANVAS_CONTEXT_INTRO_PATH as Re,CANVAS_TOOL_GUIDE_PATH as be,CANVAS_DOC_SUBSTRATE_PATH as He,CANVAS_STRUCTURED_OUTPUT_PATH as Ve,CANVAS_BASH_VALVE_PATH as Me}from"./canvas-extensions.js";import{CANVAS_EXTENSIONS as Q,mergeCanvasExtensions as P,assertMandatoryCanvasExtensions as J}from"./canvas-extensions.js";import{modelLadders as a,defaultProvider as k,STRENGTH_ALIASES as p,MODEL_PROVIDER_KEYS as x,MODEL_STRENGTHS as E,THINKING_SUFFIXES as Z,stripThinkingSuffix as m}from"./model-selection.js";import{OPENAI_PROVIDER_ENV as De,configuredLadderProviders as $e,inferPortableModelSelection as Fe}from"./model-selection.js";function C(e,r=a()){return r[e]}s(C,"ladderFor");const S={light:0,medium:1,strong:2,ultra:3};function q(e,r,n){const t=m(e);for(const o of[!0,!1]){const i=o?E:[...E].sort((c,u)=>S[c]-S[u]);for(const c of n)for(const u of i){const f=r[c][u];if(!(o?f!==e:m(f)!==t))return{provider:c,strength:u}}}return null}s(q,"findLadderCell");function w(e){const r=e.lastIndexOf("/"),n=r===-1?void 0:e.slice(0,r),t=r===-1?e:e.slice(r+1),o=p[t];return o!==void 0?o:n!==void 0&&n!=="anthropic"?null:t==="opus"?"strong":t==="sonnet"?"medium":t==="haiku"?"light":null}s(w,"modelTokenStrength");function N(e,r=a()){const n=w(e);return n!==null?n:q(A(e,r),r,x)?.strength??null}s(N,"resolvedModelStrength");function ee(e){return e==="review"||e.startsWith("review/")||e.includes("/reviewers/")}s(ee,"isReviewQualityKind");function ne(e,r,n,t=a()){if(r===void 0)return n;if(!ee(e)||n===void 0)return r;const o=N(r,t),i=N(n,t);return o===null||i===null?r:S[o]<S[i]?n:r}s(ne,"floorReviewModel");function I(e){if(e.includes("/")){const r=e.lastIndexOf("/"),n=e.slice(0,r),t=e.slice(r+1);return n!==""&&(p[t]!==void 0||n==="anthropic"&&(t==="opus"||t==="sonnet"||t==="haiku"))}return p[e]!==void 0||e==="opus"||e==="sonnet"||e==="haiku"}s(I,"isPortableModelToken");function O(e,r=a()){const n=w(e);if(n!==null)return e.includes("/")?{family:e.slice(0,e.lastIndexOf("/")),strength:n}:e==="opus"||e==="sonnet"||e==="haiku"?{family:"anthropic",strength:n}:{family:k(r),strength:n}}s(O,"logicalModelIntent");function Ee(e,r=a()){return I(e)?O(e,r):void 0}s(Ee,"explicitModelIntent");function A(e,r=a()){if(e.includes("/")){const t=e.indexOf("/"),o=e.slice(0,t),i=e.slice(t+1),c=p[i];if(c!==void 0&&(o==="anthropic"||o==="openai"))return C(o,r)[c];if(o==="anthropic"){if(i==="opus")return r.anthropic.strong;if(i==="sonnet")return r.anthropic.medium;if(i==="haiku")return r.anthropic.light}return e}const n=p[e];return n!==void 0?C(k(r),r)[n]:e==="opus"?r.anthropic.strong:e==="sonnet"?r.anthropic.medium:e==="haiku"?r.anthropic.light:e}s(A,"normalizeModel");function v(e){const r=e.lastIndexOf(":");if(r<=0)return;const n=e.slice(r+1);return Z.has(n)?n:void 0}s(v,"thinkingSuffixOf");function re(e=x){const r=e.length>0?e:x,n=a(),t=[];for(const o of E)for(const i of r)t.push(n[i][o]);return t}s(re,"interleavedLadderCycle");function Ae(e,r=1,n){const t=re(n),o=A(e),i=m(o),c=v(o);let u=t.findIndex(f=>m(f)===i&&v(f)===c);return u===-1&&(u=t.findIndex(f=>m(f)===i)),u===-1?t[0]:t[(u+r+t.length)%t.length]}s(Ae,"nextLadderModel");function L(e,r,n,t){const o=t.kinds[e],i=t.modelLadders,c=r==="orchestrator"?o?.orchestratorModel??o?.model:o?.model,u=n.modelExact===!0?n.model:ne(e,n.model,c,i),f=n.modelExact===!0||n.modelOverride===!0&&n.model!==void 0&&!I(n.model),l=n.modelExact===!0?u:u!==void 0?A(u,i):void 0,h=f?void 0:n.modelIntent??(u!==void 0?O(u,i):void 0);return{launch:{model:l,modelIntent:h,modelExact:f?!0:void 0,tools:o?.tools??[],extensions:P([...Q,...o?.extensions??[]]),systemPrompt:j,env:{...n.extraEnv??{},...h?{CRTR_MODEL_INTENT:`${h.family}/${h.strength}`}:{}}},lifecycle:n.lifecycle}}s(L,"buildLaunchSpecFromMerged");function _e(e,r,n){return L(e,r,n,M(n.cwd??process.cwd(),n.profileId!==void 0?n.profileId:T()||null))}s(_e,"buildLaunchSpec");async function Te(e,r,n){const t=n.cwd??process.cwd(),o=n.profileId!==void 0?n.profileId:T()||null,i=await oe(t,o);return L(e,r,n,i)}s(Te,"buildLaunchSpecAsync");const y=15e3;function te(e,r,n){const t=r!==null?`was killed by ${r}`:`exited with code ${e}`,o=n.trim().split(`
2
2
  `).slice(-8).join(`
3
- `).slice(-1500);return`launch config subprocess ${t}${o!==""?`: ${o}`:" (no stderr output)"}`}s(te,"describeLaunchConfigExit");class R extends Error{static{s(this,"LaunchConfigWorkerCrash")}}async function oe(e,r,n={}){const t=n.execPath??await G(),o=n.workerPath??$(new URL("./launch-config-worker.js",import.meta.url));try{return await b(e,r,t,o)}catch(i){if(!(i instanceof R))throw i;const c=await K(t);if(c===t)throw i;return b(e,r,c,o)}}s(oe,"readMergedLaunchConfigAsync");function b(e,r,n,t){return new Promise((o,i)=>{const c=F(t,[],{execPath:n,stdio:["ignore","ignore","pipe","ipc"],serialization:"advanced"});let u="";c.stderr?.setEncoding("utf8").on("data",d=>{u=(u+d).slice(-8192)}),c.send({cwd:e,profileId:r});let f=!1;const l=s(d=>{f||(f=!0,clearTimeout(h),c.connected&&c.disconnect(),c.killed||c.kill("SIGKILL"),d())},"finish"),h=setTimeout(()=>l(()=>i(new Error(`timed out after ${L}ms reading launch config for ${e}`))),L);c.once("message",d=>{d.error!==void 0?l(()=>i(new Error(d.error))):d.config!==void 0?l(()=>o(d.config)):l(()=>i(new Error("launch config subprocess returned no result")))});let g=null;c.on("error",d=>{g??=d}),c.once("close",(d,H)=>{if(f)return;const E=te(d,H,u);l(()=>i(new R(g===null?E:`${E} (${g.message})`)))})})}s(b,"runLaunchConfigWorker");function ie(e,r){try{const n=j(e);M(n,{recursive:!0});const t=U(n,"system-prompt.md");return z(n,t,r,{atomic:!0}),t}catch{return null}}s(ie,"writeSystemPromptFile");function Ne(e,r={}){const n=e.launch,t=P(n?.extensions);J(t);const o=[];for(const i of t)o.push("-e",i);if(o.push("-n",B(e)),r.forkFrom!==void 0&&r.forkFrom!=="")o.push("--fork",r.forkFrom);else{const i=r.resumeSessionPath??r.resumeSessionId;i!==void 0&&o.push("--session",i),r.newCycle===!0&&o.push("--crtr-new-cycle")}if(n?.model!==void 0&&o.push("--model",n.model),n?.modelExact===!0&&o.push("--crtr-model-exact"),n?.tools!==void 0&&n.tools.length>0&&o.push("--tools",n.tools.join(",")),n?.systemPrompt!==void 0&&n.systemPrompt!==""){const i=ie(e.node_id,n.systemPrompt)??n.systemPrompt;o.push("--append-system-prompt",i)}return r.prompt!==void 0&&r.prompt!==""&&o.push(r.prompt),Y(e.node_id),{argv:o,env:X(e)}}s(Ne,"buildPiArgv");function we(e){for(const[t,o]of Object.entries(e.env))process.env[t]=o;const r={cwd:e.env.CRTR_NODE_CWD??process.cwd(),extensionPaths:[]},n=e.argv;for(let t=0;t<n.length;t++){const o=n[t];switch(o){case"-e":r.extensionPaths.push(n[++t]);break;case"-n":r.editorName=n[++t];break;case"--fork":r.forkFrom=n[++t];break;case"--session":{const i=n[++t];i.includes("/")||i.endsWith(".jsonl")?r.resumeSessionPath=i:r.resumeSessionId=i;break}case"--model":r.model=n[++t];break;case"--crtr-model-exact":r.modelExact=!0;break;case"--tools":r.tools=n[++t].split(",").filter(i=>i!=="");break;case"--append-system-prompt":r.appendSystemPromptPath=n[++t];break;case"--crtr-new-cycle":r.newCycle=!0;break;default:r.firstPrompt=o;break}}return r}s(we,"piInvocationToSdkConfig");export{Fe as CANVAS_BASH_VALVE_PATH,Ve as CANVAS_CONTEXT_INTRO_PATH,Ue as CANVAS_DOC_SUBSTRATE_PATH,ye as CANVAS_EXTENSIONS,be as CANVAS_GOAL_CAPTURE_PATH,Le as CANVAS_INBOX_WATCHER_PATH,He as CANVAS_PASSIVE_CONTEXT_PATH,Re as CANVAS_RECAP_PATH,ve as CANVAS_STOPHOOK_PATH,De as CANVAS_STRUCTURED_OUTPUT_PATH,Me as CANVAS_TOOL_GUIDE_PATH,Ge as OPENAI_PROVIDER_ENV,Ce as buildLaunchSpec,ke as buildLaunchSpecAsync,Ne as buildPiArgv,Ke as configuredLadderProviders,te as describeLaunchConfigExit,Te as explicitModelIntent,We as inferPortableModelSelection,re as interleavedLadderCycle,I as isPortableModelToken,O as logicalModelIntent,N as modelTokenStrength,Pe as nextLadderModel,_ as normalizeModel,we as piInvocationToSdkConfig,oe as readMergedLaunchConfigAsync};
3
+ `).slice(-1500);return`launch config subprocess ${t}${o!==""?`: ${o}`:" (no stderr output)"}`}s(te,"describeLaunchConfigExit");class R extends Error{static{s(this,"LaunchConfigWorkerCrash")}}async function oe(e,r,n={}){const t=n.execPath??await X(),o=n.workerPath??D(new URL("./launch-config-worker.js",import.meta.url));try{return await b(e,r,t,o)}catch(i){if(!(i instanceof R))throw i;const c=await B(t);if(c===t)throw i;return b(e,r,c,o)}}s(oe,"readMergedLaunchConfigAsync");function ie(){try{return{person:$(),snapshot:K()}}catch(e){if(e instanceof F||e instanceof G||e instanceof W)return{};throw e}}s(ie,"heldPersonSettings");function b(e,r,n,t){return new Promise((o,i)=>{const c=U(t,[],{execPath:n,stdio:["ignore","ignore","pipe","ipc"],serialization:"advanced"});let u="";c.stderr?.setEncoding("utf8").on("data",d=>{u=(u+d).slice(-8192)}),c.send({cwd:e,profileId:r,...ie()});let f=!1;const l=s(d=>{f||(f=!0,clearTimeout(h),c.connected&&c.disconnect(),c.killed||c.kill("SIGKILL"),d())},"finish"),h=setTimeout(()=>l(()=>i(new Error(`timed out after ${y}ms reading launch config for ${e}`))),y);c.once("message",d=>{d.error!==void 0?l(()=>i(new Error(d.error))):d.config!==void 0?l(()=>o(d.config)):l(()=>i(new Error("launch config subprocess returned no result")))});let g=null;c.on("error",d=>{g??=d}),c.once("close",(d,H)=>{if(f)return;const _=te(d,H,u);l(()=>i(new R(g===null?_:`${_} (${g.message})`)))})})}s(b,"runLaunchConfigWorker");function Pe(e,r={}){const n=e.launch,t=P(n?.extensions);J(t);const o=[];for(const i of t)o.push("-e",i);if(o.push("-n",Y(e)),r.forkFrom!==void 0&&r.forkFrom!=="")o.push("--fork",r.forkFrom);else{const i=r.resumeSessionPath??r.resumeSessionId;i!==void 0&&o.push("--session",i),r.newCycle===!0&&o.push("--crtr-new-cycle")}return n?.model!==void 0&&o.push("--model",n.model),n?.modelExact===!0&&o.push("--crtr-model-exact"),n?.tools!==void 0&&n.tools.length>0&&o.push("--tools",n.tools.join(",")),n?.systemPrompt!==void 0&&n.systemPrompt!==""&&o.push("--append-system-prompt",n.systemPrompt),r.prompt!==void 0&&r.prompt!==""&&o.push(r.prompt),{argv:o,env:z(e),...n?.worktree===void 0?{}:{worktree:n.worktree}}}s(Pe,"buildPiArgv");function ke(e){for(const[t,o]of Object.entries(e.env))process.env[t]=o;const r={cwd:e.env.CRTR_NODE_CWD??process.cwd(),extensionPaths:[]},n=e.argv;for(let t=0;t<n.length;t++){const o=n[t];switch(o){case"-e":r.extensionPaths.push(n[++t]);break;case"-n":r.editorName=n[++t];break;case"--fork":r.forkFrom=n[++t];break;case"--session":{const i=n[++t];i.includes("/")||i.endsWith(".jsonl")?r.resumeSessionPath=i:r.resumeSessionId=i;break}case"--model":r.model=n[++t];break;case"--crtr-model-exact":r.modelExact=!0;break;case"--tools":r.tools=n[++t].split(",").filter(i=>i!=="");break;case"--append-system-prompt":r.appendSystemPromptPath=n[++t];break;case"--crtr-new-cycle":r.newCycle=!0;break;default:r.firstPrompt=o;break}}return r}s(ke,"piInvocationToSdkConfig");export{Me as CANVAS_BASH_VALVE_PATH,Re as CANVAS_CONTEXT_INTRO_PATH,He as CANVAS_DOC_SUBSTRATE_PATH,Ne as CANVAS_EXTENSIONS,Le as CANVAS_GOAL_CAPTURE_PATH,Oe as CANVAS_INBOX_WATCHER_PATH,ye as CANVAS_PASSIVE_CONTEXT_PATH,ve as CANVAS_RECAP_PATH,Ie as CANVAS_STOPHOOK_PATH,Ve as CANVAS_STRUCTURED_OUTPUT_PATH,be as CANVAS_TOOL_GUIDE_PATH,De as OPENAI_PROVIDER_ENV,_e as buildLaunchSpec,Te as buildLaunchSpecAsync,Pe as buildPiArgv,$e as configuredLadderProviders,te as describeLaunchConfigExit,Ee as explicitModelIntent,Fe as inferPortableModelSelection,re as interleavedLadderCycle,I as isPortableModelToken,O as logicalModelIntent,w as modelTokenStrength,Ae as nextLadderModel,A as normalizeModel,ke as piInvocationToSdkConfig,oe as readMergedLaunchConfigAsync};
@@ -1 +1 @@
1
- var i=Object.defineProperty;var r=(o,e)=>i(o,"name",{value:e,configurable:!0});import{join as t}from"node:path";import{ModelRegistry as n,ModelRuntime as m}from"@earendil-works/pi-coding-agent";import{PoolCredentialStore as s}from"../pool-credential-store.js";import{piAgentDir as a}from"./package-health.js";import{secretsDir as l}from"../layout.js";async function j(){const o=a(),e=await m.create({credentials:new s(t(l(),"auth.json")),modelsPath:t(o,"models.json")});return new n(e)}r(j,"openModelRegistry");export{j as openModelRegistry};
1
+ var r=Object.defineProperty;var t=(e,o)=>r(e,"name",{value:o,configurable:!0});import{join as n}from"node:path";import{ModelRegistry as i,ModelRuntime as m}from"@earendil-works/pi-coding-agent";import{PoolCredentialStore as s}from"../pool-credential-store.js";import{piAgentDir as a}from"./package-health.js";async function g(){const e=a(),o=await m.create({credentials:new s,modelsPath:n(e,"models.json")});return new i(o)}t(g,"openModelRegistry");export{g as openModelRegistry};
@@ -10,14 +10,12 @@ export interface NodeSessionRead {
10
10
  sessionFile: string;
11
11
  /** Verbatim contents of the session `.jsonl`. */
12
12
  sessionJsonl: string;
13
- /** The assembled system prompt as last captured, or `null` if never written. */
13
+ /** The system prompt text the latest launch recipe hands pi, or `null` when the node never launched. */
14
14
  systemPrompt: string | null;
15
15
  }
16
- /** Read a node's raw conversation record off disk — no broker, no attach, no
17
- * mapping. The system prompt is NOT part of the session file (pi assembles it
18
- * per boot), so it is read from the sidecar the broker captures on every
19
- * rebind (`<jobDir>/system-prompt.md`), falling back to the one `launch.ts`
20
- * writes at spawn (`<nodeDir>/system-prompt.md`). */
16
+ /** Read a node's raw conversation record — no broker, no attach, no mapping. The system
17
+ * prompt is NOT part of the session file (pi assembles it per boot), so it is the text
18
+ * the node's latest launch recipe passes to pi as `--append-system-prompt`. */
21
19
  export declare function readNodeSession(nodeId: string): Promise<NodeSessionRead>;
22
20
  export interface NodeSnapshotRead {
23
21
  nodeId: string;
@@ -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 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
- `)}a(ye,"transcriptMarkdown");export{he as readNodeMessagesPage,ge as readNodeSession,Z as readNodeSnapshot,ye as transcriptMarkdown};
1
+ var x=Object.defineProperty;var i=(e,t)=>x(e,"name",{value:t,configurable:!0});import{openDb as _}from"../canvas/db.js";import{latestExecutionForNode as M}from"../canvas/executions.js";import{InputError as c}from"../io.js";import{conversationIdFromPath as g,conversationStore as h,ConversationNotFoundError as C}from"../conversation-store/index.js";import{fullName as N,getNode as p}from"../canvas/index.js";import{hydratePersistedAdvertisedCommandMessages as y}from"./advertised-command-invocation.js";import{SessionManager as R}from"./broker-sdk.js";import{openModelRegistry as A}from"./model-registry.js";import{BUILTIN_SLASH_COMMANDS as $}from"./pi-vendored.js";import{cycleAwareMessages as j}from"./session-cycles.js";import{projectTranscript as F}from"./session-visibility.js";import{normalizeToolGroupSummaryRecord as L}from"../../shared/tool-groups.js";import{normalizeTurnReplyRecord as T}from"../../shared/turn-replies.js";async function k(e){if(e!==null)try{return(await A()).find(e.provider,e.modelId)}catch{return}}i(k,"resolveRecordedModel");async function w(e,t){return await i(async s=>{const r=s?g(s):null;if(r===null)return null;try{return(await h().header(r)).path}catch(a){if(a instanceof C)return null;throw a}},"resolvePath")(t)}i(w,"resolveSessionFile");async function E(e){const t=await p(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 w(e,t.pi_session_file)}i(E,"readableSessionFile");function O(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}}i(O,"emptyStats");function J(e,t,n){const s=O(t,n);s.totalMessages=e.length;for(const r of e)if(r.role==="user")s.userMessages++;else if(r.role==="assistant"){s.assistantMessages++;const a=Array.isArray(r.content)?r.content:[];s.toolCalls+=a.filter(l=>l!==null&&typeof l=="object"&&l.type==="toolCall").length;const o=r.usage;o!==void 0&&(s.tokens.input+=o.input??0,s.tokens.output+=o.output??0,s.tokens.cacheRead+=o.cacheRead??0,s.tokens.cacheWrite+=o.cacheWrite??0,s.cost+=o.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}i(J,"statsFromMessages");async function ae(e){const t=await p(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 n=await w(e,t.pi_session_file);if(n===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:n,sessionJsonl:await(async()=>{const{header:s,entries:r}=await h().read(g(n));return[s,...r].map(a=>`${JSON.stringify(a)}
2
+ `).join("")})(),systemPrompt:await P(e)}}i(ae,"readNodeSession");async function P(e){const t=(await M(e))?.launchJson??null;if(t===null)return null;const n=JSON.parse(t).argv;if(!Array.isArray(n))return null;const s=n.indexOf("--append-system-prompt");return s===-1||typeof n[s+1]!="string"?null:n[s+1]}i(P,"launchSystemPrompt");async function S(e,t){const n=await(await _()).prepare(`SELECT ${t} AS raw FROM nodes WHERE node_id = ?`).get(e);try{return n?.raw==null?null:JSON.parse(n.raw)}catch{return null}}i(S,"readSummaryColumn");async function W(e){return L(await S(e,"tool_summaries_json"))}i(W,"readToolGroupSummaries");async function B(e){return T(await S(e,"turn_replies_json"))}i(B,"readTurnReplies");async function b(e){const t=await p(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 n=await w(e,t.pi_session_file);if(n===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 h().read(g(n)),a=R.inMemory(s.cwd,void 0,[s,...r]),o=a.buildSessionContext();y(o.messages);const l=j(a);l!==void 0&&y(l.map(({message:f})=>f));const u=l===void 0?void 0:F(l,{boundaryReviewId:t.review_binding?.review_id,sessionEntries:a.getEntries()}),m=u?.map(({message:f})=>f)??o.messages;return{sessionFile:n,messages:m,identified:u,model:o.model,thinkingLevel:o.thinkingLevel,sessionId:a.getSessionId(),sessionName:a.getSessionName()}}i(b,"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."})}i(d,"invalidCursor");function U(e,t){/^[A-Za-z0-9_-]+$/u.test(e)||d();let n;try{const r=Buffer.from(e,"base64url").toString("utf8");Buffer.from(r,"utf8").toString("base64url")!==e&&d(),n=JSON.parse(r)}catch{d()}(typeof n!="object"||n===null||n.v!==1||!Number.isSafeInteger(n.before))&&d();const s=n.before;return(s<0||s>t)&&d(),s}i(U,"decodeMessagesCursor");function V(e){return Buffer.from(JSON.stringify({v:1,before:e}),"utf8").toString("base64url")}i(V,"encodeMessagesCursor");async function z(e){const t=await b(e),n={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:J(t.messages,t.sessionId,t.sessionFile),state:{model:await k(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:await W(e),turnReplies:await B(e)};return{nodeId:e,snapshot:n,commands:$.map(s=>({...s,source:"builtin"}))}}i(z,"readNodeSnapshot");async function le(e,{cursor:t,limit:n=200}){if(!Number.isSafeInteger(n)||n<1||n>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 E(e)===null)return{messages:[],messageIds:[],messageVisibility:[],nextCursor:null};const{messages:s,identified:r}=await b(e),a=t===void 0?s.length:U(t,s.length);let o=Math.max(0,a-n);for(;o>0&&typeof s[o]=="object"&&s[o]!==null&&s[o].role==="toolResult";)o--;const l=r?.slice(o,a);return{messages:l?.map(({message:u})=>u)??s.slice(o,a),...l===void 0?{}:{messageIds:l.map(({id:u})=>u)},messageVisibility:l?.map(({visibility:u})=>u)??s.slice(o,a).map(()=>"visible"),nextCursor:o===0?null:V(o)}}i(le,"readNodeMessagesPage");function G(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(""):""}i(G,"textFromContent");function D(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"}}i(D,"roleLabel");function H(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"}`):[]}i(H,"toolSummaries");async function ue(e){const t=await p(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:n}=await z(e),r=[`# ${N(t)}`,"",`Saved transcript \xB7 ${t.status} \xB7 ${t.lifecycle}`,""];for(const a of n.messages){if(typeof a!="object"||a===null)continue;const o=a;if(o.role==="custom"&&o.display===!1)continue;const l=G(o.content),u=typeof o.text=="string"?o.text:"",m=l.trim()?l:u.trim()?u:"",f=H(o);if(!(!m&&f.length===0)){r.push(`## ${D(o)}`,""),m&&r.push(m,"");for(const v of f)r.push(`- ${v}`);f.length&&r.push("")}}return r.length===5&&r.push("_No saved messages._",""),r.join(`
3
+ `)}i(ue,"transcriptMarkdown");export{le as readNodeMessagesPage,ae as readNodeSession,z as readNodeSnapshot,ue as transcriptMarkdown};
@@ -1 +1 @@
1
- var J=Object.defineProperty;var l=(e,r)=>J(e,"name",{value:r,configurable:!0});import{envHomeOverride as K,envRuntimeHomeOverride as X,INBOX_BETWEEN_TURNS_ENV as z,SCOPES_FILE_ENV as V,scopeAllowed as I}from"../../shared/env.js";import{isOwnMemoryScope as Y,validateScopes as Q}from"../scopes.js";import{activeGrant as F,terminalGrant as k}from"../grants/mirror.js";import{grantSnapshotMissing as Z}from"../../daemon/readiness.js";import{appendRunEvent as ee}from"../runs/events.js";import{personId as ne}from"../canvas/person.js";import{InputError as S}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 B}from"node:fs";import{resolve as ie,relative as oe,isAbsolute as P,join as ae,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 U}from"../../launcher/spec.js";import{resolveInstallId as _e}from"../canvas/install-id.js";import{isAppRun as we}from"../canvas/app-run.js";import{contextDir as ge}from"../canvas/paths.js";import{conversationIdFromPath as he}from"../conversation-store/index.js";import{usage as H}from"../errors.js";import{assertProfileAvailableForBirth as ve}from"../profiles/deletion-reservation.js";import{loadExactProfileManifest as Re}from"../profiles/manifest.js";import{admitNodeCreate as ye}from"../command-hooks/lifecycle-create.js";import{getById as Ee,nodeObject as C,ownerForGrantee as Ie}from"../graph/objects.js";import{recordActedOn as Ce}from"../graph/edges.js";import{recordWatch as Ne,copyWatchesForFork as ke}from"../graph/watches.js";import{publish as Se}from"../graph/events.js";import{canvasDatabaseUrl as Te}from"../canvas/db.js";import{someAsync as Oe}from"../async-array.js";import{admitIntoManagedCheckout as xe}from"../worktree-mutation-async.js";let T;const L=new Map;function hn(e){T=e}l(hn,"setInstallId");async function De(){if(T!==void 0)return T;const e=await Te(),r=L.get(e);if(r!==void 0)return r;const o=await _e();return L.set(e,o),o}l(De,"installId");function be(){return`${Date.now().toString(36)}-${te(4).toString("hex")}`}l(be,"newJobId");async function Ae(){return`${await De()}-${be()}`}l(Ae,"newNodeId");const O=128,Me=/^[a-z0-9-]+$/;class j extends Error{static{l(this,"NodeIdConflictError")}nodeId;constructor(r){super(`node already exists: ${r}`),this.nodeId=r,this.name="NodeIdConflictError"}}function x(e){if(e.length===0||e.length>O)throw H(`invalid --node-id '${e}': must be 1-${O} characters`,{next:`Pass an id-safe string (lowercase letters, digits, hyphens) of at most ${O} characters.`});if(!Me.test(e))throw H(`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(x,"validateNodeIdFormat");async function vn(e){if(x(e),await u(e)!==null)throw new j(e)}l(vn,"preflightNodeId");async function $e(e){if(x(e),await u(e)!==null)throw new j(e);return e}l($e,"validatedExplicitNodeId");async function Rn(e){let r=e;const o=new Set;for(;;){if(o.has(r))return r;o.add(r);const s=await pe(r);if(s===null||s.parent==null)return r;r=s.parent}}l(Rn,"rootOfSpine");function yn(){const e=process.env;return{nodeId:e.CRTR_NODE_ID??null,kind:e.CRTR_KIND??null,mode:e.CRTR_MODE??null}}l(yn,"currentNodeContext");function Fe(e){return we(e)}l(Fe,"inboxBetweenTurns");function En(e){const r={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:ge(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&&(r.CRTR_PARENT_NODE_ID=e.parent),e.run_id&&(r.CRTR_RUN_ID=e.run_id),Fe(e)&&(r[z]="1"),e.scopes!==null&&e.scopes!==void 0&&(r[V]=de(e.node_id)),r.CRTR_GRANTEE=e.grantee??"app:terminal";const o=K();o!==void 0&&o!==""&&(r.CRTR_HOME=o);const s=X();s!==void 0&&s!==""&&(r.CRTR_RUNTIME_HOME=s);const f=process.env.CRTR_SUBTREE;return f!==void 0&&f!==""&&(r.CRTR_SUBTREE=f),{...r,...e.launch?.env??{}}}l(En,"nodeEnv");async function Be(e){const r=he(e),o=r===null?null:await fe(r);return o===null?null:await u(o)}l(Be,"forkSourceNode");async function In(e){const r=e.nodeId!==void 0?(x(e.nodeId),e.nodeId):await Ae(),o=e.parent??null,s=o===null,f=e.spawnedBy??o,m=e.creator??null,D=e.mode??"base",N=e.lifecycle??(s?"resident":"terminal"),h=e.run===void 0?await k():null,n={node_id:r,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:D,lifecycle:N,persona_ack:{kind:e.kind,mode:D,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?r: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,caused_by:e.causedBy??null,...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:Q(e.scopes),v=o===null?null:await u(o);if(o!==null&&v===null)throw new Error(`cannot spawn under unknown parent node: ${o}`);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 b=e.forkSourceFile==null?null:await Be(e.forkSourceFile),A=e.replaces==null?null:await u(e.replaces),_=v??b??A??c??(f===null?null:await u(f)),q=[v,c,b,A,f===null?null:await u(f)],M=await Oe(q,async t=>t?.isolated===!0||t?.run_id!=null&&(await u(t.run_id))?.isolated===!0);if(M&&e.isolated===!1)throw new g(403,"isolated_run","isolation cannot be turned off under an isolated run",{param:"isolated"});if(n.isolated=M||e.isolated===!0,_!==null){const t=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 a of i){a.scopes!==null&&a.scopes!==void 0&&d.push(a.scopes);const p=a.grantee==="app:terminal"?await k():a.grant_id?await F(a.grant_id):null;if(p){const R=[...p.resolved];w.add(R),d.push(R)}else{const R=[];w.add(R),d.push(R)}}const E=l(a=>Y(a,t.grantee??"app:terminal"),"ownMemory"),$=l((a,p)=>E(p)&&w.has(a)||I(a,p),"allowed");if(y!==void 0&&!y.every(a=>d.every(p=>$(p,a))))throw new S({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(a=>a.scopes==null)&&i.every(a=>a.grant_id===t.grant_id&&a.sub===t.sub)?null:i.length===1?_.scopes??null:[...new Set(d.flat().filter(a=>d.every(p=>$(p,a))))]),n.scopes?.includes("crtr:act")&&!I(n.scopes,"crtr:llm"))throw new S({error:"invalid_scope",message:"crtr:act requires crtr:llm",received:n.scopes,field:"scopes",next:"Include crtr:llm or omit crtr:act."});n.grantee=t.grantee,n.sub=t.sub??(n.grantee==="app:terminal"?h?.sub:null)??null,n.grant_id=t.grant_id??(n.grantee==="app:terminal"?h?.id:null)??null,n.client_id=t.client_id,n.run_id=s?r:t.run_id??null}if(re(n.grantee),e.run===void 0&&n.grantee==="app:terminal"&&h===null)throw await Z()?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"||!B(U))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 t=ae(se(n.grantee??"app:terminal").nodes,r),i=oe(t,ie(n.cwd));if(!P(n.cwd)||i===".."||i.startsWith(`..${le}`)||P(i))throw new g(400,"invalid_request","isolated node cwd must be inside its own folder",{param:"cwd"})}if(n.profile_id){const t=Re(n.profile_id).manifest.grantee??"app:terminal";if(t!==n.grantee){const i=`crtr:memory:rw:${t}:profile:${n.profile_id}`,d=n.grantee==="app:terminal"?await k():n.grant_id?await F(n.grant_id):null;if(!d||d.grantee!==n.grantee||!I(d.resolved,i)||!I(n.scopes,i))throw new S({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 ye({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=l(async(t,i)=>{const d=await C(t,i.node_id),w=m??o??e.actor??f??null,E=w!==null&&(await Ee(t,w))?.type==="node"?await C(t,w):await Ie(t,e.run===void 0?ne():i.grantee);await Ce(t,E,d),o!==null&&e.subscribe!==!1&&await Ne(t,await C(t,o),d,"spawn"),e.forkSourceNode&&await ke(t,await C(t,e.forkSourceNode),d),await Se(t,{event:"created",object:d,actor:E,attrs:{name:i.name,kind:i.kind,creator:m??null}})},"recordBirth");try{e.nodeId!==void 0&&await $e(e.nodeId),await e.beforeCreate?.(),(process.platform!=="linux"||B(U))&&await me(n.grantee??"app:terminal"),await xe(n.cwd,r,()=>ce(n,{outcomeDelivery:e.outcomeDelivery,withinCreate:l(async(t,i)=>{i.run_id&&i.run_id!==i.node_id&&await ue(t,i.run_id),s&&e.run===void 0&&await ee(t,r,r,"run.started",{scopes:i.scopes??null,payer:"user",usage:JSON.parse(i.usage_json)}),await e.withinCreate?.(t,i),await G(t,i)},"withinCreate")}))}finally{W()}return n}l(In,"spawnNode");export{j as NodeIdConflictError,yn as currentNodeContext,Be as forkSourceNode,Fe as inboxBetweenTurns,be as newJobId,Ae as newNodeId,En as nodeEnv,vn as preflightNodeId,Rn as rootOfSpine,hn as setInstallId,In as spawnNode};
1
+ var J=Object.defineProperty;var l=(e,r)=>J(e,"name",{value:r,configurable:!0});import{envHomeOverride as K,envRuntimeHomeOverride as X,INBOX_BETWEEN_TURNS_ENV as z,SCOPES_FILE_ENV as V,scopeAllowed as I}from"../../shared/env.js";import{isOwnMemoryScope as Y,validateScopes as Q}from"../scopes.js";import{activeGrant as F,terminalGrant as k}from"../grants/mirror.js";import{grantSnapshotMissing as Z}from"../../daemon/readiness.js";import{appendRunEvent as ee}from"../runs/events.js";import{personId as ne}from"../canvas/person.js";import{InputError as S}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 B}from"node:fs";import{resolve as ie,relative as oe,isAbsolute as L,join as ae,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 _e}from"../spaces/space.js";import{LAUNCHER_SOCKET as P}from"../../launcher/spec.js";import{resolveInstallId as me}from"../canvas/install-id.js";import{isAppRun as we}from"../canvas/app-run.js";import{contextDir as ge}from"../canvas/paths.js";import{conversationIdFromPath as he}from"../conversation-store/index.js";import{usage as U}from"../errors.js";import{assertProfileAvailableForBirth as Re}from"../profiles/deletion-reservation.js";import{loadExactProfileManifest as ve}from"../profiles/manifest.js";import{admitNodeCreate as ye}from"../command-hooks/lifecycle-create.js";import{getById as Ee,nodeObject as N,ownerForGrantee as Ie}from"../graph/objects.js";import{recordActedOn as Ne}from"../graph/edges.js";import{recordWatch as Ce,copyWatchesForFork as ke}from"../graph/watches.js";import{publish as Se}from"../graph/events.js";import{canvasDatabaseUrl as Te}from"../canvas/db.js";import{someAsync as De}from"../async-array.js";import{admitIntoManagedCheckout as Oe}from"../worktree-mutation-async.js";let T;const H=new Map;function hn(e){T=e}l(hn,"setInstallId");async function xe(){if(T!==void 0)return T;const e=await Te(),r=H.get(e);if(r!==void 0)return r;const o=await me();return H.set(e,o),o}l(xe,"installId");function be(){return`${Date.now().toString(36)}-${te(4).toString("hex")}`}l(be,"newJobId");async function Ae(){return`${await xe()}-${be()}`}l(Ae,"newNodeId");const D=128,Me=/^[a-z0-9-]+$/;class j extends Error{static{l(this,"NodeIdConflictError")}nodeId;constructor(r){super(`node already exists: ${r}`),this.nodeId=r,this.name="NodeIdConflictError"}}function O(e){if(e.length===0||e.length>D)throw U(`invalid --node-id '${e}': must be 1-${D} characters`,{next:`Pass an id-safe string (lowercase letters, digits, hyphens) of at most ${D} characters.`});if(!Me.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(O,"validateNodeIdFormat");async function Rn(e){if(O(e),await u(e)!==null)throw new j(e)}l(Rn,"preflightNodeId");async function $e(e){if(O(e),await u(e)!==null)throw new j(e);return e}l($e,"validatedExplicitNodeId");async function vn(e){let r=e;const o=new Set;for(;;){if(o.has(r))return r;o.add(r);const s=await pe(r);if(s===null||s.parent==null)return r;r=s.parent}}l(vn,"rootOfSpine");function yn(){const e=process.env;return{nodeId:e.CRTR_NODE_ID??null,kind:e.CRTR_KIND??null,mode:e.CRTR_MODE??null}}l(yn,"currentNodeContext");function Fe(e){return we(e)}l(Fe,"inboxBetweenTurns");function En(e){const r={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:ge(e.node_id,e.grantee),...e.deadline_at?{CRTR_NODE_DEADLINE_AT:e.deadline_at}:{},CRTR_CYCLES:(e.cycles??0).toString(),CRTR_PROFILE_ID:e.profile_id??"",PI_CLAUDE_OAUTH_REINJECT_SCOPE:"never"};e.parent&&(r.CRTR_PARENT_NODE_ID=e.parent),e.run_id&&(r.CRTR_RUN_ID=e.run_id),Fe(e)&&(r[z]="1"),e.scopes!==null&&e.scopes!==void 0&&(r[V]=de(e.node_id)),r.CRTR_GRANTEE=e.grantee??"app:terminal";const o=K();o!==void 0&&o!==""&&(r.CRTR_HOME=o);const s=X();s!==void 0&&s!==""&&(r.CRTR_RUNTIME_HOME=s);const f=process.env.CRTR_SUBTREE;return f!==void 0&&f!==""&&(r.CRTR_SUBTREE=f),{...r,...e.launch?.env??{}}}l(En,"nodeEnv");async function Be(e){const r=he(e),o=r===null?null:await fe(r);return o===null?null:await u(o)}l(Be,"forkSourceNode");async function In(e){const r=e.nodeId!==void 0?(O(e.nodeId),e.nodeId):await Ae(),o=e.parent??null,s=o===null,f=e.spawnedBy??o,_=e.creator??null,x=e.mode??"base",C=e.lifecycle??(s?"resident":"terminal"),h=e.run===void 0?await k():null,n={node_id:r,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:x,lifecycle:C,persona_ack:{kind:e.kind,mode:x,lifecycle:C},status:"active",parent:o,spawned_by:f,creator:_,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?r: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,caused_by:e.causedBy??null,...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:Q(e.scopes),R=o===null?null:await u(o);if(o!==null&&R===null)throw new Error(`cannot spawn under unknown parent node: ${o}`);if(R?.run_id&&(await u(R.run_id))?.deleting_at)throw new Error("run is deleting");const c=_===null?null:await u(_);if(_!==null&&c===null)throw new Error(`cannot spawn from unknown creator node: ${_}`);if(c?.run_id&&(await u(c.run_id))?.deleting_at)throw new Error("run is deleting");const b=e.forkSourceFile==null?null:await Be(e.forkSourceFile),A=e.replaces==null?null:await u(e.replaces),m=R??b??A??c??(f===null?null:await u(f)),q=[R,c,b,A,f===null?null:await u(f)],M=await De(q,async t=>t?.isolated===!0||t?.run_id!=null&&(await u(t.run_id))?.isolated===!0);if(M&&e.isolated===!1)throw new g(403,"isolated_run","isolation cannot be turned off under an isolated run",{param:"isolated"});if(n.isolated=M||e.isolated===!0,m!==null){const t=c??m;if(c&&m.grantee&&c.grantee&&c.grantee!==m.grantee)throw new g(403,"other_app_run","cannot create under another app's node");const i=c&&c!==m?[m,c]:[m],d=[],w=new Set;for(const a of i){a.scopes!==null&&a.scopes!==void 0&&d.push(a.scopes);const p=a.grantee==="app:terminal"?await k():a.grant_id?await F(a.grant_id):null;if(p){const v=[...p.resolved];w.add(v),d.push(v)}else{const v=[];w.add(v),d.push(v)}}const E=l(a=>Y(a,t.grantee??"app:terminal"),"ownMemory"),$=l((a,p)=>E(p)&&w.has(a)||I(a,p),"allowed");if(y!==void 0&&!y.every(a=>d.every(p=>$(p,a))))throw new S({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(a=>a.scopes==null)&&i.every(a=>a.grant_id===t.grant_id&&a.sub===t.sub)?null:i.length===1?m.scopes??null:[...new Set(d.flat().filter(a=>d.every(p=>$(p,a))))]),n.scopes?.includes("crtr:act")&&!I(n.scopes,"crtr:llm"))throw new S({error:"invalid_scope",message:"crtr:act requires crtr:llm",received:n.scopes,field:"scopes",next:"Include crtr:llm or omit crtr:act."});n.grantee=t.grantee,n.sub=t.sub??(n.grantee==="app:terminal"?h?.sub:null)??null,n.grant_id=t.grant_id??(n.grantee==="app:terminal"?h?.id:null)??null,n.client_id=t.client_id,n.run_id=s?r:t.run_id??null}if(re(n.grantee),e.run===void 0&&n.grantee==="app:terminal"&&h===null)throw await Z()?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"||!B(P))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 t=ae(se(n.grantee??"app:terminal").nodes,r),i=oe(t,ie(n.cwd));if(!L(n.cwd)||i===".."||i.startsWith(`..${le}`)||L(i))throw new g(400,"invalid_request","isolated node cwd must be inside its own folder",{param:"cwd"})}if(n.profile_id){const t=ve(n.profile_id).manifest.grantee??"app:terminal";if(t!==n.grantee){const i=`crtr:memory:rw:${t}:profile:${n.profile_id}`,d=n.grantee==="app:terminal"?await k():n.grant_id?await F(n.grant_id):null;if(!d||d.grantee!==n.grantee||!I(d.resolved,i)||!I(n.scopes,i))throw new S({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 W=await ye({kind:n.kind,mode:n.mode,cwd:n.cwd,profile:n.profile_id??null,root:s,parentId:o,requestingNodeId:_,lifecycle:C,replaces:e.replaces??null},n.grantee),G=l(async(t,i)=>{const d=await N(t,i.node_id),w=_??o??e.actor??f??null,E=w!==null&&(await Ee(t,w))?.type==="node"?await N(t,w):await Ie(t,e.run===void 0?ne():i.grantee);await Ne(t,E,d),o!==null&&e.subscribe!==!1&&await Ce(t,await N(t,o),d,"spawn"),e.forkSourceNode&&await ke(t,await N(t,e.forkSourceNode),d),await Se(t,{event:"created",object:d,actor:E,attrs:{name:i.name,kind:i.kind,creator:_??null}})},"recordBirth");try{e.nodeId!==void 0&&await $e(e.nodeId),await e.beforeCreate?.(),(process.platform!=="linux"||B(P))&&await _e(n.grantee??"app:terminal"),await Oe(n.cwd,r,()=>ce(n,{outcomeDelivery:e.outcomeDelivery,withinCreate:l(async(t,i)=>{i.run_id&&i.run_id!==i.node_id&&await ue(t,i.run_id),s&&e.run===void 0&&await ee(t,r,r,"run.started",{scopes:i.scopes??null,payer:"user",usage:JSON.parse(i.usage_json)}),await e.withinCreate?.(t,i),await G(t,i)},"withinCreate")}))}finally{W()}return n}l(In,"spawnNode");export{j as NodeIdConflictError,yn as currentNodeContext,Be as forkSourceNode,Fe as inboxBetweenTurns,be as newJobId,Ae as newNodeId,En as nodeEnv,Rn as preflightNodeId,vn as rootOfSpine,hn as setInstallId,In as spawnNode};
@@ -27,7 +27,6 @@ export interface NodeOutcomeDocumentV1 {
27
27
  };
28
28
  structuredResult?: unknown;
29
29
  structuredResultOmitted?: true;
30
- structuredResultPath?: string;
31
30
  };
32
31
  failure?: {
33
32
  message: string | null;
@@ -1 +1 @@
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};
1
+ var c=Object.defineProperty;var s=(t,e)=>c(t,"name",{value:e,configurable:!0});import{readOutputResult as f}from"./output-result.js";const m=256*1024;async function p(t){return await f(t)}s(p,"structuredResult");function y(t){if(t===null)return null;try{return JSON.parse(t)}catch{return null}}s(y,"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 u=Buffer.byteLength(i,"utf8");if(r+u>1024)break;r+=u,l+=i}return`${l}${n}`}s(a,"truncateDescription");async function B(t){const{node:e,outcome:n}=t,r=y(n.detailJson),l=t.finalReport??e.final_report??"",i=a(e.name),u=e.description===void 0?void 0:a(e.description),o=n.kind==="result"?t.structuredResult===void 0?await p(e.node_id):t.structuredResult:void 0,d={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,...u===void 0?{}:{description:u},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(d),"utf8")>m&&d.result?.structuredResult!==void 0&&(delete d.result.structuredResult,d.result.structuredResultOmitted=!0),d}s(B,"composeNodeOutcomeDocument");export{B as composeNodeOutcomeDocument};
@@ -0,0 +1,15 @@
1
+ /** The node's machine result: the latest completed terminal structured request's result row; undefined when none completed. */
2
+ export declare function readOutputResult(nodeId: string): Promise<unknown>;
3
+ import type { StructuredOutputRequest } from './structured-output.js';
4
+ /** The node's pending structured request, read from its `structured_requests` row; null when none is pending. */
5
+ export declare function readOutputRequest(nodeId: string): Promise<StructuredOutputRequest | null>;
6
+ export interface SchemaReprompts {
7
+ count: number;
8
+ at: number;
9
+ }
10
+ /** The pending request's consecutive schema reprompts (stop guard); none recorded reads as 0. */
11
+ export declare function readSchemaReprompts(nodeId: string): Promise<SchemaReprompts>;
12
+ /** Record one reprompt only if the stored count is still `from`; false when another process counted first. */
13
+ export declare function takeSchemaReprompt(nodeId: string, from: number, count: number, at: number): Promise<boolean>;
14
+ /** A submission resets the count. */
15
+ export declare function clearSchemaReprompts(nodeId: string): Promise<void>;
@@ -0,0 +1,5 @@
1
+ var u=Object.defineProperty;var r=(t,e)=>u(t,"name",{value:e,configurable:!0});import{openDb as s}from"../canvas/db.js";async function d(t){const e=await(await s()).prepareUncached(`SELECT result_json FROM structured_requests
2
+ WHERE node_id = ? AND submission = 'terminal' AND state = 'completed' AND result_json IS NOT NULL
3
+ ORDER BY settled_at DESC, seq DESC LIMIT 1`).get(t);return e===void 0?void 0:JSON.parse(e.result_json)}r(d,"readOutputResult");async function c(t){const e=await(await s()).prepareUncached(`SELECT request_id, submission, schema_json, request_message_id FROM structured_requests
4
+ WHERE node_id = ? AND state = 'pending'`).get(t);return e===void 0?null:{request_id:e.request_id,mode:e.submission,schema:JSON.parse(e.schema_json),...e.request_message_id===null?{}:{requestMessageId:e.request_message_id}}}r(c,"readOutputRequest");async function i(t){const e=await(await s()).prepareUncached("SELECT reprompt_count, reprompted_at FROM structured_requests WHERE node_id = ? AND state = 'pending'").get(t);return{count:Number(e?.reprompt_count??0),at:Number(e?.reprompted_at??0)}}r(i,"readSchemaReprompts");async function _(t,e,n,a){return Number((await(await s()).prepareUncached(`UPDATE structured_requests SET reprompt_count = ?, reprompted_at = ?
5
+ WHERE node_id = ? AND state = 'pending' AND reprompt_count = ?`).run(n,a,t,e)).changes)===1}r(_,"takeSchemaReprompt");async function m(t){await(await s()).prepareUncached("UPDATE structured_requests SET reprompt_count = 0, reprompted_at = NULL WHERE node_id = ? AND state = 'pending'").run(t)}r(m,"clearSchemaReprompts");export{m as clearSchemaReprompts,c as readOutputRequest,d as readOutputResult,i as readSchemaReprompts,_ as takeSchemaReprompt};