@north-light/cli 0.3.561 → 0.3.563

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 (579) 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/build-root.d.ts +1 -0
  23. package/dist/build-root.js +1 -1
  24. package/dist/builtin-memory/crouter-sdk/release-notes.md +4 -0
  25. package/dist/cli.js +7 -7
  26. package/dist/clients/attach/chrome/bash-jobs.d.ts +11 -1
  27. package/dist/clients/attach/chrome/bash-jobs.js +1 -1
  28. package/dist/clients/attach/chrome/canvas-panels.d.ts +1 -1
  29. package/dist/clients/attach/chrome/roster.js +6 -4
  30. package/dist/clients/attach/overlays/auth.js +2 -2
  31. package/dist/clients/attach/render/chat-view.js +1 -1
  32. package/dist/clients/attach/viewer.js +550 -567
  33. package/dist/commands/canvas-config.js +2 -2
  34. package/dist/commands/canvas-use.js +1 -1
  35. package/dist/commands/human.js +2 -2
  36. package/dist/commands/node/bash.js +3 -3
  37. package/dist/commands/node/create.js +2 -2
  38. package/dist/commands/person-settings.d.ts +1 -0
  39. package/dist/commands/person-settings.js +1 -0
  40. package/dist/commands/pkg/market-manage.d.ts +2 -2
  41. package/dist/commands/pkg/market-manage.js +1 -1
  42. package/dist/commands/pkg/plugin-manage.js +13 -13
  43. package/dist/commands/pkg/shared.js +1 -1
  44. package/dist/commands/profile/default.js +1 -1
  45. package/dist/commands/push.js +2 -3
  46. package/dist/commands/sys/config.js +1 -1
  47. package/dist/commands/sys/connect.js +1 -1
  48. package/dist/commands/sys/context/sysprompt.js +2 -2
  49. package/dist/commands/sys/doctor.js +1 -1
  50. package/dist/commands/sys/join.js +1 -1
  51. package/dist/commands/sys/panels/broker-limits-panel.js +1 -1
  52. package/dist/commands/sys/panels/keybindings-panel.js +1 -1
  53. package/dist/commands/sys/panels/models-panel.d.ts +8 -2
  54. package/dist/commands/sys/panels/models-panel.js +1 -1
  55. package/dist/commands/sys/panels/prefs-panel.d.ts +1 -0
  56. package/dist/commands/sys/panels/prefs-panel.js +1 -1
  57. package/dist/commands/sys/panels/profiles-panel.js +1 -1
  58. package/dist/commands/sys/panels/provider-panel.d.ts +4 -0
  59. package/dist/commands/sys/panels/provider-panel.js +1 -1
  60. package/dist/commands/sys/provider-login.js +5 -5
  61. package/dist/commands/sys/setup-core.js +3 -3
  62. package/dist/commands/sys/setup-settings-runner.js +1 -1
  63. package/dist/commands/sys/spend.js +3 -3
  64. package/dist/commands/sys/update.js +1 -1
  65. package/dist/core/auth-file.d.ts +11 -19
  66. package/dist/core/auth-file.js +1 -2
  67. package/dist/core/auto-update.d.ts +1 -1
  68. package/dist/core/auto-update.js +4 -4
  69. package/dist/core/bash-jobs.d.ts +29 -71
  70. package/dist/core/bash-jobs.js +9 -10
  71. package/dist/core/blobs/directory.d.ts +3 -0
  72. package/dist/core/blobs/directory.js +1 -0
  73. package/dist/core/blobs/fault.d.ts +3 -0
  74. package/dist/core/blobs/fault.js +1 -0
  75. package/dist/core/blobs/index.d.ts +21 -0
  76. package/dist/core/blobs/index.js +1 -0
  77. package/dist/core/blobs/r2.d.ts +9 -0
  78. package/dist/core/blobs/r2.js +4 -0
  79. package/dist/core/bootstrap.d.ts +1 -1
  80. package/dist/core/bootstrap.js +2 -2
  81. package/dist/core/canvas/canvas.d.ts +9 -7
  82. package/dist/core/canvas/canvas.js +8 -8
  83. package/dist/core/canvas/crons.d.ts +3 -2
  84. package/dist/core/canvas/crons.js +3 -3
  85. package/dist/core/canvas/daemon-owner.d.ts +5 -0
  86. package/dist/core/canvas/daemon-owner.js +1 -1
  87. package/dist/core/canvas/db.d.ts +10 -9
  88. package/dist/core/canvas/db.js +4 -4
  89. package/dist/core/canvas/executions.d.ts +100 -4
  90. package/dist/core/canvas/executions.js +1 -1
  91. package/dist/core/canvas/export-sqlite.js +1 -1
  92. package/dist/core/canvas/focuses.d.ts +4 -0
  93. package/dist/core/canvas/focuses.js +1 -1
  94. package/dist/core/canvas/history.js +9 -9
  95. package/dist/core/canvas/managed-worktree-sweep-candidates.d.ts +2 -1
  96. package/dist/core/canvas/managed-worktree-sweep-candidates.js +3 -2
  97. package/dist/core/canvas/node-tokens.d.ts +1 -4
  98. package/dist/core/canvas/node-tokens.js +3 -3
  99. package/dist/core/canvas/paths.d.ts +0 -1
  100. package/dist/core/canvas/paths.js +1 -1
  101. package/dist/core/canvas/person-state.d.ts +26 -0
  102. package/dist/core/canvas/person-state.js +1 -0
  103. package/dist/core/canvas/person.d.ts +3 -10
  104. package/dist/core/canvas/person.js +7 -7
  105. package/dist/core/canvas/reconciler-leases.d.ts +12 -0
  106. package/dist/core/canvas/reconciler-leases.js +8 -0
  107. package/dist/core/canvas/recovery.d.ts +4 -0
  108. package/dist/core/canvas/recovery.js +1 -1
  109. package/dist/core/canvas/schema-pg/003-fleet-removals.sql +1 -1
  110. package/dist/core/canvas/schema-pg/005-fleet-blobs.sql +13 -0
  111. package/dist/core/canvas/schema-pg/006-job-rows.sql +20 -0
  112. package/dist/core/canvas/schema-pg/007-ledger-check.sql +117 -0
  113. package/dist/core/canvas/schema-version.d.ts +1 -1
  114. package/dist/core/canvas/schema-version.js +1 -1
  115. package/dist/core/canvas/sessions.d.ts +8 -11
  116. package/dist/core/canvas/sessions.js +1 -4
  117. package/dist/core/canvas/tree.d.ts +4 -2
  118. package/dist/core/canvas/tree.js +6 -6
  119. package/dist/core/canvas/types.d.ts +7 -0
  120. package/dist/core/command-hooks/transport/exec-lifecycle.js +1 -1
  121. package/dist/core/command-plugins/bundle.d.ts +1 -1
  122. package/dist/core/command-plugins/bundle.js +1 -1
  123. package/dist/core/command-plugins/compose.d.ts +1 -1
  124. package/dist/core/command-plugins/discovery.d.ts +0 -1
  125. package/dist/core/command-plugins/discovery.js +1 -1
  126. package/dist/core/command-plugins/help-addenda.js +1 -1
  127. package/dist/core/command-plugins/presence.d.ts +2 -0
  128. package/dist/core/command-plugins/presence.js +1 -1
  129. package/dist/core/config.d.ts +16 -15
  130. package/dist/core/config.js +1 -1
  131. package/dist/core/conversation-store/client-worker.js +1 -1
  132. package/dist/core/conversation-store/client.js +2 -2
  133. package/dist/core/conversation-store/index.d.ts +9 -11
  134. package/dist/core/conversation-store/index.js +1 -1
  135. package/dist/core/conversation-store/patch.js +1 -1
  136. package/dist/core/conversation-store/row-store.d.ts +14 -0
  137. package/dist/core/conversation-store/row-store.js +13 -0
  138. package/dist/core/directory/join.d.ts +5 -3
  139. package/dist/core/directory/join.js +1 -1
  140. package/dist/core/env-name.d.ts +1 -0
  141. package/dist/core/env-name.js +1 -1
  142. package/dist/core/environment-recipe.d.ts +15 -0
  143. package/dist/core/environment-recipe.js +1 -0
  144. package/dist/core/environments.js +1 -1
  145. package/dist/core/events/emit.js +2 -2
  146. package/dist/core/events/run-event-chunks.d.ts +25 -0
  147. package/dist/core/events/run-event-chunks.js +5 -0
  148. package/dist/core/feed/messages.js +5 -5
  149. package/dist/core/grants/mirror.d.ts +15 -0
  150. package/dist/core/grants/mirror.js +15 -3
  151. package/dist/core/grants/on-sync.d.ts +9 -5
  152. package/dist/core/grants/on-sync.js +1 -1
  153. package/dist/core/grants/remove.d.ts +1 -6
  154. package/dist/core/grants/remove.js +1 -1
  155. package/dist/core/grants/sync.js +1 -1
  156. package/dist/core/grants/watch.d.ts +15 -9
  157. package/dist/core/grants/watch.js +1 -1
  158. package/dist/core/graph/custom.js +8 -8
  159. package/dist/core/graph/jobs.d.ts +83 -5
  160. package/dist/core/graph/jobs.js +11 -2
  161. package/dist/core/graph/kinds/job.js +2 -2
  162. package/dist/core/graph/names.js +7 -7
  163. package/dist/core/graph/objects.d.ts +5 -1
  164. package/dist/core/graph/objects.js +11 -11
  165. package/dist/core/graph/reader.d.ts +3 -0
  166. package/dist/core/graph/reader.js +3 -3
  167. package/dist/core/graph/repo-sync/identity.d.ts +3 -1
  168. package/dist/core/graph/repo-sync/identity.js +1 -1
  169. package/dist/core/graph/repo-sync/repos.d.ts +1 -1
  170. package/dist/core/graph/repo-sync/repos.js +2 -2
  171. package/dist/core/graph/repo-sync/sync.js +2 -2
  172. package/dist/core/installed-plugins.js +1 -1
  173. package/dist/core/keybindings/persistence.d.ts +1 -1
  174. package/dist/core/keybindings/persistence.js +1 -1
  175. package/dist/core/layout-migrate/loose-keys.d.ts +1 -1
  176. package/dist/core/layout-migrate/loose-keys.js +1 -1
  177. package/dist/core/ledger/account.d.ts +12 -0
  178. package/dist/core/ledger/account.js +2 -0
  179. package/dist/core/ledger/charges.d.ts +2 -2
  180. package/dist/core/ledger/charges.js +1 -1
  181. package/dist/core/ledger/check.d.ts +5 -1
  182. package/dist/core/ledger/check.js +1 -7
  183. package/dist/core/ledger/chunks.d.ts +8 -0
  184. package/dist/core/ledger/chunks.js +2 -0
  185. package/dist/core/ledger/index.d.ts +2 -1
  186. package/dist/core/ledger/index.js +1 -1
  187. package/dist/core/ledger/infra-allowance.d.ts +9 -0
  188. package/dist/core/ledger/infra-allowance.js +1 -0
  189. package/dist/core/ledger/limits.js +3 -3
  190. package/dist/core/ledger/payer.d.ts +1 -1
  191. package/dist/core/ledger/payer.js +1 -1
  192. package/dist/core/ledger/read.d.ts +14 -4
  193. package/dist/core/ledger/read.js +2 -3
  194. package/dist/core/ledger/totals.d.ts +5 -16
  195. package/dist/core/ledger/totals.js +4 -4
  196. package/dist/core/ledger/types.d.ts +12 -3
  197. package/dist/core/llm/run.js +2 -2
  198. package/dist/core/managed-providers.d.ts +72 -0
  199. package/dist/core/managed-providers.js +1 -0
  200. package/dist/core/model-auth/api-credential-store.d.ts +10 -0
  201. package/dist/core/model-auth/api-credential-store.js +1 -0
  202. package/dist/core/model-auth/daemon-login.d.ts +1 -1
  203. package/dist/core/model-auth/daemon-login.js +1 -1
  204. package/dist/core/model-auth/flows.d.ts +5 -4
  205. package/dist/core/model-auth/flows.js +1 -1
  206. package/dist/core/model-auth/handoff-jti.d.ts +3 -4
  207. package/dist/core/model-auth/handoff-jti.js +1 -1
  208. package/dist/core/model-auth/readiness.js +1 -1
  209. package/dist/core/model-config.d.ts +1 -1
  210. package/dist/core/model-config.js +1 -1
  211. package/dist/core/model-routes-pool.d.ts +14 -0
  212. package/dist/core/model-routes-pool.js +1 -0
  213. package/dist/core/model-routes.d.ts +11 -16
  214. package/dist/core/model-routes.js +1 -1
  215. package/dist/core/peer/ingest.d.ts +2 -0
  216. package/dist/core/peer/ingest.js +1 -1
  217. package/dist/core/peer/stubs.d.ts +8 -0
  218. package/dist/core/peer/stubs.js +1 -1
  219. package/dist/core/permissions/evaluator.d.ts +7 -2
  220. package/dist/core/permissions/evaluator.js +2 -2
  221. package/dist/core/plugin-env.js +1 -1
  222. package/dist/core/pool-credential-store.d.ts +2 -5
  223. package/dist/core/pool-credential-store.js +1 -1
  224. package/dist/core/profiles/app-env-store.d.ts +5 -5
  225. package/dist/core/profiles/app-env-store.js +1 -2
  226. package/dist/core/profiles/default-binding.d.ts +5 -5
  227. package/dist/core/profiles/default-binding.js +1 -1
  228. package/dist/core/profiles/env-store.d.ts +10 -21
  229. package/dist/core/profiles/env-store.js +1 -2
  230. package/dist/core/profiles/manifest.d.ts +14 -18
  231. package/dist/core/profiles/manifest.js +1 -1
  232. package/dist/core/profiles/relocate.js +1 -1
  233. package/dist/core/profiles/select.js +21 -21
  234. package/dist/core/provider-credential.d.ts +1 -1
  235. package/dist/core/provider-credential.js +1 -1
  236. package/dist/core/provider-management.d.ts +3 -4
  237. package/dist/core/provider-management.js +1 -1
  238. package/dist/core/providers/bundles.js +2 -2
  239. package/dist/core/providers/call.d.ts +3 -34
  240. package/dist/core/providers/description.d.ts +34 -0
  241. package/dist/core/providers/description.js +0 -0
  242. package/dist/core/providers/token-cache.d.ts +14 -14
  243. package/dist/core/providers/token-cache.js +1 -1
  244. package/dist/core/review/companion.js +1 -1
  245. package/dist/core/runs/activity.d.ts +1 -1
  246. package/dist/core/runs/activity.js +1 -1
  247. package/dist/core/runs/events.d.ts +7 -5
  248. package/dist/core/runs/events.js +2 -6
  249. package/dist/core/runs/operations.d.ts +1 -1
  250. package/dist/core/runs/operations.js +6 -6
  251. package/dist/core/runtime/bearings.js +1 -1
  252. package/dist/core/runtime/broker/attachments-fetch.d.ts +5 -0
  253. package/dist/core/runtime/broker/attachments-fetch.js +1 -0
  254. package/dist/core/runtime/broker/bash-job-launch.d.ts +4 -2
  255. package/dist/core/runtime/broker/bash-job-launch.js +1 -1
  256. package/dist/core/runtime/broker/boot-state.d.ts +9 -0
  257. package/dist/core/runtime/broker/boot-state.js +1 -0
  258. package/dist/core/runtime/broker/cli-relay.d.ts +2 -1
  259. package/dist/core/runtime/broker/cli-relay.js +1 -1
  260. package/dist/core/runtime/broker/client-registry.d.ts +3 -3
  261. package/dist/core/runtime/broker/daemon-ops.d.ts +10 -1
  262. package/dist/core/runtime/broker/daemon-ops.js +1 -1
  263. package/dist/core/runtime/broker/fault-retry.d.ts +2 -0
  264. package/dist/core/runtime/broker/fault-retry.js +1 -1
  265. package/dist/core/runtime/broker/frame-engine-control.js +1 -1
  266. package/dist/core/runtime/broker/held-deferred-inbox.d.ts +3 -0
  267. package/dist/core/runtime/broker/held-deferred-inbox.js +1 -1
  268. package/dist/core/runtime/broker/job-reporter.d.ts +18 -0
  269. package/dist/core/runtime/broker/job-reporter.js +2 -0
  270. package/dist/core/runtime/broker/model-adapter.d.ts +3 -0
  271. package/dist/core/runtime/broker/model-adapter.js +3 -2
  272. package/dist/core/runtime/broker/signal-stream.js +1 -1
  273. package/dist/core/runtime/broker/spilled-body.d.ts +5 -0
  274. package/dist/core/runtime/broker/spilled-body.js +1 -0
  275. package/dist/core/runtime/broker/summaries-post.d.ts +5 -0
  276. package/dist/core/runtime/broker/summaries-post.js +1 -0
  277. package/dist/core/runtime/broker/tool-groups.d.ts +3 -0
  278. package/dist/core/runtime/broker/tool-groups.js +1 -1
  279. package/dist/core/runtime/broker/turn-replies.d.ts +1 -0
  280. package/dist/core/runtime/broker/turn-replies.js +1 -1
  281. package/dist/core/runtime/broker-persona-guidance.js +2 -2
  282. package/dist/core/runtime/broker.js +1 -1
  283. package/dist/core/runtime/deliver-live.js +1 -1
  284. package/dist/core/runtime/first-boot-rows.d.ts +8 -0
  285. package/dist/core/runtime/first-boot-rows.js +2 -0
  286. package/dist/core/runtime/fleet.d.ts +13 -12
  287. package/dist/core/runtime/front-door-login.js +1 -1
  288. package/dist/core/runtime/front-door.js +6 -6
  289. package/dist/core/runtime/headless-pi.js +1 -1
  290. package/dist/core/runtime/host.d.ts +14 -3
  291. package/dist/core/runtime/host.js +3 -3
  292. package/dist/core/runtime/invocation.d.ts +6 -0
  293. package/dist/core/runtime/kickoff.d.ts +2 -14
  294. package/dist/core/runtime/kickoff.js +17 -19
  295. package/dist/core/runtime/launch-config-worker.js +1 -1
  296. package/dist/core/runtime/launch.js +2 -2
  297. package/dist/core/runtime/model-registry.js +1 -1
  298. package/dist/core/runtime/node-read.d.ts +4 -6
  299. package/dist/core/runtime/node-read.js +3 -3
  300. package/dist/core/runtime/nodes.js +1 -1
  301. package/dist/core/runtime/outcome-document.d.ts +0 -1
  302. package/dist/core/runtime/outcome-document.js +1 -1
  303. package/dist/core/runtime/output-result.d.ts +15 -0
  304. package/dist/core/runtime/output-result.js +5 -0
  305. package/dist/core/runtime/placement.d.ts +17 -1
  306. package/dist/core/runtime/placement.js +1 -1
  307. package/dist/core/runtime/provider-credential-gate.d.ts +6 -2
  308. package/dist/core/runtime/provider-credential-gate.js +2 -2
  309. package/dist/core/runtime/recovery-hold.d.ts +21 -2
  310. package/dist/core/runtime/recovery-hold.js +2 -1
  311. package/dist/core/runtime/recycle.js +1 -1
  312. package/dist/core/runtime/reset.js +1 -1
  313. package/dist/core/runtime/revive.d.ts +2 -2
  314. package/dist/core/runtime/revive.js +2 -2
  315. package/dist/core/runtime/runner/blaxel/client.d.ts +81 -0
  316. package/dist/core/runtime/runner/blaxel/client.js +1 -0
  317. package/dist/core/runtime/runner/blaxel/image-build.d.ts +74 -0
  318. package/dist/core/runtime/runner/blaxel/image-build.js +5 -0
  319. package/dist/core/runtime/runner/blaxel/runner.d.ts +41 -0
  320. package/dist/core/runtime/runner/blaxel/runner.js +3 -0
  321. package/dist/core/runtime/runner/index.d.ts +8 -0
  322. package/dist/core/runtime/runner/index.js +1 -0
  323. package/dist/core/runtime/runner/process.d.ts +11 -0
  324. package/dist/core/runtime/runner/process.js +1 -0
  325. package/dist/core/runtime/runner/types.d.ts +95 -0
  326. package/dist/core/runtime/runner/types.js +0 -0
  327. package/dist/core/runtime/situational-context.d.ts +3 -6
  328. package/dist/core/runtime/situational-context.js +2 -2
  329. package/dist/core/runtime/situational-live.js +1 -1
  330. package/dist/core/runtime/spawn-env-rows.d.ts +5 -0
  331. package/dist/core/runtime/spawn-env-rows.js +1 -0
  332. package/dist/core/runtime/spawn-env.d.ts +4 -18
  333. package/dist/core/runtime/spawn-env.js +1 -1
  334. package/dist/core/runtime/spawn.js +2 -2
  335. package/dist/core/runtime/stop-guard.d.ts +1 -1
  336. package/dist/core/runtime/stop-guard.js +2 -8
  337. package/dist/core/runtime/structured-output.d.ts +0 -67
  338. package/dist/core/runtime/structured-output.js +3 -8
  339. package/dist/core/runtime/tmux-driver.d.ts +8 -0
  340. package/dist/core/runtime/tmux-driver.js +6 -6
  341. package/dist/core/runtime/view-socket.d.ts +20 -0
  342. package/dist/core/runtime/view-socket.js +3 -1
  343. package/dist/core/runtime/warm-pool.d.ts +13 -1
  344. package/dist/core/runtime/warm-pool.js +1 -1
  345. package/dist/core/scoped-state/legacy-profiles.d.ts +11 -0
  346. package/dist/core/scoped-state/legacy-profiles.js +1 -0
  347. package/dist/core/scoped-state/materialized-plugins.d.ts +18 -0
  348. package/dist/core/scoped-state/materialized-plugins.js +1 -0
  349. package/dist/core/scoped-state/migrate.d.ts +8 -1
  350. package/dist/core/scoped-state/migrate.js +3 -3
  351. package/dist/core/scoped-state/person-rows.d.ts +10 -0
  352. package/dist/core/scoped-state/person-rows.js +6 -0
  353. package/dist/core/scoped-state/person-store.d.ts +72 -0
  354. package/dist/core/scoped-state/person-store.js +1 -0
  355. package/dist/core/secrets/blaxel-launch.d.ts +24 -0
  356. package/dist/core/secrets/blaxel-launch.js +4 -0
  357. package/dist/core/secrets/blaxel-register.d.ts +2 -0
  358. package/dist/core/secrets/blaxel-register.js +1 -0
  359. package/dist/core/secrets/env-rows.d.ts +17 -0
  360. package/dist/core/secrets/env-rows.js +4 -0
  361. package/dist/core/secrets/environment-owner.d.ts +8 -0
  362. package/dist/core/secrets/environment-owner.js +1 -0
  363. package/dist/core/secrets/environment-secrets.d.ts +14 -0
  364. package/dist/core/secrets/environment-secrets.js +1 -0
  365. package/dist/core/secrets/index.d.ts +2 -0
  366. package/dist/core/secrets/index.js +1 -0
  367. package/dist/core/secrets/key.d.ts +3 -0
  368. package/dist/core/secrets/key.js +2 -0
  369. package/dist/core/secrets/seal.d.ts +18 -0
  370. package/dist/core/secrets/seal.js +1 -0
  371. package/dist/core/spaces/mounts.d.ts +1 -1
  372. package/dist/core/spaces/mounts.js +1 -1
  373. package/dist/core/spaces/process.d.ts +1 -1
  374. package/dist/core/spaces/stop.d.ts +7 -5
  375. package/dist/core/spaces/stop.js +2 -2
  376. package/dist/core/spaces/users.d.ts +2 -1
  377. package/dist/core/spaces/users.js +1 -1
  378. package/dist/core/storage/attachments.d.ts +11 -8
  379. package/dist/core/storage/attachments.js +1 -1
  380. package/dist/core/storage/tables.d.ts +4 -0
  381. package/dist/core/storage/tables.js +3 -3
  382. package/dist/core/subscription-state.d.ts +34 -72
  383. package/dist/core/subscription-state.js +1 -4
  384. package/dist/core/substrate/delivery/plan.js +1 -1
  385. package/dist/core/user-settings.js +1 -1
  386. package/dist/daemon/api/app-listener.js +10 -10
  387. package/dist/daemon/api/auth/person-bearer.d.ts +14 -0
  388. package/dist/daemon/api/auth/person-bearer.js +1 -0
  389. package/dist/daemon/api/bridge.js +4 -4
  390. package/dist/daemon/api/document-listener.js +3 -3
  391. package/dist/daemon/api/environment-of.d.ts +18 -0
  392. package/dist/daemon/api/environment-of.js +5 -0
  393. package/dist/daemon/api/handlers/analytics.js +1 -1
  394. package/dist/daemon/api/handlers/app-profiles.d.ts +2 -2
  395. package/dist/daemon/api/handlers/app-profiles.js +1 -1
  396. package/dist/daemon/api/handlers/bash-jobs.js +1 -1
  397. package/dist/daemon/api/handlers/bash.js +1 -1
  398. package/dist/daemon/api/handlers/broker-ops.d.ts +3 -0
  399. package/dist/daemon/api/handlers/broker-ops.js +1 -1
  400. package/dist/daemon/api/handlers/broker-recovery.js +1 -1
  401. package/dist/daemon/api/handlers/broker-signals.d.ts +0 -3
  402. package/dist/daemon/api/handlers/broker-signals.js +2 -2
  403. package/dist/daemon/api/handlers/canvas.js +4 -4
  404. package/dist/daemon/api/handlers/charges.d.ts +1 -1
  405. package/dist/daemon/api/handlers/charges.js +1 -1
  406. package/dist/daemon/api/handlers/conversations.d.ts +2 -0
  407. package/dist/daemon/api/handlers/conversations.js +3 -0
  408. package/dist/daemon/api/handlers/crons.js +1 -1
  409. package/dist/daemon/api/handlers/daemon.js +1 -1
  410. package/dist/daemon/api/handlers/delivery.d.ts +1 -1
  411. package/dist/daemon/api/handlers/delivery.js +1 -1
  412. package/dist/daemon/api/handlers/docs.js +1 -1
  413. package/dist/daemon/api/handlers/exec.js +1 -1
  414. package/dist/daemon/api/handlers/execution-start.d.ts +2 -0
  415. package/dist/daemon/api/handlers/execution-start.js +2 -0
  416. package/dist/daemon/api/handlers/files.js +1 -1
  417. package/dist/daemon/api/handlers/git-credential.d.ts +11 -0
  418. package/dist/daemon/api/handlers/git-credential.js +1 -0
  419. package/dist/daemon/api/handlers/hook-exec.d.ts +1 -1
  420. package/dist/daemon/api/handlers/hook-exec.js +1 -1
  421. package/dist/daemon/api/handlers/human-requests.js +1 -1
  422. package/dist/daemon/api/handlers/inbox.js +1 -1
  423. package/dist/daemon/api/handlers/messages.js +1 -1
  424. package/dist/daemon/api/handlers/model-config.js +1 -1
  425. package/dist/daemon/api/handlers/modelauth.d.ts +1 -1
  426. package/dist/daemon/api/handlers/modelauth.js +1 -1
  427. package/dist/daemon/api/handlers/node-events.d.ts +6 -0
  428. package/dist/daemon/api/handlers/node-events.js +3 -3
  429. package/dist/daemon/api/handlers/node-outcomes.js +1 -1
  430. package/dist/daemon/api/handlers/node-records.js +3 -2
  431. package/dist/daemon/api/handlers/nodes.js +1 -1
  432. package/dist/daemon/api/handlers/objects.js +3 -3
  433. package/dist/daemon/api/handlers/profiles.js +1 -1
  434. package/dist/daemon/api/handlers/providers.js +1 -1
  435. package/dist/daemon/api/handlers/reports.js +9 -13
  436. package/dist/daemon/api/handlers/reviews.js +1 -1
  437. package/dist/daemon/api/handlers/runs.js +1 -1
  438. package/dist/daemon/api/handlers/settings.d.ts +2 -0
  439. package/dist/daemon/api/handlers/settings.js +1 -0
  440. package/dist/daemon/api/handlers/structured-requests.js +1 -1
  441. package/dist/daemon/api/handlers/vendor-status.d.ts +1 -1
  442. package/dist/daemon/api/handlers/vendor-status.js +1 -1
  443. package/dist/daemon/api/handlers/worktree.js +1 -1
  444. package/dist/daemon/api/map.d.ts +2 -2
  445. package/dist/daemon/api/map.js +2 -2
  446. package/dist/daemon/api/operations.js +1 -1
  447. package/dist/daemon/api/reader.d.ts +8 -1
  448. package/dist/daemon/api/reader.js +1 -1
  449. package/dist/daemon/api/router.d.ts +4 -2
  450. package/dist/daemon/api/router.js +1 -1
  451. package/dist/daemon/api/server.d.ts +15 -3
  452. package/dist/daemon/api/server.js +1 -1
  453. package/dist/daemon/api/vendor-signin.d.ts +2 -1
  454. package/dist/daemon/api/vendor-signin.js +19 -19
  455. package/dist/daemon/api/viewer-presence.d.ts +20 -6
  456. package/dist/daemon/api/viewer-presence.js +2 -1
  457. package/dist/daemon/boot-settings.d.ts +3 -0
  458. package/dist/daemon/boot-settings.js +1 -0
  459. package/dist/daemon/broker-signals/bus.d.ts +48 -11
  460. package/dist/daemon/broker-signals/bus.js +1 -1
  461. package/dist/daemon/cron/armed-context.js +1 -1
  462. package/dist/daemon/cron/lease-recovery.js +1 -1
  463. package/dist/daemon/cron/live-runs.d.ts +6 -0
  464. package/dist/daemon/cron/live-runs.js +1 -1
  465. package/dist/daemon/cron/run-socket.js +1 -1
  466. package/dist/daemon/cron-run.js +2 -2
  467. package/dist/daemon/crtrd-cli.js +1 -1
  468. package/dist/daemon/crtrd.d.ts +10 -0
  469. package/dist/daemon/crtrd.js +18 -17
  470. package/dist/daemon/delivery/run-delivery.d.ts +1 -1
  471. package/dist/daemon/delivery/run-delivery.js +1 -1
  472. package/dist/daemon/due-sources.d.ts +1 -1
  473. package/dist/daemon/due-sources.js +1 -1
  474. package/dist/daemon/due.js +7 -6
  475. package/dist/daemon/fleet.d.ts +6 -6
  476. package/dist/daemon/fleet.js +9 -9
  477. package/dist/daemon/park-activity.d.ts +2 -1
  478. package/dist/daemon/park-activity.js +1 -1
  479. package/dist/daemon/park-pending.d.ts +20 -13
  480. package/dist/daemon/park-pending.js +3 -1
  481. package/dist/daemon/profile-delete.js +1 -1
  482. package/dist/daemon/reconcilers/bash-deadline.d.ts +15 -10
  483. package/dist/daemon/reconcilers/bash-deadline.js +1 -3
  484. package/dist/daemon/reconcilers/broker-supervision.d.ts +13 -3
  485. package/dist/daemon/reconcilers/broker-supervision.js +4 -4
  486. package/dist/daemon/reconcilers/cron-lane.d.ts +0 -1
  487. package/dist/daemon/reconcilers/cron-lane.js +1 -1
  488. package/dist/daemon/reconcilers/fault-retry-backstop.d.ts +2 -9
  489. package/dist/daemon/reconcilers/fault-retry-backstop.js +1 -1
  490. package/dist/daemon/reconcilers/grant-effects.d.ts +8 -0
  491. package/dist/daemon/reconcilers/grant-effects.js +1 -0
  492. package/dist/daemon/reconcilers/grove-instance-sweep.d.ts +1 -3
  493. package/dist/daemon/reconcilers/grove-instance-sweep.js +1 -1
  494. package/dist/daemon/reconcilers/ledger-r2.d.ts +27 -0
  495. package/dist/daemon/reconcilers/ledger-r2.js +7 -0
  496. package/dist/daemon/reconcilers/ledger-sandbox.d.ts +55 -0
  497. package/dist/daemon/reconcilers/ledger-sandbox.js +9 -0
  498. package/dist/daemon/reconcilers/ledger-storage.d.ts +22 -0
  499. package/dist/daemon/reconcilers/ledger-storage.js +5 -0
  500. package/dist/daemon/reconcilers/live-obligation.d.ts +3 -2
  501. package/dist/daemon/reconcilers/live-obligation.js +1 -1
  502. package/dist/daemon/reconcilers/managed-worktree-sweep.d.ts +0 -5
  503. package/dist/daemon/reconcilers/managed-worktree-sweep.js +1 -1
  504. package/dist/daemon/reconcilers/node-deadline.d.ts +2 -1
  505. package/dist/daemon/reconcilers/node-deadline.js +1 -1
  506. package/dist/daemon/reconcilers/node-lifecycle/freeze-lane.d.ts +1 -2
  507. package/dist/daemon/reconcilers/node-lifecycle/freeze-lane.js +1 -1
  508. package/dist/daemon/reconcilers/node-lifecycle/remote-wake.d.ts +31 -0
  509. package/dist/daemon/reconcilers/node-lifecycle/remote-wake.js +1 -0
  510. package/dist/daemon/reconcilers/node-lifecycle/requested-stops.d.ts +5 -0
  511. package/dist/daemon/reconcilers/node-lifecycle/requested-stops.js +2 -0
  512. package/dist/daemon/reconcilers/node-lifecycle/tick.js +1 -1
  513. package/dist/daemon/reconcilers/pending-review-submit.js +1 -1
  514. package/dist/daemon/reconcilers/recipe-image.d.ts +49 -0
  515. package/dist/daemon/reconcilers/recipe-image.js +7 -0
  516. package/dist/daemon/reconcilers/row-claim.d.ts +19 -0
  517. package/dist/daemon/reconcilers/row-claim.js +2 -0
  518. package/dist/daemon/reconcilers/storage-due-work.d.ts +18 -3
  519. package/dist/daemon/reconcilers/storage-due-work.js +2 -1
  520. package/dist/daemon/reconcilers/storage-maintenance.d.ts +5 -13
  521. package/dist/daemon/reconcilers/storage-maintenance.js +1 -1
  522. package/dist/daemon/reconcilers/structured-request-lane.js +1 -1
  523. package/dist/daemon/reconcilers/throttled-lane.d.ts +11 -0
  524. package/dist/daemon/reconcilers/throttled-lane.js +1 -0
  525. package/dist/daemon/review/finish.js +1 -1
  526. package/dist/daemon/run-notices.d.ts +3 -0
  527. package/dist/daemon/run-notices.js +1 -1
  528. package/dist/daemon/runs/append-section.d.ts +4 -1
  529. package/dist/daemon/runs/append-section.js +2 -2
  530. package/dist/daemon/runs/observer.d.ts +3 -2
  531. package/dist/daemon/runs/observer.js +3 -2
  532. package/dist/daemon/runs/view-transport.d.ts +19 -0
  533. package/dist/daemon/runs/view-transport.js +1 -0
  534. package/dist/daemon/structured-requests/boot.d.ts +2 -1
  535. package/dist/daemon/structured-requests/boot.js +1 -1
  536. package/dist/daemon/structured-requests/effects.d.ts +4 -3
  537. package/dist/daemon/structured-requests/effects.js +1 -1
  538. package/dist/daemon/structured-requests/notifier.d.ts +2 -0
  539. package/dist/daemon/structured-requests/notifier.js +1 -1
  540. package/dist/daemon/structured-requests/sidecar.d.ts +4 -3
  541. package/dist/daemon/structured-requests/sidecar.js +1 -1
  542. package/dist/launcher/validate.js +1 -1
  543. package/dist/migrations/004-canvas-documents/index.js +2 -2
  544. package/dist/pi-extensions/broker-local.d.ts +3 -3
  545. package/dist/pi-extensions/broker-local.js +1 -2
  546. package/dist/pi-extensions/canvas-bash-valve.js +6 -6
  547. package/dist/pi-extensions/canvas-context-intro.js +2 -2
  548. package/dist/pi-extensions/canvas-elapsed.js +2 -2
  549. package/dist/pi-extensions/canvas-goal-capture.js +1 -1
  550. package/dist/pi-extensions/canvas-inbox-watcher.js +2 -2
  551. package/dist/pi-extensions/canvas-review-boundary.d.ts +11 -1
  552. package/dist/pi-extensions/canvas-review-boundary.js +3 -3
  553. package/dist/pi-extensions/canvas-stophook.js +1 -1
  554. package/dist/pi-extensions/canvas-structured-output.d.ts +5 -3
  555. package/dist/pi-extensions/canvas-structured-output.js +6 -11
  556. package/dist/pi-extensions/canvas-tool-guide.d.ts +9 -2
  557. package/dist/pi-extensions/canvas-tool-guide.js +6 -6
  558. package/dist/shared/inbox-entry-body.js +7 -7
  559. package/dist/types.d.ts +12 -0
  560. package/docs/sdk/release-notes.md +4 -0
  561. package/package.json +7 -4
  562. package/packages/crouter-identity/package.json +1 -1
  563. package/runtime.lock.json +13 -13
  564. package/scripts/git-credential-crtr +33 -0
  565. package/scripts/sandbox-bootstrap.sh +54 -0
  566. package/scripts/sandbox-start.mjs +320 -0
  567. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.d.ts +0 -78
  568. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.js +0 -1179
  569. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.ts +0 -1406
  570. package/dist/core/conversation-store/file-store.d.ts +0 -37
  571. package/dist/core/conversation-store/file-store.js +0 -9
  572. package/dist/core/conversation-store/listener.d.ts +0 -4
  573. package/dist/core/conversation-store/listener.js +0 -8
  574. package/dist/core/scoped-state/profiles.d.ts +0 -27
  575. package/dist/core/scoped-state/profiles.js +0 -1
  576. package/dist/core/scoped-state/providers.d.ts +0 -24
  577. package/dist/core/scoped-state/providers.js +0 -1
  578. package/dist/core/scoped-state/settings.d.ts +0 -28
  579. package/dist/core/scoped-state/settings.js +0 -1
@@ -1,3 +1,3 @@
1
- var se=Object.defineProperty;var d=(e,o)=>se(e,"name",{value:o,configurable:!0});import{accessSync as ce,constants as le}from"node:fs";import{isAbsolute as fe,resolve as ue,join as me}from"node:path";import{appSpace as we}from"../layout.js";import{ApiError as J}from"../../api/errors.js";import{spawnNode as he,forkSourceNode as pe,currentNodeContext as ke,rootOfSpine as _e,newNodeId as ve,preflightNodeId as ye}from"./nodes.js";import{resolveProfileOperand as ge}from"../profiles/manifest.js";import{selectProfileForCwd as be,selectProfileForCwdReadOnly as xe}from"../profiles/select.js";import{buildLaunchSpecAsync as Q,buildPiArgv as Ce}from"./launch.js";import{createManagedWorktreeAsync as Ee,rollbackManagedWorktreeAsync as $e}from"../worktree-mutation-async.js";import{usage as u,brokerLaunchFailed as N}from"../errors.js";import{writeGoal as Fe}from"./kickoff.js";import{appendSituationalContext as Se,formatSituationalProse as Oe}from"./situational-context.js";import{ensureRoadmap as Re}from"./roadmap.js";import{buildWakeBearings as Ie}from"./bearings.js";import{encodeKickoffOrigin as Ne,KICKOFF_ORIGIN_ENV as Pe}from"./stamp/protocol.js";import{beginExecution as Be,crtrHome as De,getNode as f,fullName as Z,jobDir as Te,recordExecutionPid as Le,abortExecution as A,setFrozen as Ae}from"../canvas/index.js";import{contextDir as M,nodeAgentDir as j}from"../canvas/node-agent-paths.js";import{copyTreeBeneath as Me}from"../spaces/open-beneath.js";import{conversationIdFromPath as P,conversationStore as x}from"../conversation-store/index.js";import{appMemoryTooSmall as je,boundFleet as We,brokerThresholdsForDaemon as He}from"./fleet.js";import{admitBrokerMemory as Ke}from"./memory-admission.js";import{emitEvent as ze}from"../events/emit.js";import{openViewerWindow as Ge,focusOf as Ue,windowOfPane as Ve}from"./placement.js";import{waitForBrokerViewSocket as Xe}from"./placement-tmux.js";import{transition as h}from"./lifecycle.js";import{beginBootFaultAttempt as qe}from"../canvas/recovery.js";import{headlessBrokerHost as W}from"./host.js";import{ensureDaemon as Ye}from"../../daemon/manage.js";import{readConfig as Je}from"../config.js";import{modelRequestFromConfig as Qe,unregisteredConcreteModel as Ze}from"../model-routes.js";import{openModelRegistry as en}from"./model-registry.js";import{MODEL_SPEC_NEXT as nn}from"./model-selection.js";import{forkNodeLedger as on}from"./ledger.js";import{appRungForGrant as rn}from"../llm/app-rungs.js";import{APP_FAMILY as H}from"../model-routes.js";import{discoverLifecycleHookRegistry as tn}from"../command-hooks/discovery.js";import{invokeLifecycleHooks as an}from"../command-hooks/transport/exec-lifecycle.js";import{someAsync as dn}from"../async-array.js";import{checkStart as sn}from"./start-check.js";function p(e){return{detail:{schema:"crtr.node-outcome-detail/v1",message:e instanceof Error?e.message:String(e)}}}d(p,"launchFailureOutcome");async function cn(e,o,a){try{return await W.launch(e,o,a)}catch(r){try{await h(e,"crash",{reason:"launch_failed",outcome:p(r)})}catch{}const t=r.message;throw N(t.startsWith("[broker]")?t:`[broker] refusing to launch ${e}: ${t}`,"Inspect the cause above, fix the launch recipe or environment, then retry.")}}d(cn,"launchBrokerOrCrash");async function ln(e,o){try{await h(e,"crash",{reason:"launch_failed",outcome:p(o)})}catch{}try{W.teardown(e)}catch{}}d(ln,"crashAndTearDown");async function fn(e){const o=(await x().list()).map(({conversation_id:t,path:s})=>({id:t,path:s})),a=o.filter(t=>t.id===e),r=a.length>0?a:o.filter(t=>t.id.startsWith(e));if(r.length===0)throw u(`--fork-from '${e}': no pi session with that id found.`,{next:"Pass a live node id, a real session uuid/prefix, or an absolute .jsonl session path."});if(r.length>1)throw u(`--fork-from '${e}': ambiguous \u2014 ${r.length} sessions match that id prefix; pass the full id or the .jsonl path.`,{next:"Pass the full session uuid or an absolute .jsonl path to disambiguate."});return r[0].path}d(fn,"resolveSessionUuid");async function ee(e){const o=e.trim();if(o==="")throw u("--fork-from requires a node id, session file, or session uuid.",{next:"Pass a live node id, an absolute .jsonl session path, or a session uuid/prefix."});if(o.includes("/")||o.endsWith(".jsonl")){const r=P(fe(o)?o:ue(process.cwd(),o));if(r===null)throw u(`--fork-from '${o}': invalid conversation path.`,{next:"Pass a conversation file path or id."});return(await x().header(r)).path}const a=await f(o);if(a!==null){const r=a.pi_session_file;if(r==null||r==="")throw u(`node ${o} has no pi session yet \u2014 it has not captured a session FILE to fork from (the broker forks a .jsonl path, not a bare id).`,{next:"Pick a node that has captured a session, or drop --fork-from."});const t=P(r);if(t===null)throw u(`node ${o} has no valid conversation id.`,{next:"Pick a node with a captured conversation."});return(await x().header(t)).path}return await fn(o)}d(ee,"resolveForkSource");async function un(e,o,a,r={}){return e===null?null:e!==void 0&&e!==""?ge(e).profileId:o!==null?(await f(o))?.profile_id??null:r.readOnlySelection===!0?xe(a):be(a)}d(un,"resolveProfileId");function ne(e){const o=e.modelIntent===void 0?void 0:`${e.modelIntent.family}/${e.modelIntent.strength}`;return Qe(e.model,o,e.modelExact===!0)}d(ne,"requestFromLaunch");async function oe(e,o,a){const r=a??(e.modelIntent?`${e.modelIntent.family}/${e.modelIntent.strength}`:e.model),t=await rn(o,r,e.modelExact===!0);if(t===null)return e;const{CRTR_MODEL_INTENT:s,...c}=e.env??{};return{...e,model:t.model,modelIntent:{family:H,strength:t.strength},modelExact:void 0,env:{...c,CRTR_MODEL_INTENT:`${H}/${t.strength}`}}}d(oe,"appPaidLaunch");async function re(e,o,a){if(e===void 0||e.kind==="logical"&&e.family!==H)return;const r=Ze(e.kind==="logical"?{kind:"concrete",spec:e.spec}:e,a??await en(),o);if(r!==void 0)throw u(`model '${r.request.spec}' is not registered in this daemon.`,{received:r.request.spec,next:nn})}d(re,"assertLaunchModelRegistered");function mn(e,o,a){const r=e??o??null;if(!a&&r===null)throw new Error("spawnChild requires a calling node (CRTR_NODE_ID) or an explicit parent");return r}d(mn,"resolveSpawner");async function ie(e,o,a){try{Ye()}catch{}const r=ke(),t=e.root===!0,s=mn(e.parent,r.nodeId??null,t),c=e.mode??"base",k=e.rootLifecycle??(t?"resident":"terminal"),te=t&&k==="resident",$=s===null?null:await f(s),K=e.creator===void 0||e.creator===null?null:await f(e.creator);e.nodeId!==void 0&&await ye(e.nodeId);const _=e.forkFrom!==void 0?await ee(e.forkFrom):void 0,B=_===void 0?null:await pe(_),D=await dn([$,K,B],async l=>l?.isolated===!0||l?.run_id!=null&&(await f(l.run_id))?.isolated===!0);if(D&&e.isolated===!1)throw new J(403,"isolated_run","isolation cannot be turned off under an isolated run",{param:"isolated"});const F=D||e.isolated===!0;if(F&&e.worktree===!0)throw new J(400,"invalid_request","isolated nodes cannot use a worktree",{param:"worktree"});const S=e.worktree===!0,v=F||S?e.nodeId??await ve():e.nodeId,O=F?e.run!==void 0&&t&&!D?e.cwd:me(we(e.run?.grantee??$?.grantee??"app:terminal").nodes,v):e.cwd,C=await un(e.profile,s,O),z=e.run?.grant_id??$?.grant_id??null,G=await oe((await Q(e.kind,c,{lifecycle:k,hasManager:!t,model:e.model,modelOverride:e.model!==void 0,cwd:O,profileId:C})).launch,z,e.model);await re(ne(G),{cwd:O,profileId:C});const T=e.run??K??$??B;await sn({grantee:T?.grantee??"app:terminal",sub:T?.sub,grant_id:T?.grant_id});const U=B?.node_id??null;let y,R=O;try{S&&(y=await Ee(e.worktreeCwd??e.cwd,v,e.worktreeBase),R=y.path);const l=S?await oe((await Q(e.kind,c,{lifecycle:k,hasManager:!t,model:e.model,modelOverride:e.model!==void 0,cwd:R,profileId:C})).launch,z,e.model):G;S&&await re(ne(l),{cwd:R,profileId:C});const n=await he({kind:e.kind,mode:c,lifecycle:k,cwd:R,name:e.name??e.kind,description:e.description,parent:t?null:s,creator:e.creator,...e.actor===void 0?{}:{actor:e.actor},forkSourceNode:U,spawnedBy:t?s??void 0:void 0,profile_id:C,...e.scopes===void 0?{}:{scopes:e.scopes},isolated:F,...e.run===void 0?{}:{run:e.run},...e.causedBy===void 0?{}:{causedBy:e.causedBy},...e.withinCreate===void 0?{}:{withinCreate:e.withinCreate},forkFrom:e.forkFrom,forkSourceFile:_,modelOverride:e.model===void 0?void 0:l.model,...y!==void 0?{managedWorktree:y}:{},...v!==void 0?{nodeId:v}:{},...e.reviewBinding===void 0?{}:{reviewBinding:e.reviewBinding},...e.deadlineAt===void 0?{}:{deadlineAt:e.deadlineAt},...e.outcomeDelivery===void 0?{}:{outcomeDelivery:e.outcomeDelivery},launch:l});if(a?.(n.node_id),e.forkFrom!==void 0)try{await on(n.node_id,U??null)}catch(i){throw await h(n.node_id,"crash",{reason:"launch_failed",outcome:p(i)}),i}if(await Fe(n.node_id,e.prompt),e.situationalContext!==void 0&&Se(n.node_id,Oe(e.situationalContext)),o!==void 0)try{o(n.node_id)}catch(i){throw await h(n.node_id,"crash",{reason:"launch_failed",outcome:p(i)}),i}const L=e.prompt!=="",ae=`${L&&e.wakeOrigin!==void 0?`${Ie(e.wakeOrigin)}
1
+ var we=Object.defineProperty;var d=(e,o)=>we(e,"name",{value:o,configurable:!0});import{accessSync as me,constants as he}from"node:fs";import{isAbsolute as pe,resolve as ke,join as _e}from"node:path";import{appSpace as ve}from"../layout.js";import{ApiError as Q}from"../../api/errors.js";import{spawnNode as ye,forkSourceNode as ge,currentNodeContext as be,rootOfSpine as xe,newNodeId as Ce,preflightNodeId as Ee}from"./nodes.js";import{resolveProfileOperand as Re}from"../profiles/manifest.js";import{selectProfileForCwd as Se,selectProfileForCwdReadOnly as $e}from"../profiles/select.js";import{buildLaunchSpecAsync as Z,buildPiArgv as Fe}from"./launch.js";import{runsOnBlaxel as Oe,sandboxWorktreeRequest as Ie}from"../../daemon/api/environment-of.js";import{createManagedWorktreeAsync as Be,rollbackManagedWorktreeAsync as Ne}from"../worktree-mutation-async.js";import{usage as u,brokerLaunchFailed as B}from"../errors.js";import{writeGoal as Pe}from"./kickoff.js";import{appendSituationalContext as De,formatSituationalProse as Te}from"./situational-context.js";import{ensureRoadmap as Le}from"./roadmap.js";import{buildWakeBearings as Ae}from"./bearings.js";import{encodeKickoffOrigin as Me,KICKOFF_ORIGIN_ENV as We}from"./stamp/protocol.js";import{ExecutionCapReached as je,beginExecution as He,crtrHome as ze,getNode as f,fullName as ee,jobDir as Ke,recordExecutionPid as Ge,abortExecution as M,setFrozen as ne}from"../canvas/index.js";import{contextDir as W,nodeAgentDir as j}from"../canvas/node-agent-paths.js";import{copyTreeBeneath as Ue}from"../spaces/open-beneath.js";import{conversationIdFromPath as N,conversationStore as E}from"../conversation-store/index.js";import{appMemoryTooSmall as Ve,boundFleet as Xe,brokerThresholdsForDaemon as oe}from"./fleet.js";import{admitBrokerMemory as qe}from"./memory-admission.js";import{emitEvent as re}from"../events/emit.js";import{openViewerWindow as Ye,focusOf as Je,windowOfPane as Qe}from"./placement.js";import{waitForBrokerViewSocket as Ze}from"./placement-tmux.js";import{transition as _}from"./lifecycle.js";import{beginBootFaultAttempt as en}from"../canvas/recovery.js";import{headlessBrokerHost as H}from"./host.js";import{ensureDaemon as nn}from"../../daemon/manage.js";import{readConfig as on}from"../config.js";import{modelRequestFromConfig as rn,unregisteredConcreteModel as tn}from"../model-routes.js";import{openModelRegistry as an}from"./model-registry.js";import{MODEL_SPEC_NEXT as dn}from"./model-selection.js";import{forkNodeLedger as sn}from"./ledger.js";import{appRungForGrant as cn}from"../llm/app-rungs.js";import{APP_FAMILY as z}from"../model-routes.js";import{discoverLifecycleHookRegistry as ln}from"../command-hooks/discovery.js";import{invokeLifecycleHooks as fn}from"../command-hooks/transport/exec-lifecycle.js";import{someAsync as un}from"../async-array.js";import{checkStart as wn}from"./start-check.js";function v(e){return{detail:{schema:"crtr.node-outcome-detail/v1",message:e instanceof Error?e.message:String(e)}}}d(v,"launchFailureOutcome");async function mn(e,o,a){try{return await H.launch(e,o,a)}catch(i){try{await _(e,"crash",{reason:"launch_failed",outcome:v(i)})}catch{}const t=i.message;throw B(t.startsWith("[broker]")?t:`[broker] refusing to launch ${e}: ${t}`,"Inspect the cause above, fix the launch recipe or environment, then retry.")}}d(mn,"launchBrokerOrCrash");async function hn(e,o){try{await _(e,"crash",{reason:"launch_failed",outcome:v(o)})}catch{}try{H.teardown(e)}catch{}}d(hn,"crashAndTearDown");async function pn(e){const o=(await E().list()).map(({conversation_id:t,path:s})=>({id:t,path:s})),a=o.filter(t=>t.id===e),i=a.length>0?a:o.filter(t=>t.id.startsWith(e));if(i.length===0)throw u(`--fork-from '${e}': no pi session with that id found.`,{next:"Pass a live node id, a real session uuid/prefix, or an absolute .jsonl session path."});if(i.length>1)throw u(`--fork-from '${e}': ambiguous \u2014 ${i.length} sessions match that id prefix; pass the full id or the .jsonl path.`,{next:"Pass the full session uuid or an absolute .jsonl path to disambiguate."});return i[0].path}d(pn,"resolveSessionUuid");async function ie(e){const o=e.trim();if(o==="")throw u("--fork-from requires a node id, session file, or session uuid.",{next:"Pass a live node id, an absolute .jsonl session path, or a session uuid/prefix."});if(o.includes("/")||o.endsWith(".jsonl")){const i=N(pe(o)?o:ke(process.cwd(),o));if(i===null)throw u(`--fork-from '${o}': invalid conversation path.`,{next:"Pass a conversation file path or id."});return(await E().header(i)).path}const a=await f(o);if(a!==null){const i=a.pi_session_file;if(i==null||i==="")throw u(`node ${o} has no pi session yet \u2014 it has not captured a session FILE to fork from (the broker forks a .jsonl path, not a bare id).`,{next:"Pick a node that has captured a session, or drop --fork-from."});const t=N(i);if(t===null)throw u(`node ${o} has no valid conversation id.`,{next:"Pick a node with a captured conversation."});return(await E().header(t)).path}return await pn(o)}d(ie,"resolveForkSource");async function kn(e,o,a,i={}){return e===null?null:e!==void 0&&e!==""?Re(e).profileId:o!==null?(await f(o))?.profile_id??null:i.readOnlySelection===!0?$e(a):Se(a)}d(kn,"resolveProfileId");function te(e){const o=e.modelIntent===void 0?void 0:`${e.modelIntent.family}/${e.modelIntent.strength}`;return rn(e.model,o,e.modelExact===!0)}d(te,"requestFromLaunch");async function ae(e,o,a){const i=a??(e.modelIntent?`${e.modelIntent.family}/${e.modelIntent.strength}`:e.model),t=await cn(o,i,e.modelExact===!0);if(t===null)return e;const{CRTR_MODEL_INTENT:s,...c}=e.env??{};return{...e,model:t.model,modelIntent:{family:z,strength:t.strength},modelExact:void 0,env:{...c,CRTR_MODEL_INTENT:`${z}/${t.strength}`}}}d(ae,"appPaidLaunch");async function de(e,o,a){if(e===void 0||e.kind==="logical"&&e.family!==z)return;const i=await tn(e.kind==="logical"?{kind:"concrete",spec:e.spec}:e,a??await an(),o);if(i!==void 0)throw u(`model '${i.request.spec}' is not registered in this daemon.`,{received:i.request.spec,next:dn})}d(de,"assertLaunchModelRegistered");function _n(e,o,a){const i=e??o??null;if(!a&&i===null)throw new Error("spawnChild requires a calling node (CRTR_NODE_ID) or an explicit parent");return i}d(_n,"resolveSpawner");async function se(e,o,a){try{nn()}catch{}const i=be(),t=e.root===!0,s=_n(e.parent,i.nodeId??null,t),c=e.mode??"base",y=e.rootLifecycle??(t?"resident":"terminal"),ce=t&&y==="resident",S=s===null?null:await f(s),K=e.creator===void 0||e.creator===null?null:await f(e.creator);e.nodeId!==void 0&&await Ee(e.nodeId);const g=e.forkFrom!==void 0?await ie(e.forkFrom):void 0,P=g===void 0?null:await ge(g),D=await un([S,K,P],async l=>l?.isolated===!0||l?.run_id!=null&&(await f(l.run_id))?.isolated===!0);if(D&&e.isolated===!1)throw new Q(403,"isolated_run","isolation cannot be turned off under an isolated run",{param:"isolated"});const $=D||e.isolated===!0;if($&&e.worktree===!0)throw new Q(400,"invalid_request","isolated nodes cannot use a worktree",{param:"worktree"});const R=e.worktree===!0,w=$||R?e.nodeId??await Ce():e.nodeId,F=$?e.run!==void 0&&t&&!D?e.cwd:_e(ve(e.run?.grantee??S?.grantee??"app:terminal").nodes,w):e.cwd,m=await kn(e.profile,s,F),G=e.run?.grant_id??S?.grant_id??null,U=await ae((await Z(e.kind,c,{lifecycle:y,hasManager:!t,model:e.model,modelOverride:e.model!==void 0,cwd:F,profileId:m})).launch,G,e.model);await de(te(U),{cwd:F,profileId:m});const T=e.run??K??S??P;await wn({grantee:T?.grantee??"app:terminal",sub:T?.sub,grant_id:T?.grant_id});const V=P?.node_id??null;let b,O=F;const L=R&&await Oe(m)?await Ie(m,e.worktreeCwd??e.cwd,w,e.worktreeBase):void 0;try{R&&L===void 0&&(b=await Be(e.worktreeCwd??e.cwd,w,e.worktreeBase),O=b.path);const l=R?await ae((await Z(e.kind,c,{lifecycle:y,hasManager:!t,model:e.model,modelOverride:e.model!==void 0,cwd:O,profileId:m})).launch,G,e.model):U;L!==void 0&&(l.worktree=L),R&&await de(te(l),{cwd:O,profileId:m});const n=await ye({kind:e.kind,mode:c,lifecycle:y,cwd:O,name:e.name??e.kind,description:e.description,parent:t?null:s,creator:e.creator,...e.actor===void 0?{}:{actor:e.actor},forkSourceNode:V,spawnedBy:t?s??void 0:void 0,profile_id:m,...e.scopes===void 0?{}:{scopes:e.scopes},isolated:$,...e.run===void 0?{}:{run:e.run},...e.causedBy===void 0?{}:{causedBy:e.causedBy},...e.withinCreate===void 0?{}:{withinCreate:e.withinCreate},forkFrom:e.forkFrom,forkSourceFile:g,modelOverride:e.model===void 0?void 0:l.model,...b!==void 0?{managedWorktree:b}:{},...w!==void 0?{nodeId:w}:{},...e.reviewBinding===void 0?{}:{reviewBinding:e.reviewBinding},...e.deadlineAt===void 0?{}:{deadlineAt:e.deadlineAt},...e.outcomeDelivery===void 0?{}:{outcomeDelivery:e.outcomeDelivery},launch:l});if(a?.(n.node_id),e.forkFrom!==void 0)try{await sn(n.node_id,V??null)}catch(r){throw await _(n.node_id,"crash",{reason:"launch_failed",outcome:v(r)}),r}if(await Pe(n.node_id,e.prompt),e.situationalContext!==void 0&&await De(n.node_id,Te(e.situationalContext)),o!==void 0)try{o(n.node_id)}catch(r){throw await _(n.node_id,"crash",{reason:"launch_failed",outcome:v(r)}),r}const A=e.prompt!=="",le=`${A&&e.wakeOrigin!==void 0?`${Ae(e.wakeOrigin)}
2
2
 
3
- `:""}${e.prompt}`;c==="orchestrator"&&await Re(n.node_id,{goal:e.prompt.trim()}),await wn(n);let V;if(_!==void 0)try{const i=P(_);if(i===null)throw new Error(`invalid fork source ${_}`);const w=await x().fork(i,n.node_id);V=(await x().header(w)).path}catch(i){throw await h(n.node_id,"crash",{reason:"launch_failed",outcome:p(i)}),i}const g=Ce(n,{prompt:ae,resumeSessionPath:V});if(g.env={...g.env,CRTR_SUBTREE:await _e(n.node_id)},L){const i=e.wakeOrigin!==void 0?{type:"runtime",kind:"wake",wake:e.wakeOrigin}:{type:"runtime",kind:"kickoff",...n.spawned_by!=null&&n.spawned_by!==""?{spawnedBy:n.spawned_by}:{}};g.env[Pe]=Ne(i)}const b=We(),X=b.reserveSlot(n.node_id),m=X?await Ke(n.node_id):null;if(m?.verdict==="too_small"){b.releaseReservation(n.node_id);const i=je(m);throw await h(n.node_id,"crash",{reason:"launch_failed",outcome:p(i)}),i}if(!X||m?.verdict==="denied")return m?.verdict==="denied"&&b.releaseReservation(n.node_id),await Ae(n.node_id,new Date().toISOString()),ze({level:"info",event:"broker.frozen",node_id:n.node_id,fields:m?.verdict==="denied"?{reason:"app_memory",free_bytes:m.free_bytes,needed_bytes:m.needed_bytes}:{reason:"broker_cap",live_count:b.size(),hard_cap:He().automaticReviveCap}}),{node:await f(n.node_id),frozen:!0,window:null,session:null};const de=await qe(n.node_id),E=await Be(n.node_id,{daemonEpoch:b.epoch()});g.env={...g.env,CRTR_EXECUTION_ID:E};let I;try{I=await cn(n.node_id,g,{cwd:n.cwd,name:Z(n),resuming:!1})}catch(i){throw await A(E,{reason:"launch_failed"}),i}finally{b.releaseReservation(n.node_id)}if(I.pid===null){const i=new Error(`broker host returned no pid for ${n.node_id}`);throw await A(E,{reason:"launch_failed"}),await h(n.node_id,"crash",{reason:"launch_failed",outcome:p(i)}),N(`failed to launch the broker engine for ${n.node_id} (${n.name}) \u2014 the node was not started.`,`Inspect canonical event diagnostics with \`crtr sys logs --node ${n.node_id}\`, then verify the pi engine can start in this environment.`)}if(await Le(E,n.node_id,I.pid)==="shutdown")throw await A(E,{reason:"superseded"}),W.teardown(n.node_id),N(`broker execution was superseded for ${n.node_id}`,"Retry spawning the node.");if(te&&e.readiness==="await"&&!await Xe(n.node_id,I.exited)){const i=await de.explanation();throw await ln(n.node_id,new Error(i??`broker view socket never bound for ${n.node_id}`)),N(i!==null?`the root broker ${n.node_id} could not start \u2014 ${i}`:`the root broker ${n.node_id} never bound its view socket \u2014 it was not started.`,i!==null?"Resolve the cause named above, then retry.":`The broker engine exited before binding its view socket. Inspect canonical event diagnostics with \`crtr sys logs --node ${n.node_id}\`, then retry.`)}let q=null,Y=null;if(!t&&s!==null&&Je("user").auto_open_child_viewers)try{const i=await Ue(s);if(i!==null&&i.pane!==null&&i.pane!==""){const w=await Ge(n.node_id,i.session??"",{name:Z(n),cwd:e.cwd,besidePane:i.pane,waitForBroker:!0,initialWhip:L});w!==null&&w.pane!==null&&w.pane!==""&&(Y=w.session,q=Ve(w.pane))}}catch{}return{node:await f(n.node_id),frozen:!1,window:q,session:Y}}catch(l){throw y!==void 0&&v!==void 0&&await f(v)===null&&await $e(y),l}}d(ie,"spawnChildPrepared");async function io(e){return ie(e)}d(io,"spawnChild");async function wn(e){const o=tn(e.cwd,e.profile_id).plans.get("node:start")??[];await an(o,{node:{id:e.node_id,name:e.name,kind:e.kind,mode:e.mode,lifecycle:e.lifecycle,cwd:e.cwd,nodeDir:await j(e.node_id),contextDir:await M(e.node_id),jobDir:Te(e.node_id)},runtime:{isBirth:!0,canvasHome:De(),profile:e.profile_id??null}})}d(wn,"invokeBirthLifecycleHooks");const hn=new Set(["initial-prompt.md","yield-message.md","result.json","jobs"]);async function to(e,o,a){const r=await f(e);if(r===null)throw u(`unknown node: ${e}`,{received:e,next:"List nodes and pass the id of a node with a captured pi session."});const t=await ee(e),s=await M(e);try{await x().header(P(t)),ce(s,le.R_OK)}catch(c){throw new Error(`cannot fork ${e}: its conversation or context is unreadable \u2014 ${c.message}`)}return ie({kind:r.kind,mode:"base",cwd:r.cwd,prompt:"",root:!0,readiness:"await",forkFrom:e,...a===void 0?{}:{actor:a},profile:r.profile_id,model:r.model_override??void 0,...o===void 0?{}:{scopes:o}},async c=>{const k=await M(c);Me(await j(e),s,await j(c),k,hn)})}d(to,"forkNode");export{oe as appPaidLaunch,re as assertLaunchModelRegistered,to as forkNode,wn as invokeBirthLifecycleHooks,ee as resolveForkSource,un as resolveProfileId,mn as resolveSpawner,io as spawnChild,ie as spawnChildPrepared};
3
+ `:""}${e.prompt}`;c==="orchestrator"&&await Le(n.node_id,{goal:e.prompt.trim()}),await vn(n);let X;if(g!==void 0)try{const r=N(g);if(r===null)throw new Error(`invalid fork source ${g}`);const k=await E().fork(r,n.node_id);X=(await E().header(k)).path}catch(r){throw await _(n.node_id,"crash",{reason:"launch_failed",outcome:v(r)}),r}const x=Fe(n,{prompt:le,resumeSessionPath:X});if(x.env={...x.env,CRTR_SUBTREE:await xe(n.node_id)},A){const r=e.wakeOrigin!==void 0?{type:"runtime",kind:"wake",wake:e.wakeOrigin}:{type:"runtime",kind:"kickoff",...n.spawned_by!=null&&n.spawned_by!==""?{spawnedBy:n.spawned_by}:{}};x.env[We]=Me(r)}const h=Xe(),q=await h.reserveSlot(n.node_id),p=q?await qe(n.node_id):null;if(p?.verdict==="too_small"){h.releaseReservation(n.node_id);const r=Ve(p);throw await _(n.node_id,"crash",{reason:"launch_failed",outcome:v(r)}),r}if(!q||p?.verdict==="denied")return p?.verdict==="denied"&&h.releaseReservation(n.node_id),await ne(n.node_id,new Date().toISOString()),re({level:"info",event:"broker.frozen",node_id:n.node_id,fields:p?.verdict==="denied"?{reason:"app_memory",free_bytes:p.free_bytes,needed_bytes:p.needed_bytes}:{reason:"broker_cap",live_count:await h.occupancy(),hard_cap:oe().automaticReviveCap}}),{node:await f(n.node_id),frozen:!0,window:null,session:null};const fe=await en(n.node_id),{automaticReviveCap:ue}=oe();let C;try{C=await He(n.node_id,{daemonEpoch:h.epoch(),cap:ue})}catch(r){if(!(r instanceof je))throw r;return h.releaseReservation(n.node_id),await ne(n.node_id,new Date().toISOString()),re({level:"info",event:"broker.frozen",node_id:n.node_id,fields:{reason:"broker_cap",live_count:r.live,hard_cap:r.cap}}),{node:await f(n.node_id),frozen:!0,window:null,session:null}}x.env={...x.env,CRTR_EXECUTION_ID:C};let I;try{I=await mn(n.node_id,x,{cwd:n.cwd,name:ee(n),resuming:!1})}catch(r){throw await M(C,{reason:"launch_failed"}),r}finally{h.releaseReservation(n.node_id)}if(I.pid===null){const r=new Error(`broker host returned no pid for ${n.node_id}`);throw await M(C,{reason:"launch_failed"}),await _(n.node_id,"crash",{reason:"launch_failed",outcome:v(r)}),B(`failed to launch the broker engine for ${n.node_id} (${n.name}) \u2014 the node was not started.`,`Inspect canonical event diagnostics with \`crtr sys logs --node ${n.node_id}\`, then verify the pi engine can start in this environment.`)}if(await Ge(C,n.node_id,I.pid)==="shutdown")throw await M(C,{reason:"superseded"}),H.teardown(n.node_id),B(`broker execution was superseded for ${n.node_id}`,"Retry spawning the node.");if(ce&&e.readiness==="await"&&!await Ze(n.node_id,I.exited)){const r=await fe.explanation();throw await hn(n.node_id,new Error(r??`broker view socket never bound for ${n.node_id}`)),B(r!==null?`the root broker ${n.node_id} could not start \u2014 ${r}`:`the root broker ${n.node_id} never bound its view socket \u2014 it was not started.`,r!==null?"Resolve the cause named above, then retry.":`The broker engine exited before binding its view socket. Inspect canonical event diagnostics with \`crtr sys logs --node ${n.node_id}\`, then retry.`)}let Y=null,J=null;if(!t&&s!==null&&on("user").auto_open_child_viewers)try{const r=await Je(s);if(r!==null&&r.pane!==null&&r.pane!==""){const k=await Ye(n.node_id,r.session??"",{name:ee(n),cwd:e.cwd,besidePane:r.pane,waitForBroker:!0,initialWhip:A});k!==null&&k.pane!==null&&k.pane!==""&&(J=k.session,Y=Qe(k.pane))}}catch{}return{node:await f(n.node_id),frozen:!1,window:Y,session:J}}catch(l){throw b!==void 0&&w!==void 0&&await f(w)===null&&await Ne(b),l}}d(se,"spawnChildPrepared");async function fo(e){return se(e)}d(fo,"spawnChild");async function vn(e){const o=ln(e.cwd,e.profile_id).plans.get("node:start")??[];await fn(o,{node:{id:e.node_id,name:e.name,kind:e.kind,mode:e.mode,lifecycle:e.lifecycle,cwd:e.cwd,nodeDir:await j(e.node_id),contextDir:await W(e.node_id),jobDir:Ke(e.node_id)},runtime:{isBirth:!0,canvasHome:ze(),profile:e.profile_id??null}})}d(vn,"invokeBirthLifecycleHooks");const yn=new Set(["initial-prompt.md","yield-message.md","result.json","jobs"]);async function uo(e,o,a){const i=await f(e);if(i===null)throw u(`unknown node: ${e}`,{received:e,next:"List nodes and pass the id of a node with a captured pi session."});const t=await ie(e),s=await W(e);try{await E().header(N(t)),me(s,he.R_OK)}catch(c){throw new Error(`cannot fork ${e}: its conversation or context is unreadable \u2014 ${c.message}`)}return se({kind:i.kind,mode:"base",cwd:i.cwd,prompt:"",root:!0,readiness:"await",forkFrom:e,...a===void 0?{}:{actor:a},profile:i.profile_id,model:i.model_override??void 0,...o===void 0?{}:{scopes:o}},async c=>{const y=await W(c);Ue(await j(e),s,await j(c),y,yn)})}d(uo,"forkNode");export{ae as appPaidLaunch,de as assertLaunchModelRegistered,uo as forkNode,vn as invokeBirthLifecycleHooks,ie as resolveForkSource,kn as resolveProfileId,_n as resolveSpawner,fo as spawnChild,se as spawnChildPrepared};
@@ -28,4 +28,4 @@ export type StopAction = {
28
28
  /** Decide what to do when a node stops. crtrd supplies every current-canvas
29
29
  * fact; the broker contributes only whether its Pi-owned background job registry
30
30
  * is still running work. */
31
- export declare function evaluateStop(nodeId: string, signals: StopSignals, backgroundJobsRunning?: boolean): Promise<StopAction>;
31
+ export declare function evaluateStop(nodeId: string, signals: StopSignals): Promise<StopAction>;
@@ -1,8 +1,2 @@
1
- var g=Object.defineProperty;var a=(t,e)=>g(t,"name",{value:e,configurable:!0});import{hasActiveLiveSubscription as _,hasPendingCronWake as v,getNode as p}from"../canvas/index.js";import{hasLiveControllerWait as S,hasLiveObjectWait as y}from"../canvas/waits.js";import{contextDir as m}from"../canvas/node-agent-paths.js";import{activeBackgroundBashJobs as f}from"../bash-jobs.js";import{hasOpenReplyBearingRequestByRequester as O}from"../human/requests.js";import{formatCard as o,formatStructuredOutputReprompt as L,STALL_REPROMPT as A}from"../../shared/generated-context.js";import{readOutputRequest as d,readSchemaReprompts as N,writeSchemaReprompts as q}from"./structured-output.js";import{openDb as x}from"../canvas/db.js";const h=3;function w(t){return t.parent==null&&t.run_id===t.node_id&&t.metadata_json!=null}a(w,"isAppRunRoot");async function R(t){const e=N(t);return e.count===0?e:await(await x()).prepare(`SELECT 1 FROM deliveries d JOIN messages m ON m.message_id = d.message_id
2
- WHERE d.destination_id = ? AND d.wake = 1 AND m.kind IN ('message', 'completed') AND d.created_at > ? LIMIT 1`).get(t,e.at)!==void 0?{count:0,at:e.at}:e}a(R,"effectiveSchemaReprompts");async function E(t){const{count:e}=await R(t);return e>=h?!1:(q(t,{count:e+1,at:Date.now()}),!0)}a(E,"takeRunSchemaReprompt");async function H(t){return t.pi_pid!=null&&w(t)&&d(t.node_id).state==="valid"&&(await R(t.node_id)).count<h&&await s(t.node_id,f(await m(t.node_id)).length>0)===null}a(H,"runSchemaRepromptPending");import{STALL_REPROMPT as Y}from"../../shared/generated-context.js";function P(t,e){return o("stop-guard",{},L(JSON.stringify(e,null,2),t))}a(P,"formatValidStructuredOutputReprompt");function T(t){return o("stop-guard",{},`Structured-output request file is invalid and cannot be used: ${t}
3
-
4
- You have two options:
5
- 1. Remove the invalid file (the output-schema.json in your node directory has been corrupted)
6
- 2. Fix the corruption if you know the original request schema
7
-
8
- After resolving the file, call the \`submit_result\` tool again (with \`decline\` when the schema cannot be honestly satisfied). If this is unexpected, escalate to the user using \`crtr human send\`.`)}a(T,"formatInvalidStructuredOutputReprompt");async function s(t,e){return await v(t)?"scheduled":await _(t)||await S(t)||await y(t)||await O(t)||e?"awaiting":null}a(s,"wakeCapableWait");async function J(t,e,i){if(i??=f(await m(t)).length>0,e.pushedFinal)return{action:"allow",reason:"finished"};const n=d(t);if(n.state==="valid"){const l=await s(t,i);if(l!==null)return{action:"allow",reason:l};const c=await p(t);return c!==null&&w(c)&&!await E(t)?{action:"allow",reason:"dormant"}:{action:"reprompt",reason:"stalled",message:P(n.request.request_id,n.request.schema)}}if(n.state==="invalid")return{action:"reprompt",reason:"stalled",message:T(n.error)};const r=await p(t);if(r!==null&&(r.final_report!=null||r.status==="done"||r.status==="dead"||r.status==="canceled"))return{action:"allow",reason:"finished"};if(r!==null&&r.lifecycle==="resident")return{action:"allow",reason:"dormant"};const u=await s(t,i);return u!==null?{action:"allow",reason:u}:{action:"reprompt",reason:"stalled",message:o("stop-guard",{},A)}}a(J,"evaluateStop");export{h as RUN_SCHEMA_REPROMPT_LIMIT,Y as STALL_REPROMPT,J as evaluateStop,w as isAppRunRoot,H as runSchemaRepromptPending};
1
+ var g=Object.defineProperty;var e=(t,a)=>g(t,"name",{value:a,configurable:!0});import{hasActiveLiveSubscription as _,hasPendingCronWake as h,getNode as l}from"../canvas/index.js";import{hasLiveControllerWait as S,hasLiveObjectWait as O}from"../canvas/waits.js";import{runningJobs as L}from"../graph/jobs.js";import{hasOpenReplyBearingRequestByRequester as y}from"../human/requests.js";import{formatCard as p,formatStructuredOutputReprompt as N,STALL_REPROMPT as A}from"../../shared/generated-context.js";import{readOutputRequest as c,readSchemaReprompts as m,takeSchemaReprompt as E}from"./output-result.js";import{openDb as f}from"../canvas/db.js";const w=3;function d(t){return t.parent==null&&t.run_id===t.node_id&&t.metadata_json!=null}e(d,"isAppRunRoot");async function R(t){const a=await m(t);return a.count===0?a:await(await f()).prepare(`SELECT 1 FROM deliveries d JOIN messages m ON m.message_id = d.message_id
2
+ WHERE d.destination_id = ? AND d.wake = 1 AND m.kind IN ('message', 'completed') AND d.created_at > ? LIMIT 1`).get(t,a.at)!==void 0?{count:0,at:a.at}:a}e(R,"effectiveSchemaReprompts");async function P(t){const{count:a}=await R(t);return a>=w?!1:await E(t,(await m(t)).count,a+1,Date.now())}e(P,"takeRunSchemaReprompt");async function D(t){return t.pi_pid!=null&&d(t)&&await c(t.node_id)!==null&&(await R(t.node_id)).count<w&&await i(t.node_id)===null}e(D,"runSchemaRepromptPending");import{STALL_REPROMPT as F}from"../../shared/generated-context.js";function T(t,a){return p("stop-guard",{},N(JSON.stringify(a,null,2),t))}e(T,"formatValidStructuredOutputReprompt");async function i(t){return await h(t)?"scheduled":await _(t)||await S(t)||await O(t)||await y(t)||(await L(await f(),t)).length>0?"awaiting":null}e(i,"wakeCapableWait");async function J(t,a){if(a.pushedFinal)return{action:"allow",reason:"finished"};const r=await c(t);if(r!==null){const u=await i(t);if(u!==null)return{action:"allow",reason:u};const s=await l(t);return s!==null&&d(s)&&!await P(t)?{action:"allow",reason:"dormant"}:{action:"reprompt",reason:"stalled",message:T(r.request_id,r.schema)}}const n=await l(t);if(n!==null&&(n.final_report!=null||n.status==="done"||n.status==="dead"||n.status==="canceled"))return{action:"allow",reason:"finished"};if(n!==null&&n.lifecycle==="resident")return{action:"allow",reason:"dormant"};const o=await i(t);return o!==null?{action:"allow",reason:o}:{action:"reprompt",reason:"stalled",message:p("stop-guard",{},A)}}e(J,"evaluateStop");export{w as RUN_SCHEMA_REPROMPT_LIMIT,F as STALL_REPROMPT,J as evaluateStop,d as isAppRunRoot,D as runSchemaRepromptPending};
@@ -1,5 +1,4 @@
1
1
  import { outputSchemaRefProblem } from './output-schema-refs.js';
2
- import type { DeclinedResult } from '../canvas/types.js';
3
2
  /** The pi tool a node calls to answer its pending structured-output request
4
3
  * (registered by canvas-structured-output; `run.get` names it `submitting_result`). */
5
4
  export declare const SUBMIT_RESULT_TOOL = "submit_result";
@@ -11,16 +10,6 @@ export interface StructuredOutputRequest {
11
10
  /** The one-off request's message id; its answer ends the requester's message watch. */
12
11
  requestMessageId?: string;
13
12
  }
14
- /** Tri-state result of reading a structured-output request file. */
15
- export type StructuredOutputState = {
16
- state: 'absent';
17
- } | {
18
- state: 'valid';
19
- request: StructuredOutputRequest;
20
- } | {
21
- state: 'invalid';
22
- error: string;
23
- };
24
13
  /** The `--output-schema` transport clause, rendered verbatim by every leaf that
25
14
  * accepts one. Declared once so the call sites cannot drift apart. */
26
15
  export declare const OUTPUT_SCHEMA_TRANSPORT = "A .json file path, or inline JSON beginning with `{`.";
@@ -28,37 +17,7 @@ export declare const OUTPUT_SCHEMA_TRANSPORT = "A .json file path, or inline JSO
28
17
  * `crtr push result`; a mismatch rejects with the field errors and records
29
18
  * nothing, so an over-constrained schema costs the target retries. */
30
19
  export declare const OUTPUT_SCHEMA_CONSTRAINTS = "The full schema (including enum, pattern, and numeric bounds) is enforced when the target submits its result (its `submit_result` tool, or `crtr push result`); a mismatch rejects with the field errors and records nothing, so an over-constrained schema costs the target retries. A target that cannot honestly satisfy the schema declines (`submit_result` with `decline`, or `crtr push result --decline \"<reason>\" --code <token> [--retryable]`), which records a failure outcome with reason `declined` carrying the reason, code, and retryable flag instead of a value.";
31
- export declare function outputSchemaPath(nodeId: string): string;
32
- /** Broker-visible copy; the daemon validates only against outputSchemaPath. */
33
- export declare function brokerOutputSchemaPath(nodeId: string): string;
34
- export declare function shareRunFileWithBroker(nodeId: string, path: string): void;
35
- export declare function projectOutputSchema(nodeId: string): void;
36
- export declare function outputResultPath(nodeId: string, grantee?: string): string;
37
- /** The node's machine result, read beneath its agent folder; undefined when it wrote none. */
38
- export declare function readOutputResult(nodeId: string, grantee?: string): unknown;
39
- export declare function structuredRequestResultPath(nodeId: string, requestId: string, mode: StructuredOutputMode, grantee?: string): string;
40
- /** The marker a declined request leaves beside where `result.json` would have been. */
41
- export declare function outputDeclinedPath(nodeId: string, grantee?: string): string;
42
- export interface OutputDeclined extends DeclinedResult {
43
- mode: StructuredOutputMode;
44
- at: string;
45
- }
46
20
  export declare function parseOutputSchemaValue(value: string | undefined): Record<string, unknown> | null;
47
- /** The daemon is the only caller for a row-backed request sidecar. */
48
- export declare function writeStructuredRequestSidecar(row: {
49
- request_id: string;
50
- node_id: string | null;
51
- submission: StructuredOutputMode;
52
- schema: Record<string, unknown>;
53
- request_message_id?: string | null;
54
- }): string;
55
- /** Read a structured-output request with full validation and error reporting.
56
- * Returns a tri-state: absent (file doesn't exist), valid (parsed successfully),
57
- * or invalid (file exists but is malformed). */
58
- export declare function readOutputRequest(nodeId: string): StructuredOutputState;
59
- export declare function readBrokerOutputRequest(nodeId: string): StructuredOutputState;
60
- /** Reads the pre-request-id sidecar shape for daemon boot adoption only. */
61
- export declare function readLegacyOutputRequest(nodeId: string): Pick<StructuredOutputRequest, 'mode' | 'schema' | 'requestMessageId'> | null;
62
21
  /** Validate a submitted result value against a stored output schema, strictly. Returns
63
22
  * the value exactly as submitted, or throws an Error whose message lists the per-field
64
23
  * failures. Nothing is coerced: unlike a model's tool arguments, a final result is data
@@ -75,29 +34,3 @@ export { outputSchemaRefProblem };
75
34
  export declare function outputSchemaProblem(schema: Record<string, unknown>): Promise<string | null>;
76
35
  /** Throws the `bad_output_schema` input error when `outputSchemaProblem` finds one. */
77
36
  export declare function assertOutputSchemaAccepted(schema: Record<string, unknown>): Promise<void>;
78
- /** Persist a validated result atomically (temp-file-plus-rename), so a
79
- * concurrent reader (Core's result poll peeks this file) never sees a torn
80
- * write. Returns the result path. */
81
- export declare function writeOutputResult(nodeId: string, value: unknown, grantee?: string): string;
82
- /** Persist a decline atomically. `result.json` is left untouched: a one-off
83
- * decline after an earlier answered request must not erase that answer. */
84
- export declare function writeOutputDeclined(nodeId: string, declined: OutputDeclined, grantee?: string): string;
85
- /** The stop guard's count of consecutive schema reprompts of a run's root
86
- * (Silas, 2026-09-30): daemon-owned, beside the schema it counts against. */
87
- export declare function schemaRepromptsPath(nodeId: string): string;
88
- export interface SchemaReprompts {
89
- count: number;
90
- at: number;
91
- }
92
- export declare function readSchemaReprompts(nodeId: string): SchemaReprompts;
93
- export declare function writeSchemaReprompts(nodeId: string, value: SchemaReprompts): void;
94
- /** A `result.submit` resets the count. */
95
- export declare function clearSchemaReprompts(nodeId: string): void;
96
- export declare function removeOutputSchema(nodeId: string, requestId?: string): void;
97
- export interface StagedStructuredProjection {
98
- path: string;
99
- tmpPath: string;
100
- }
101
- /** Stage the authoritative value before its settlement commit; install is one rename. */
102
- export declare function stageStructuredResult(nodeId: string, requestId: string, mode: StructuredOutputMode, value: unknown, grantee?: string): StagedStructuredProjection;
103
- export declare function installStagedStructuredProjection(staged: StagedStructuredProjection): string;
@@ -1,8 +1,3 @@
1
- var j=Object.defineProperty;var o=(t,e)=>j(t,"name",{value:e,configurable:!0});import{existsSync as d,mkdirSync as f,readFileSync as a,unlinkSync as h,writeFileSync as S,renameSync as g}from"node:fs";import{dirname as b,resolve as T}from"node:path";import{randomUUID as x}from"node:crypto";import{nodeDir as R,nodeRunDir as O,contextDir as y,nodeAgentDir as $}from"../canvas/paths.js";import{readTextBeneathIfExists as E,unlinkBeneath as k,writeFileBeneath as q}from"../spaces/open-beneath.js";import{outputSchemaRefProblem as v}from"./output-schema-refs.js";import{InputError as l}from"../io.js";import{isRecord as c}from"../../shared/predicates.js";import{setModeBeneath as A}from"../spaces/open-beneath.js";import{LAUNCHER_SOCKET as B}from"../../launcher/spec.js";const et="submit_result",rt="A .json file path, or inline JSON beginning with `{`.",nt='The full schema (including enum, pattern, and numeric bounds) is enforced when the target submits its result (its `submit_result` tool, or `crtr push result`); a mismatch rejects with the field errors and records nothing, so an over-constrained schema costs the target retries. A target that cannot honestly satisfy the schema declines (`submit_result` with `decline`, or `crtr push result --decline "<reason>" --code <token> [--retryable]`), which records a failure outcome with reason `declined` carrying the reason, code, and retryable flag instead of a value.';function p(t){return`${R(t)}/output-schema.json`}o(p,"outputSchemaPath");function _(t){return`${O(t)}/output-schema.json`}o(_,"brokerOutputSchemaPath");function M(){const t=a("/etc/group","utf8").split(`
2
- `).find(r=>r.startsWith("crtr-data:")),e=Number(t?.split(":")[2]);if(!Number.isInteger(e))throw new Error("crtr-data group is required on sandboxed Linux");return e}o(M,"dataGroupId");function U(t,e){process.platform!=="linux"||!d(B)||A(O(t),e,432,{uid:process.getuid(),gid:M()})}o(U,"shareRunFileWithBroker");function C(t){const e=p(t),r=_(t);d(e)&&(q(O(t),r,a(e),{atomic:!0}),U(t,r))}o(C,"projectOutputSchema");function w(t,e){return`${y(t,e)}/result.json`}o(w,"outputResultPath");function ot(t,e){const r=E($(t,e),w(t,e));return r===null?void 0:JSON.parse(r)}o(ot,"readOutputResult");function D(t,e,r,n){return r==="terminal"?w(t,n):`${y(t,n)}/structured-requests/${e}/result.json`}o(D,"structuredRequestResultPath");function P(t,e){return`${y(t,e)}/declined.json`}o(P,"outputDeclinedPath");function st(t){const e=t?.trim();if(e===void 0||e==="")return null;let r,n;if(e.startsWith("{"))r=e,n="inline JSON";else{const u=T(e);n=u;try{r=a(u,"utf8")}catch(i){throw new l({error:"bad_output_schema",message:`could not read output schema from ${u}: ${i.message}`,field:"output-schema",next:"Pass a readable JSON Schema file path, or inline JSON beginning with `{`."})}}let s;try{s=JSON.parse(r)}catch(u){throw new l({error:"bad_output_schema",message:`output schema from ${n} is not valid JSON: ${u.message}`,field:"output-schema",next:"Pass valid JSON whose top-level value is an object."})}if(!c(s))throw new l({error:"bad_output_schema",message:`output schema from ${n} must be a JSON object`,field:"output-schema",next:"Pass a JSON Schema object, not an array, string, number, boolean, or null."});return s}o(st,"parseOutputSchemaValue");function ut(t){if(t.node_id===null)throw new Error(`cannot publish structured request ${t.request_id} before node binding`);const e=t.node_id,r=p(e);f(b(r),{recursive:!0});const n={request_id:t.request_id,mode:t.submission,schema:t.schema,...t.request_message_id==null?{}:{requestMessageId:t.request_message_id}},s=`${r}.${x()}.tmp`;return S(s,`${JSON.stringify(n,null,2)}
3
- `,"utf8"),g(s,r),C(e),r}o(ut,"writeStructuredRequestSidecar");function F(t){return J(p(t))}o(F,"readOutputRequest");function it(t){return J(_(t))}o(it,"readBrokerOutputRequest");function J(t){if(!d(t))return{state:"absent"};let e;try{e=a(t,"utf8")}catch(m){return{state:"invalid",error:`could not read request file: ${m.message}`}}let r;try{r=JSON.parse(e)}catch(m){return{state:"invalid",error:`request file is not valid JSON: ${m.message}`}}if(!c(r))return{state:"invalid",error:"request file top-level value must be an object"};const n=r.request_id,s=r.mode,u=r.schema;if(typeof n!="string"||n==="")return{state:"invalid",error:"request_id must be a non-empty string"};if(s!=="terminal"&&s!=="oneoff")return{state:"invalid",error:`mode must be 'terminal' or 'oneoff', got ${JSON.stringify(s)}`};if(!c(u))return{state:"invalid",error:`schema must be an object, got ${typeof u}`};const i=r.requestMessageId;return i!==void 0&&typeof i!="string"?{state:"invalid",error:`requestMessageId must be a string, got ${typeof i}`}:{state:"valid",request:{request_id:n,mode:s,schema:u,...i===void 0?{}:{requestMessageId:i}}}}o(J,"readOutputRequestAt");function at(t){try{const e=JSON.parse(a(p(t),"utf8"));if(!c(e)||Object.hasOwn(e,"request_id"))return null;const r=e.mode,n=e.schema,s=e.requestMessageId;return r!=="terminal"&&r!=="oneoff"||!c(n)?null:{mode:r,schema:n,...typeof s=="string"?{requestMessageId:s}:{}}}catch{return null}}o(at,"readLegacyOutputRequest");async function ct(t,e){const{Compile:r}=await import("typebox/compile"),n=r(t);if(n.Check(e))return e;const s=n.Errors(e).map(u=>` - ${(u.keyword==="required"?[...u.instancePath.split("/").filter(Boolean),String(u.params.requiredProperties?.[0]??"")].filter(Boolean).join("."):u.instancePath.split("/").filter(Boolean).join("."))||"root"}: ${u.message}`);throw new Error(`Validation failed:
4
- ${s.join(`
5
- `)||" - Unknown validation error"}`)}o(ct,"validateStructuredResult");async function L(t){const e=v(t);if(e!==null)return e;try{const{Compile:r}=await import("typebox/compile");r(t)}catch(r){return`the schema cannot be compiled: ${r.message}`}return null}o(L,"outputSchemaProblem");async function pt(t){const e=await L(t);if(e!==null)throw new l({error:"bad_output_schema",message:`output_schema is not usable: ${e}`,field:"output-schema",next:"Fix the schema (bundle referenced documents under $defs with their own $id) and send it again."})}o(pt,"assertOutputSchemaAccepted");function lt(t,e,r){const n=$(t,r),s=w(t,r);q(n,s,`${JSON.stringify(e,null,2)}
6
- `,{atomic:!0});try{k(n,P(t,r))}catch(u){if(u.code!=="ENOENT")throw u}return s}o(lt,"writeOutputResult");function mt(t,e,r){const n=P(t,r);return q($(t,r),n,`${JSON.stringify(e,null,2)}
7
- `,{atomic:!0}),n}o(mt,"writeOutputDeclined");function N(t){return`${R(t)}/output-schema-reprompts.json`}o(N,"schemaRepromptsPath");function dt(t){try{const e=JSON.parse(a(N(t),"utf8"));if(c(e)&&Number.isSafeInteger(e.count)&&Number.isFinite(e.at))return{count:e.count,at:e.at}}catch{}return{count:0,at:0}}o(dt,"readSchemaReprompts");function ft(t,e){const r=N(t);f(b(r),{recursive:!0});const n=`${r}.${x()}.tmp`;S(n,JSON.stringify(e),"utf8"),g(n,r)}o(ft,"writeSchemaReprompts");function I(t){try{h(N(t))}catch{}}o(I,"clearSchemaReprompts");function ht(t,e){const r=p(t);if(e!==void 0){const s=F(t);if(s.state!=="valid"||s.request.request_id!==e)return}try{h(r)}catch{}I(t);const n=_(t);try{h(n)}catch{}}o(ht,"removeOutputSchema");function St(t,e,r,n,s){const u=D(t,e,r,s);f(b(u),{recursive:!0});const i=`${u}.${x()}.tmp`;return S(i,`${JSON.stringify(n,null,2)}
8
- `,"utf8"),{path:u,tmpPath:i}}o(St,"stageStructuredResult");function gt(t){return g(t.tmpPath,t.path),t.path}o(gt,"installStagedStructuredProjection");export{nt as OUTPUT_SCHEMA_CONSTRAINTS,rt as OUTPUT_SCHEMA_TRANSPORT,et as SUBMIT_RESULT_TOOL,pt as assertOutputSchemaAccepted,_ as brokerOutputSchemaPath,I as clearSchemaReprompts,gt as installStagedStructuredProjection,P as outputDeclinedPath,w as outputResultPath,p as outputSchemaPath,L as outputSchemaProblem,v as outputSchemaRefProblem,st as parseOutputSchemaValue,C as projectOutputSchema,it as readBrokerOutputRequest,at as readLegacyOutputRequest,F as readOutputRequest,ot as readOutputResult,dt as readSchemaReprompts,ht as removeOutputSchema,N as schemaRepromptsPath,U as shareRunFileWithBroker,St as stageStructuredResult,D as structuredRequestResultPath,ct as validateStructuredResult,mt as writeOutputDeclined,lt as writeOutputResult,ft as writeSchemaReprompts,ut as writeStructuredRequestSidecar};
1
+ var l=Object.defineProperty;var s=(r,e)=>l(r,"name",{value:e,configurable:!0});import{resolve as m}from"node:path";import{readFileSync as h}from"node:fs";import{outputSchemaRefProblem as u}from"./output-schema-refs.js";import{InputError as i}from"../io.js";import{isRecord as d}from"../../shared/predicates.js";const O="submit_result",x="A .json file path, or inline JSON beginning with `{`.",y='The full schema (including enum, pattern, and numeric bounds) is enforced when the target submits its result (its `submit_result` tool, or `crtr push result`); a mismatch rejects with the field errors and records nothing, so an over-constrained schema costs the target retries. A target that cannot honestly satisfy the schema declines (`submit_result` with `decline`, or `crtr push result --decline "<reason>" --code <token> [--retryable]`), which records a failure outcome with reason `declined` carrying the reason, code, and retryable flag instead of a value.';function N(r){const e=r?.trim();if(e===void 0||e==="")return null;let o,n;if(e.startsWith("{"))o=e,n="inline JSON";else{const t=m(e);n=t;try{o=h(t,"utf8")}catch(c){throw new i({error:"bad_output_schema",message:`could not read output schema from ${t}: ${c.message}`,field:"output-schema",next:"Pass a readable JSON Schema file path, or inline JSON beginning with `{`."})}}let a;try{a=JSON.parse(o)}catch(t){throw new i({error:"bad_output_schema",message:`output schema from ${n} is not valid JSON: ${t.message}`,field:"output-schema",next:"Pass valid JSON whose top-level value is an object."})}if(!d(a))throw new i({error:"bad_output_schema",message:`output schema from ${n} must be a JSON object`,field:"output-schema",next:"Pass a JSON Schema object, not an array, string, number, boolean, or null."});return a}s(N,"parseOutputSchemaValue");async function T(r,e){const{Compile:o}=await import("typebox/compile"),n=o(r);if(n.Check(e))return e;const a=n.Errors(e).map(t=>` - ${(t.keyword==="required"?[...t.instancePath.split("/").filter(Boolean),String(t.params.requiredProperties?.[0]??"")].filter(Boolean).join("."):t.instancePath.split("/").filter(Boolean).join("."))||"root"}: ${t.message}`);throw new Error(`Validation failed:
2
+ ${a.join(`
3
+ `)||" - Unknown validation error"}`)}s(T,"validateStructuredResult");async function p(r){const e=u(r);if(e!==null)return e;try{const{Compile:o}=await import("typebox/compile");o(r)}catch(o){return`the schema cannot be compiled: ${o.message}`}return null}s(p,"outputSchemaProblem");async function $(r){const e=await p(r);if(e!==null)throw new i({error:"bad_output_schema",message:`output_schema is not usable: ${e}`,field:"output-schema",next:"Fix the schema (bundle referenced documents under $defs with their own $id) and send it again."})}s($,"assertOutputSchemaAccepted");export{y as OUTPUT_SCHEMA_CONSTRAINTS,x as OUTPUT_SCHEMA_TRANSPORT,O as SUBMIT_RESULT_TOOL,$ as assertOutputSchemaAccepted,p as outputSchemaProblem,u as outputSchemaRefProblem,N as parseOutputSchemaValue,T as validateStructuredResult};
@@ -5,6 +5,7 @@ declare function tmux(args: string[]): {
5
5
  ok: boolean;
6
6
  stdout: string;
7
7
  stderr: string;
8
+ timedOut: boolean;
8
9
  };
9
10
  export declare function inTmux(): boolean;
10
11
  /** Is any tmux SESSION currently up? `tmux list-sessions` exits 0 iff a server
@@ -160,6 +161,13 @@ export declare function windowIndex(target: string): number | null;
160
161
  * liveness. We therefore require the echoed `#{pane_id}` to equal the requested
161
162
  * pane: a live pane echoes its own id, a gone/bogus one yields empty. */
162
163
  export declare function paneExists(pane: string): boolean;
164
+ /** What a liveness probe of a pane learned. `unknown` means the probe timed out: tmux did not answer, which says nothing
165
+ * about the pane. A caller that deletes state on `gone` must keep it on `unknown`. */
166
+ export type PaneState = 'live' | 'gone' | 'unknown';
167
+ /** {@link paneExists} that tells a timed-out probe apart from a pane that is gone. */
168
+ export declare function paneState(pane: string): PaneState;
169
+ /** {@link paneState} without blocking the event loop, bounded by the same timeout. */
170
+ export declare function paneStateAsync(pane: string, timeoutMs?: number): Promise<PaneState>;
163
171
  /** Does this pane exist AND have its command still RUNNING (`#{pane_dead}` = 0)?
164
172
  * Distinguishes a pane genuinely hosting a live process from a remain-on-exit
165
173
  * corpse frozen after exit (`pane_dead` = 1). Node viewer panes run `crtr surface attach`
@@ -1,6 +1,6 @@
1
- var O=Object.defineProperty;var r=(n,t)=>O(n,"name",{value:t,configurable:!0});import{execFile as w,spawnSync as d}from"node:child_process";import{encodeAttachControlInput as C}from"../keybindings/index.js";import{listProcessTable as E}from"../canvas/pid.js";import{bundledPiCommandForShell as $}from"./pi-cli.js";import{shellQuote as l}from"../../shared/shell-quote.js";import{envPiBinaryOverride as N}from"../../shared/env.js";function o(n){const t=d("tmux",n,{encoding:"utf8"});return{ok:t.status===0,stdout:(t.stdout??"").trim(),stderr:(t.stderr??"").trim()}}r(o,"tmux");function p(n,t){return o(n===void 0||n===""?t:["-S",n,...t])}r(p,"tmuxOnSocket");function M(){return process.env.TMUX!==void 0&&process.env.TMUX!==""}r(M,"inTmux");function Y(){return d("tmux",["list-sessions"],{encoding:"utf8",stdio:"ignore"}).status===0}r(Y,"tmuxSessionsReachable");function Z(){return d("tmux",["list-clients","-F","#{client_name}"],{encoding:"utf8"}).status===0}r(Z,"tmuxClientsReachable");function nn(n){if(n==="")return null;const t=o(["list-panes","-a","-F","#{pane_id} #{@crtr_node}"]);if(!t.ok)return null;for(const e of t.stdout.split(`
2
- `)){const s=e.indexOf(" ");if(!(s<0)&&e.slice(s+1)===n){const u=e.slice(0,s);if(u!=="")return u}}return null}r(nn,"paneOfNode");function T(){if(!M())return null;const n=o(["display-message","-p","#{session_name} #{window_id} #{pane_id}"]);if(!n.ok)return null;const[t,e,s]=n.stdout.split(" ");return{session:t,window:e,pane:s}}r(T,"currentTmux");function tn(){const n=d("tmux",["-V"],{stdio:"ignore"});return n.error===void 0&&n.status===0}r(tn,"tmuxAvailable");function en(n){return d("tmux",n,{stdio:"inherit"}).status??1}r(en,"tmuxInteractive");function F(n){return o(["has-session","-t",n]).ok}r(F,"sessionExists");function A(){const n=o(["show-options","-s","terminal-overrides"]).stdout;/Enbp=\\+E/.test(n)||o(["set-option","-sga","terminal-overrides","*:Enbp=\\E[?2004h:Dsbp=\\E[?2004l"])}r(A,"ensureBracketedPaste");function R(){A(),o(["set-option","-s","focus-events","on"])}r(R,"ensureServerOptions");function rn(n,t){F(n)||o(["new-session","-d","-s",n,"-c",t]),R()}r(rn,"ensureSession");function x(n){const t=[];for(const[e,s]of Object.entries(n))t.push("-e",`${e}=${s}`);return t}r(x,"envFlags");function on(n){const t=o(["new-window","-d","-a","-P","-F","#{window_id} #{pane_id}","-t",`${n.session}:`,"-n",n.name,"-c",n.cwd,...x(n.env),n.command]);if(!t.ok)return null;const[e,s]=t.stdout.split(" ");return e===void 0||e===""||s===void 0||s===""?null:{window:e,pane:s}}r(on,"openNodeWindow");function sn(n,t){const e=o(["split-window","-d",...t.vertical===!0?[]:["-h"],...t.before===!0?["-b"]:[],...t.size!==void 0?["-l",String(t.size)]:[],"-P","-F","#{pane_id}","-t",n,"-c",t.cwd,...x(t.env),t.command]);return e.ok&&e.stdout!==""?e.stdout:null}r(sn,"splitWindow");function un(n,t){return!(T()?.session===n)&&!o(["switch-client","-t",n]).ok?!1:o(["select-window","-t",t]).ok}r(un,"focusWindow");function an(n){return o(["kill-window","-t",n]).ok}r(an,"closeWindow");function cn(n,t){return o(["rename-window","-t",n,t]).ok}r(cn,"renameWindow");function dn(n){const t=o(["break-pane","-d","-P","-F","#{window_id} #{pane_id}","-s",n]);if(!t.ok)return null;const[e,s]=t.stdout.split(" ");return e===void 0||e===""||s===void 0||s===""?null:{window:e,pane:s}}r(dn,"breakPane");function pn(n){return o(["kill-pane","-t",n]).ok}r(pn,"closePane");function ln(n,t,e){return o(h(n,t,e)).ok}r(ln,"displayPopup");function fn(n,t,e){return new Promise(s=>{try{w("tmux",h(n,t,e),i=>s(i===null)).stdin?.end()}catch{s(!1)}})}r(fn,"displayPopupAsync");function h(n,t,e){return["display-popup","-E","-t",n,"-d",t,"-w","90%","-h","90%",e]}r(h,"displayPopupArgs");function mn(n,t){const e=o(["display-message","-p","-t",`${n}:${t}`,"#{pane_id}"]);return e.ok&&e.stdout!==""?e.stdout:null}r(mn,"paneOfWindow");function wn(n){const t=o(["display-message","-p","-t",n,"#{window_id}"]);return t.ok&&t.stdout!==""?t.stdout:null}r(wn,"windowOfPane");function xn(n){const t=o(["display-message","-p","-t",n,"#{session_name} #{window_id}"]);if(!t.ok)return null;const e=/^(.*) (@\d+)$/.exec(t.stdout);return e===null||e[1]===""?null:{session:e[1],window:e[2]}}r(xn,"paneLocation");function kn(n){const t=o(["display-message","-p","-t",n,"#{window_index}"]);return!t.ok||!/^\d+$/.test(t.stdout)?null:Number.parseInt(t.stdout,10)}r(kn,"windowIndex");function gn(n){const t=o(["display-message","-p","-t",n,"#{pane_id}"]);return t.ok&&t.stdout===n}r(gn,"paneExists");function hn(n){const t=o(["display-message","-p","-t",n,"#{pane_id} #{pane_dead}"]);return t.ok&&t.stdout===`${n} 0`}r(hn,"paneRunning");function _n(){const n=o(["list-panes","-a","-F","#{pane_id}"]);return n.ok?new Set(n.stdout.split(`
3
- `).filter(t=>t!=="")):null}r(_n,"listLivePanes");const V=2e3;async function Pn(){const n=await new Promise(t=>{try{w("tmux",["list-panes","-a","-F","#{pane_id}"],{encoding:"utf8",timeout:V,maxBuffer:4194304},(e,s)=>t(e?null:s))}catch{t(null)}});return n===null?null:new Set(n.trim().split(`
4
- `).filter(t=>t!==""))}r(Pn,"listLivePanesAsync");function yn(n){const t=o(["display-message","-p","-t",n,"#{pane_current_path}"]);return t.ok&&t.stdout!==""?t.stdout:null}r(yn,"paneCurrentPath");function bn(n){const t=o(["display-message","-p","-t",n,"#{pane_width} #{pane_height}"]);if(!t.ok)return null;const[e,s]=t.stdout.split(" "),u=Number.parseInt(e,10),i=Number.parseInt(s,10);return Number.isInteger(u)&&u>0&&Number.isInteger(i)&&i>0?{cols:u,rows:i}:null}r(bn,"paneSize");function vn(n,t,e=4e3){const s=r(u=>{const i=["display-message",...u?["-C"]:[],"-d",String(e)];return t!==void 0&&t!==""&&i.push("-t",t),i.push(n),i},"args");return o(s(!0)).ok||o(s(!1)).ok}r(vn,"displayMessage");function Sn(n,t,e){return o(["set-option","-p","-t",n,t,e]).ok}r(Sn,"setPaneOption");function In(n,t){const e=o(["show-options","-p","-t",n,"-q","-v",t]);return e.ok?e.stdout:void 0}r(In,"getPaneOption");const W="@crtr_viewer_at";let _=0,P=Promise.resolve();function On(n){if(n==="")return;const t=Math.max(Date.now(),_+1);_=t,P=P.then(()=>new Promise(e=>{try{w("tmux",["set-option","-p","-t",n,W,String(t)],()=>e())}catch{e()}}))}r(On,"stampViewerPaneAsync");function B(n){return n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}r(B,"escapeRegex");function k(n,t){const e=n.replace(/^"|"$/g,"");return new RegExp(`(?:^|\\s)surface\\s+attach\\s+to\\s+${B(t)}(?:\\s|$)`).test(e)}r(k,"looksLikeViewerCommand");function L(){const n=E();if(n===null)return null;const t=new Map,e=new Map;for(const{pid:s,ppid:u,command:i}of n){e.set(s,i);const a=t.get(u)??[];a.push(s),t.set(u,a)}return{childrenOf:t,commandOf:e}}r(L,"readProcessTree");function j(n,t,e){const s=[t];for(;s.length>0;){const u=s.pop();if(k(n.commandOf.get(u)??"",e))return!0;const i=n.childrenOf.get(u);i!==void 0&&s.push(...i)}return!1}r(j,"processTreeHasViewer");function Cn(n){const t=p(n,["list-panes","-a","-F","#{pane_id} #{session_name} #{@crtr_node} #{@crtr_viewer_at}"]);if(!t.ok||t.stdout==="")return[];const e=[];let s;for(const u of t.stdout.split(`
5
- `)){const[i,a,c,b]=u.split(" ");if(i===void 0||i===""||a===void 0||a===""||c===void 0||c==="")continue;const g=p(n,["display-message","-p","-t",i,"#{pane_current_command} #{pane_start_command} #{pane_pid}"]);if(!g.ok)continue;const[v="",S="",I]=g.stdout.split(" ");if(!(k(v,c)||k(S,c))){s??=L();const m=Number.parseInt(I,10);if(s===null||!Number.isInteger(m)||m<=0||!j(s,m,c))continue}const f=Number.parseInt(b??"",10);e.push({pane:i,session:a,nodeId:c,stampMs:Number.isSafeInteger(f)&&f>=0?f:0})}return e}r(Cn,"liveViewerPanes");function En(n,t,e){return p(n,["send-keys","-l","-t",t,C(e)]).ok}r(En,"sendAttachControl");function $n(n,t,e){const s=r(u=>{const i=["display-message",...u?["-C"]:[]];return t!==void 0&&t!==""&&i.push("-c",t),i.push(e),i},"args");return p(n,s(!0)).ok||p(n,s(!1)).ok}r($n,"displayClientMessage");function y(n){return["respawn-pane","-k","-c",n.cwd,...x(n.env),"-t",n.pane,n.command]}r(y,"respawnPaneArgs");function Nn(n){return o(y(n)).ok}r(Nn,"respawnPaneSync");function Mn(n){return z(`tmux ${y(n).map(l).join(" ")} >/dev/null 2>&1`)}r(Mn,"respawnPaneInBackground");function z(n){return o(["run-shell","-b",n]).ok}r(z,"runShellInBackground");function Tn(n){const t=o(["display-message","-p","-t",n,"#{pane_start_command}"]);return t.ok?t.stdout:void 0}r(Tn,"paneStartCommand");function Fn(n,t){const e=o(["swap-pane","-s",n,"-t",t]);return e.ok?null:e.stderr===""?"tmux swap-pane failed":e.stderr}r(Fn,"swapPanes");function An(n){const t=o(["display-message","-p","-t",n,"#{pane_current_command}"]);return t.ok&&t.stdout!==""?t.stdout:void 0}r(An,"paneCurrentCommand");function Rn(n){const t=o(["display-message","-p","-t",n,"#{pane_pid}"]);if(!t.ok)return;const e=Number.parseInt(t.stdout,10);return Number.isInteger(e)&&e>0?e:void 0}r(Rn,"panePid");function Vn(n){return o(["respawn-pane","-k","-t",n]).ok}r(Vn,"respawnPaneInPlace");function Wn(n,t=N()??$(l)){return[t,...n.map(l)].join(" ")}r(Wn,"piCommand");function U(n){const t=o(["list-windows","-t",n,"-F","#{window_id}"]);return!t.ok||t.stdout===""?[]:t.stdout.split(`
6
- `).filter(e=>e!=="")}r(U,"listWindowIds");function Bn(n,t){return n==null||t==null?!1:U(n).includes(t)}r(Bn,"windowAlive");function Ln(n,t){return o(["select-window","-t",`${n}:${t}`]).ok}r(Ln,"selectWindow");function jn(n,t){return o(["select-layout","-t",n,t]).ok}r(jn,"selectLayout");function zn(n){return o(["select-pane","-t",n]).ok}r(zn,"selectPane");function Un(n){return o(["switch-client","-t",n]).ok}r(Un,"switchClient");function qn(n,t){return o(["send-keys","-t",n,t,"Enter"]).ok}r(qn,"sendKeysEnter");export{W as VIEWER_STAMP_OPTION,dn as breakPane,pn as closePane,an as closeWindow,T as currentTmux,$n as displayClientMessage,vn as displayMessage,ln as displayPopup,fn as displayPopupAsync,rn as ensureSession,un as focusWindow,In as getPaneOption,M as inTmux,_n as listLivePanes,Pn as listLivePanesAsync,U as listWindowIds,Cn as liveViewerPanes,on as openNodeWindow,An as paneCurrentCommand,yn as paneCurrentPath,gn as paneExists,xn as paneLocation,nn as paneOfNode,mn as paneOfWindow,Rn as panePid,hn as paneRunning,bn as paneSize,Tn as paneStartCommand,Wn as piCommand,cn as renameWindow,Mn as respawnPaneInBackground,Vn as respawnPaneInPlace,Nn as respawnPaneSync,z as runShellInBackground,o as runTmux,jn as selectLayout,zn as selectPane,Ln as selectWindow,En as sendAttachControl,qn as sendKeysEnter,F as sessionExists,Sn as setPaneOption,l as shellQuote,sn as splitWindow,On as stampViewerPaneAsync,Fn as swapPanes,Un as switchClient,tn as tmuxAvailable,Z as tmuxClientsReachable,en as tmuxInteractive,Y as tmuxSessionsReachable,Bn as windowAlive,kn as windowIndex,wn as windowOfPane};
1
+ var T=Object.defineProperty;var r=(n,t)=>T(n,"name",{value:t,configurable:!0});import{execFile as f,spawnSync as d}from"node:child_process";import{encodeAttachControlInput as M}from"../keybindings/index.js";import{listProcessTable as C}from"../canvas/pid.js";import{bundledPiCommandForShell as $}from"./pi-cli.js";import{shellQuote as m}from"../../shared/shell-quote.js";import{envPiBinaryOverride as L}from"../../shared/env.js";const p=5e3;function o(n){const t=d("tmux",n,{encoding:"utf8",timeout:p,killSignal:"SIGKILL"});return{timedOut:t.error?.code==="ETIMEDOUT",ok:t.status===0,stdout:(t.stdout??"").trim(),stderr:(t.stderr??"").trim()}}r(o,"tmux");function l(n,t){return o(n===void 0||n===""?t:["-S",n,...t])}r(l,"tmuxOnSocket");function N(){return process.env.TMUX!==void 0&&process.env.TMUX!==""}r(N,"inTmux");function tn(){return d("tmux",["list-sessions"],{encoding:"utf8",stdio:"ignore",timeout:p,killSignal:"SIGKILL"}).status===0}r(tn,"tmuxSessionsReachable");function en(){return d("tmux",["list-clients","-F","#{client_name}"],{encoding:"utf8",timeout:p,killSignal:"SIGKILL"}).status===0}r(en,"tmuxClientsReachable");function rn(n){if(n==="")return null;const t=o(["list-panes","-a","-F","#{pane_id} #{@crtr_node}"]);if(!t.ok)return null;for(const e of t.stdout.split(`
2
+ `)){const s=e.indexOf(" ");if(!(s<0)&&e.slice(s+1)===n){const u=e.slice(0,s);if(u!=="")return u}}return null}r(rn,"paneOfNode");function F(){if(!N())return null;const n=o(["display-message","-p","#{session_name} #{window_id} #{pane_id}"]);if(!n.ok)return null;const[t,e,s]=n.stdout.split(" ");return{session:t,window:e,pane:s}}r(F,"currentTmux");function on(){const n=d("tmux",["-V"],{stdio:"ignore",timeout:p,killSignal:"SIGKILL"});return n.error===void 0&&n.status===0}r(on,"tmuxAvailable");function sn(n){return d("tmux",n,{stdio:"inherit"}).status??1}r(sn,"tmuxInteractive");function A(n){return o(["has-session","-t",n]).ok}r(A,"sessionExists");function R(){const n=o(["show-options","-s","terminal-overrides"]).stdout;/Enbp=\\+E/.test(n)||o(["set-option","-sga","terminal-overrides","*:Enbp=\\E[?2004h:Dsbp=\\E[?2004l"])}r(R,"ensureBracketedPaste");function V(){R(),o(["set-option","-s","focus-events","on"])}r(V,"ensureServerOptions");function un(n,t){A(n)||o(["new-session","-d","-s",n,"-c",t]),V()}r(un,"ensureSession");function k(n){const t=[];for(const[e,s]of Object.entries(n))t.push("-e",`${e}=${s}`);return t}r(k,"envFlags");function an(n){const t=o(["new-window","-d","-a","-P","-F","#{window_id} #{pane_id}","-t",`${n.session}:`,"-n",n.name,"-c",n.cwd,...k(n.env),n.command]);if(!t.ok)return null;const[e,s]=t.stdout.split(" ");return e===void 0||e===""||s===void 0||s===""?null:{window:e,pane:s}}r(an,"openNodeWindow");function cn(n,t){const e=o(["split-window","-d",...t.vertical===!0?[]:["-h"],...t.before===!0?["-b"]:[],...t.size!==void 0?["-l",String(t.size)]:[],"-P","-F","#{pane_id}","-t",n,"-c",t.cwd,...k(t.env),t.command]);return e.ok&&e.stdout!==""?e.stdout:null}r(cn,"splitWindow");function dn(n,t){return!(F()?.session===n)&&!o(["switch-client","-t",n]).ok?!1:o(["select-window","-t",t]).ok}r(dn,"focusWindow");function pn(n){return o(["kill-window","-t",n]).ok}r(pn,"closeWindow");function ln(n,t){return o(["rename-window","-t",n,t]).ok}r(ln,"renameWindow");function fn(n){const t=o(["break-pane","-d","-P","-F","#{window_id} #{pane_id}","-s",n]);if(!t.ok)return null;const[e,s]=t.stdout.split(" ");return e===void 0||e===""||s===void 0||s===""?null:{window:e,pane:s}}r(fn,"breakPane");function mn(n){return o(["kill-pane","-t",n]).ok}r(mn,"closePane");function wn(n,t,e){return o(h(n,t,e)).ok}r(wn,"displayPopup");function xn(n,t,e){return new Promise(s=>{try{f("tmux",h(n,t,e),i=>s(i===null)).stdin?.end()}catch{s(!1)}})}r(xn,"displayPopupAsync");function h(n,t,e){return["display-popup","-E","-t",n,"-d",t,"-w","90%","-h","90%",e]}r(h,"displayPopupArgs");function kn(n,t){const e=o(["display-message","-p","-t",`${n}:${t}`,"#{pane_id}"]);return e.ok&&e.stdout!==""?e.stdout:null}r(kn,"paneOfWindow");function gn(n){const t=o(["display-message","-p","-t",n,"#{window_id}"]);return t.ok&&t.stdout!==""?t.stdout:null}r(gn,"windowOfPane");function _n(n){const t=o(["display-message","-p","-t",n,"#{session_name} #{window_id}"]);if(!t.ok)return null;const e=/^(.*) (@\d+)$/.exec(t.stdout);return e===null||e[1]===""?null:{session:e[1],window:e[2]}}r(_n,"paneLocation");function hn(n){const t=o(["display-message","-p","-t",n,"#{window_index}"]);return!t.ok||!/^\d+$/.test(t.stdout)?null:Number.parseInt(t.stdout,10)}r(hn,"windowIndex");function yn(n){return W(n)==="live"}r(yn,"paneExists");function y(n,t){return t.timedOut?"unknown":t.ok&&t.stdout===n?"live":"gone"}r(y,"paneStateFrom");function W(n){return y(n,o(["display-message","-p","-t",n,"#{pane_id}"]))}r(W,"paneState");async function Pn(n,t=p){return await new Promise(e=>{try{f("tmux",["display-message","-p","-t",n,"#{pane_id}"],{encoding:"utf8",timeout:t,killSignal:"SIGKILL"},(s,u)=>{const i=s!==null&&s.killed===!0;e(y(n,{ok:s===null,stdout:String(u).trim(),timedOut:i}))})}catch{e("gone")}})}r(Pn,"paneStateAsync");function Sn(n){const t=o(["display-message","-p","-t",n,"#{pane_id} #{pane_dead}"]);return t.ok&&t.stdout===`${n} 0`}r(Sn,"paneRunning");function In(){const n=o(["list-panes","-a","-F","#{pane_id}"]);return n.ok?new Set(n.stdout.split(`
3
+ `).filter(t=>t!=="")):null}r(In,"listLivePanes");const B=2e3;async function bn(){const n=await new Promise(t=>{try{f("tmux",["list-panes","-a","-F","#{pane_id}"],{encoding:"utf8",timeout:B,maxBuffer:4194304},(e,s)=>t(e?null:s))}catch{t(null)}});return n===null?null:new Set(n.trim().split(`
4
+ `).filter(t=>t!==""))}r(bn,"listLivePanesAsync");function vn(n){const t=o(["display-message","-p","-t",n,"#{pane_current_path}"]);return t.ok&&t.stdout!==""?t.stdout:null}r(vn,"paneCurrentPath");function On(n){const t=o(["display-message","-p","-t",n,"#{pane_width} #{pane_height}"]);if(!t.ok)return null;const[e,s]=t.stdout.split(" "),u=Number.parseInt(e,10),i=Number.parseInt(s,10);return Number.isInteger(u)&&u>0&&Number.isInteger(i)&&i>0?{cols:u,rows:i}:null}r(On,"paneSize");function En(n,t,e=4e3){const s=r(u=>{const i=["display-message",...u?["-C"]:[],"-d",String(e)];return t!==void 0&&t!==""&&i.push("-t",t),i.push(n),i},"args");return o(s(!0)).ok||o(s(!1)).ok}r(En,"displayMessage");function Tn(n,t,e){return o(["set-option","-p","-t",n,t,e]).ok}r(Tn,"setPaneOption");function Mn(n,t){const e=o(["show-options","-p","-t",n,"-q","-v",t]);return e.ok?e.stdout:void 0}r(Mn,"getPaneOption");const K="@crtr_viewer_at";let P=0,S=Promise.resolve();function Cn(n){if(n==="")return;const t=Math.max(Date.now(),P+1);P=t,S=S.then(()=>new Promise(e=>{try{f("tmux",["set-option","-p","-t",n,K,String(t)],()=>e())}catch{e()}}))}r(Cn,"stampViewerPaneAsync");function U(n){return n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}r(U,"escapeRegex");function g(n,t){const e=n.replace(/^"|"$/g,"");return new RegExp(`(?:^|\\s)surface\\s+attach\\s+to\\s+${U(t)}(?:\\s|$)`).test(e)}r(g,"looksLikeViewerCommand");function G(){const n=C();if(n===null)return null;const t=new Map,e=new Map;for(const{pid:s,ppid:u,command:i}of n){e.set(s,i);const a=t.get(u)??[];a.push(s),t.set(u,a)}return{childrenOf:t,commandOf:e}}r(G,"readProcessTree");function j(n,t,e){const s=[t];for(;s.length>0;){const u=s.pop();if(g(n.commandOf.get(u)??"",e))return!0;const i=n.childrenOf.get(u);i!==void 0&&s.push(...i)}return!1}r(j,"processTreeHasViewer");function $n(n){const t=l(n,["list-panes","-a","-F","#{pane_id} #{session_name} #{@crtr_node} #{@crtr_viewer_at}"]);if(!t.ok||t.stdout==="")return[];const e=[];let s;for(const u of t.stdout.split(`
5
+ `)){const[i,a,c,b]=u.split(" ");if(i===void 0||i===""||a===void 0||a===""||c===void 0||c==="")continue;const _=l(n,["display-message","-p","-t",i,"#{pane_current_command} #{pane_start_command} #{pane_pid}"]);if(!_.ok)continue;const[v="",O="",E]=_.stdout.split(" ");if(!(g(v,c)||g(O,c))){s??=G();const x=Number.parseInt(E,10);if(s===null||!Number.isInteger(x)||x<=0||!j(s,x,c))continue}const w=Number.parseInt(b??"",10);e.push({pane:i,session:a,nodeId:c,stampMs:Number.isSafeInteger(w)&&w>=0?w:0})}return e}r($n,"liveViewerPanes");function Ln(n,t,e){return l(n,["send-keys","-l","-t",t,M(e)]).ok}r(Ln,"sendAttachControl");function Nn(n,t,e){const s=r(u=>{const i=["display-message",...u?["-C"]:[]];return t!==void 0&&t!==""&&i.push("-c",t),i.push(e),i},"args");return l(n,s(!0)).ok||l(n,s(!1)).ok}r(Nn,"displayClientMessage");function I(n){return["respawn-pane","-k","-c",n.cwd,...k(n.env),"-t",n.pane,n.command]}r(I,"respawnPaneArgs");function Fn(n){return o(I(n)).ok}r(Fn,"respawnPaneSync");function An(n){return z(`tmux ${I(n).map(m).join(" ")} >/dev/null 2>&1`)}r(An,"respawnPaneInBackground");function z(n){return o(["run-shell","-b",n]).ok}r(z,"runShellInBackground");function Rn(n){const t=o(["display-message","-p","-t",n,"#{pane_start_command}"]);return t.ok?t.stdout:void 0}r(Rn,"paneStartCommand");function Vn(n,t){const e=o(["swap-pane","-s",n,"-t",t]);return e.ok?null:e.stderr===""?"tmux swap-pane failed":e.stderr}r(Vn,"swapPanes");function Wn(n){const t=o(["display-message","-p","-t",n,"#{pane_current_command}"]);return t.ok&&t.stdout!==""?t.stdout:void 0}r(Wn,"paneCurrentCommand");function Bn(n){const t=o(["display-message","-p","-t",n,"#{pane_pid}"]);if(!t.ok)return;const e=Number.parseInt(t.stdout,10);return Number.isInteger(e)&&e>0?e:void 0}r(Bn,"panePid");function Kn(n){return o(["respawn-pane","-k","-t",n]).ok}r(Kn,"respawnPaneInPlace");function Un(n,t=L()??$(m)){return[t,...n.map(m)].join(" ")}r(Un,"piCommand");function D(n){const t=o(["list-windows","-t",n,"-F","#{window_id}"]);return!t.ok||t.stdout===""?[]:t.stdout.split(`
6
+ `).filter(e=>e!=="")}r(D,"listWindowIds");function Gn(n,t){return n==null||t==null?!1:D(n).includes(t)}r(Gn,"windowAlive");function jn(n,t){return o(["select-window","-t",`${n}:${t}`]).ok}r(jn,"selectWindow");function zn(n,t){return o(["select-layout","-t",n,t]).ok}r(zn,"selectLayout");function Dn(n){return o(["select-pane","-t",n]).ok}r(Dn,"selectPane");function Xn(n){return o(["switch-client","-t",n]).ok}r(Xn,"switchClient");function qn(n,t){return o(["send-keys","-t",n,t,"Enter"]).ok}r(qn,"sendKeysEnter");export{K as VIEWER_STAMP_OPTION,fn as breakPane,mn as closePane,pn as closeWindow,F as currentTmux,Nn as displayClientMessage,En as displayMessage,wn as displayPopup,xn as displayPopupAsync,un as ensureSession,dn as focusWindow,Mn as getPaneOption,N as inTmux,In as listLivePanes,bn as listLivePanesAsync,D as listWindowIds,$n as liveViewerPanes,an as openNodeWindow,Wn as paneCurrentCommand,vn as paneCurrentPath,yn as paneExists,_n as paneLocation,rn as paneOfNode,kn as paneOfWindow,Bn as panePid,Sn as paneRunning,On as paneSize,Rn as paneStartCommand,W as paneState,Pn as paneStateAsync,Un as piCommand,ln as renameWindow,An as respawnPaneInBackground,Kn as respawnPaneInPlace,Fn as respawnPaneSync,z as runShellInBackground,o as runTmux,zn as selectLayout,Dn as selectPane,jn as selectWindow,Ln as sendAttachControl,qn as sendKeysEnter,A as sessionExists,Tn as setPaneOption,m as shellQuote,cn as splitWindow,Cn as stampViewerPaneAsync,Vn as swapPanes,Xn as switchClient,on as tmuxAvailable,en as tmuxClientsReachable,sn as tmuxInteractive,tn as tmuxSessionsReachable,Gn as windowAlive,hn as windowIndex,gn as windowOfPane};
@@ -18,3 +18,23 @@ export declare function waitForBrokerViewSocket(nodeId: string, exited?: Promise
18
18
  code: number | null;
19
19
  signal: NodeJS.Signals | null;
20
20
  }>, waitMs?: number): Promise<boolean>;
21
+ /** The port a sandboxed broker serves `/view` on (127.0.0.1 only; the private preview forwards it). */
22
+ export declare const BROKER_VIEW_PORT = 4180;
23
+ /** The relay's end of one broker view connection: a view.sock {@link Socket}, or {@link connectWssView}'s link. Bytes in
24
+ * both directions are newline-terminated frames; `close` carries whether an error preceded it. */
25
+ export interface BrokerViewLink {
26
+ readonly destroyed: boolean;
27
+ write(line: string): unknown;
28
+ destroy(): unknown;
29
+ on(event: 'connect', listener: () => void): this;
30
+ on(event: 'data', listener: (chunk: Buffer) => void): this;
31
+ on(event: 'error', listener: (error: NodeJS.ErrnoException) => void): this;
32
+ on(event: 'close', listener: (hadError: boolean) => void): this;
33
+ }
34
+ /** A broker's `/view` WebSocket as a {@link BrokerViewLink}. Each broker message is one frame, delivered as one
35
+ * newline-terminated chunk; each line written is sent as one text message. The headers (the preview token) are
36
+ * sent on the handshake only and kept nowhere else. */
37
+ export declare function connectWssView(url: string, headers: Record<string, string>): BrokerViewLink;
38
+ /** Resolve true once the broker's `/view` WebSocket accepts a handshake within `waitMs`, retrying while it refuses;
39
+ * false on the deadline or when the broker's launch handle exits. */
40
+ export declare function waitForWssView(url: string, headers: Record<string, string>, exited?: Promise<unknown>, waitMs?: number): Promise<boolean>;
@@ -1 +1,3 @@
1
- var w=Object.defineProperty;var a=(t,e)=>w(t,"name",{value:e,configurable:!0});import{createConnection as p,Socket as S}from"node:net";import{nodeRunDir as _,viewSocketPath as h}from"../canvas/paths.js";import{isBeneathRefusal as x,socketBeneath as E}from"../spaces/open-beneath.js";const u=3e4,l=100,B=u;function m(t){return new Promise(e=>{setTimeout(e,t)})}a(m,"sleep");function d(t){let e;try{e=E(_(t),h(t))}catch(c){const n=new S;return process.nextTick(()=>n.destroy(c)),n}const i=p(e.path);return i.once("connect",e.release),i.once("close",e.release),i}a(d,"connectViewSocket");function O(t,e){return new Promise((i,c)=>{let n=!1,r=null;const s=a(o=>{n||(n=!0,r!==null&&r.destroy(),o instanceof Error?c(o):i(o))},"finish");r=d(t),r.once("connect",()=>s(!0)),r.once("error",o=>s(x(o)?o:!1)),r.setTimeout(e,()=>s(!1))})}a(O,"probeViewSocket");async function C(t,e,i=u){const c=Date.now()+i,n=e?.then(()=>"exit");for(;Date.now()<=c;){const r=Math.max(0,c-Date.now()),s=O(t,Math.min(l,r)).then(f=>f?"ready":"retry"),o=n===void 0?await s:await Promise.race([s,n]);if(o==="ready")return!0;if(o==="exit")return!1;if(n!==void 0){if(await Promise.race([m(l).then(()=>"sleep"),n])==="exit")return!1}else await m(l)}return!1}a(C,"waitForBrokerViewSocket");export{B as BROKER_VIEW_SOCKET_WAIT_MS,d as connectViewSocket,O as probeViewSocket,C as waitForBrokerViewSocket};
1
+ var m=Object.defineProperty;var a=(n,e)=>m(n,"name",{value:e,configurable:!0});import{EventEmitter as p}from"node:events";import{createConnection as E,Socket as S}from"node:net";import{WebSocket as u}from"ws";import{CLIENT_READ_CAPS as x}from"./broker-protocol.js";import{nodeRunDir as y,viewSocketPath as O}from"../canvas/paths.js";import{isBeneathRefusal as _,socketBeneath as k}from"../spaces/open-beneath.js";const w=3e4,l=100,A=w;function d(n){return new Promise(e=>{setTimeout(e,n)})}a(d,"sleep");function R(n){let e;try{e=k(y(n),O(n))}catch(t){const r=new S;return process.nextTick(()=>r.destroy(t)),r}const s=E(e.path);return s.once("connect",e.release),s.once("close",e.release),s}a(R,"connectViewSocket");function T(n,e){return new Promise((s,t)=>{let r=!1,o=null;const f=a(i=>{r||(r=!0,o!==null&&o.destroy(),i instanceof Error?t(i):s(i))},"finish");o=R(n),o.once("connect",()=>f(!0)),o.once("error",i=>f(_(i)?i:!1)),o.setTimeout(e,()=>f(!1))})}a(T,"probeViewSocket");async function K(n,e,s=w){const t=Date.now()+s,r=e?.then(()=>"exit");for(;Date.now()<=t;){const o=Math.max(0,t-Date.now()),f=T(n,Math.min(l,o)).then(c=>c?"ready":"retry"),i=r===void 0?await f:await Promise.race([f,r]);if(i==="ready")return!0;if(i==="exit")return!1;if(r!==void 0){if(await Promise.race([d(l).then(()=>"sleep"),r])==="exit")return!1}else await d(l)}return!1}a(K,"waitForBrokerViewSocket");const I=4180;function C(n,e){return new B(n,e)}a(C,"connectWssView");class B extends p{static{a(this,"WssViewLink")}ws;failed=!1;ended=!1;terminated=!1;pending=[];constructor(e,s){super(),this.ws=new u(e,{headers:s,maxPayload:x.maxLineBytes}),this.ws.on("open",()=>{for(const t of this.pending.splice(0))this.ws.send(t);this.emit("connect")}),this.ws.on("message",t=>{const r=Array.isArray(t)?Buffer.concat(t):Buffer.isBuffer(t)?t:Buffer.from(new Uint8Array(t));this.emit("data",r.at(-1)===10?r:Buffer.concat([r,Buffer.from(`
2
+ `)]))}),this.ws.on("unexpected-response",(t,r)=>{this.fail(Object.assign(new Error(`broker view refused the upgrade (${r.statusCode??"no status"})`),{code:"ECONNREFUSED"})),this.ws.terminate()}),this.ws.on("error",t=>this.fail(t)),this.ws.on("close",t=>{this.ended||(t===1006&&!this.terminated&&this.fail(Object.assign(new Error("broker view connection dropped (1006)"),{code:"ECONNRESET"})),this.ended=!0,this.emit("close",this.failed))})}get destroyed(){return this.ended||this.ws.readyState===u.CLOSING||this.ws.readyState===u.CLOSED}write(e){const s=e.endsWith(`
3
+ `)?e.slice(0,-1):e;return this.ws.readyState===u.CONNECTING?(this.pending.push(s),!0):this.ws.readyState!==u.OPEN?!1:(this.ws.send(s),!0)}destroy(){return this.terminated=!0,this.ws.terminate(),this}fail(e){this.failed||(this.failed=!0,this.emit("error",e))}}async function M(n,e,s,t=w){const r=Date.now()+t;let o=!1;for(s?.then(()=>{o=!0});Date.now()<=r&&!o;){if(await new Promise(i=>{const c=C(n,e),h=setTimeout(()=>{c.destroy(),i(!1)},Math.max(1,r-Date.now()));c.on("connect",()=>{clearTimeout(h),c.destroy(),i(!0)}),c.on("error",()=>{}),c.on("close",()=>{clearTimeout(h),i(!1)})}))return!0;if(Date.now()+l>r)break;await d(l)}return!1}a(M,"waitForWssView");export{I as BROKER_VIEW_PORT,A as BROKER_VIEW_SOCKET_WAIT_MS,R as connectViewSocket,C as connectWssView,T as probeViewSocket,K as waitForBrokerViewSocket,M as waitForWssView};
@@ -1,4 +1,4 @@
1
- import type { Mode, OutcomeDeliveryBinding } from '../canvas/index.js';
1
+ import type { LaunchSpec, Mode, OutcomeDeliveryBinding } from '../canvas/index.js';
2
2
  /** Kill switch. `CRTR_WARM_POOL=0` makes every create cold again: claims stop,
3
3
  * refills stop, and daemon-start pre-warm no-ops. Read live (not cached at
4
4
  * module load) so flipping it takes effect on the next `crtr sys daemon
@@ -29,6 +29,13 @@ export interface WarmRequest {
29
29
  * claimant's, so provenance survives the warm path. */
30
30
  creator: string | null;
31
31
  }
32
+ /** The frozen half of a request, resolved. */
33
+ export interface ResolvedRecipe {
34
+ key: string;
35
+ /** The launch spec the CLAIMANT gets — model included. */
36
+ launch: LaunchSpec;
37
+ request: WarmRequest;
38
+ }
32
39
  /** Claim a spare for `request`, reshaped onto its persona — or null when the
33
40
  * pool cannot serve it. The caller falls back to a cold spawn; a refused
34
41
  * create hook leaves the spare untouched and rejects the create. `beforeClaimDelivery`
@@ -53,10 +60,15 @@ export declare function resumeWarmClaim(request: WarmRequest, nodeId: string, be
53
60
  * new owner. Only after winning the marker is the broker killed and the row +
54
61
  * dir deleted. Never throws: a failed reap is retried on the next sweep. */
55
62
  export declare function reapStaleSpares(): Promise<string[]>;
63
+ /** Claims the lease and renews it until the returned release runs; undefined when another holder has it. */
64
+ export declare function holdMintLease(lane: string, key: string): Promise<(() => Promise<void>) | undefined>;
56
65
  /** Bring the pool for `request` back to depth 1, in the background. Never
57
66
  * throws and never blocks a caller: a failed mint just means the next create
58
67
  * for this key is cold again. */
59
68
  export declare function refillWarmPool(request: WarmRequest): void;
69
+ /** Births one spare as node `nodeId`. The node's mint lease is held before the node exists and until its birth settles, so no
70
+ * process's reaper can take the spare for a dead broker; when the lease is not obtained nothing is born. */
71
+ export declare function birthSpare({ key, request }: ResolvedRecipe, nodeId: string): Promise<void>;
60
72
  /** Mint a spare for the most recently used profiles so the FIRST create after
61
73
  * crtrd boots is warm too, not only the second. The profile is the whole
62
74
  * recipe: it supplies the cwd, and everything else a claim reshapes live.
@@ -1 +1 @@
1
- var _=Object.defineProperty;var n=(e,r)=>_(e,"name",{value:r,configurable:!0});import{createHash as x}from"node:crypto";import{claimWarmSpare as N,deleteNode as $,getNode as p,listNodes as C,listWarmSpares as b,registerWarmSpare as R,unregisterWarmSpare as W,updateNode as P,warmSpareCount as w}from"../canvas/index.js";import{recordedPidLiveness as L}from"../canvas/pid.js";import{nowIso as y}from"../fs-utils.js";import{admitNodeCreate as M}from"../command-hooks/lifecycle-create.js";import{spawnChildPrepared as A}from"./spawn.js";import{checkStart as E}from"./start-check.js";import{buildLaunchSpecAsync as O}from"./launch.js";import{setModelLive as I}from"./model-swap.js";import{setSituationalContextLive as T}from"./situational-live.js";import{deliverBearingsLive as D}from"./deliver-live.js";import{closeNode as h}from"./close.js";function g(){return process.env.CRTR_WARM_POOL!=="0"}n(g,"warmPoolEnabled");function j(e,r,t){const a=Object.entries(t.env??{}).sort(([s],[i])=>s<i?-1:s>i?1:0),o=JSON.stringify([e,r,t.tools??[],t.extensions??[],t.systemPrompt??null,a]);return x("sha256").update(o).digest("hex").slice(0,32)}n(j,"warmRecipeKey");async function d(e){const{launch:r}=await O(e.kind,e.mode,{lifecycle:"resident",hasManager:!1,...e.model!==null?{model:e.model}:{},cwd:e.cwd,profileId:e.profileId});return{key:j(e.cwd,e.profileId,r),launch:r,request:e}}n(d,"resolveRecipe");async function k(e){const r=e.creator===null?null:await p(e.creator);await E({grantee:r?.grantee??"app:terminal",sub:r?.sub,grant_id:r?.grant_id})}n(k,"checkClaimantStart");async function re(e,r={},t){await k(e);const a=await d(e);if(await w(a.key)===0)return null;const o=y(),s=await M({kind:e.kind,mode:e.mode,cwd:e.cwd,profile:e.profileId,root:!0,parentId:null,requestingNodeId:e.creator,lifecycle:"resident",replaces:null},e.creator===null?"app:terminal":await(async()=>{const c=await p(e.creator);if(!c?.grantee)throw new Error("warm node creator has no app");return c.grantee})());let i;try{i=await N(a.key,o,r)}finally{s()}return i===null?null:v(i,a,o,t)}n(re,"claimWarmNode");async function te(e,r,t){return await k(e),v(r,await d(e),y(),t)}n(te,"resumeWarmClaim");async function v(e,r,t,a){const{request:o}=r,i=(await p(e))?.launch?.model;await P(e,{created:t,kind:o.kind,mode:o.mode,name:o.name??o.kind,creator:o.creator,launch:r.launch,persona_ack:{kind:o.kind,mode:o.mode,lifecycle:"resident"},...o.model!==null?{model_override:o.model}:{}});try{a?.(e)}catch(l){return await m(e,"birth preparation",l)}try{await D(e)}catch(l){return await m(e,"bearings delivery",l)}const c=r.launch.model;if(c!==void 0&&c!==i)try{await I(e,c,r.launch.modelIntent)}catch(l){return await m(e,"model swap",l)}if(o.situationalContext!==null)try{await T(e,o.situationalContext)}catch(l){return await m(e,"situational-context delivery",l)}return e}n(v,"completeWarmClaim");async function m(e,r,t){console.error(`[warm-pool] ${r} failed on claim; closing the spare: ${t.message}`);try{await h(e)}catch{}return null}n(m,"abandonSpare");const B=3600*1e3;async function ae(){const e=[];let r;try{r=await b()}catch(a){return console.error(`[warm-pool] spare scan failed: ${a.message}`),e}const t=Date.now()-B;for(const a of r){if(u.has(a.node_id))continue;const o=Date.parse(a.created),s=Number.isNaN(o)||o<t,i=L(a.pi_pid,a.pi_pid_identity),c=(a.status==="active"||a.status==="idle")&&i==="alive";if(!(c&&!s)&&!(i==="indeterminate"&&!s))try{if(!await W(a.node_id))continue;if(c)try{await h(a.node_id)}catch{}await $(a.node_id),e.push(a.node_id)}catch(l){console.error(`[warm-pool] reap failed for ${a.node_id}: ${l.message}`)}}return e}n(ae,"reapStaleSpares");const f=new Set,u=new Set;function oe(e){if(g())try{d({...e,model:null,situationalContext:null}).then(S).catch(r=>console.error(`[warm-pool] recipe resolution failed: ${r.message}`))}catch(r){console.error(`[warm-pool] recipe resolution failed: ${r.message}`)}}n(oe,"refillWarmPool");async function S(e){const{key:r,request:t}=e;f.has(r)||await w(r)>0||(f.add(r),(async()=>{let a=null;try{await A({kind:t.kind,mode:t.mode,cwd:t.cwd,prompt:"",root:!0,readiness:"await",profile:t.profileId},async o=>{a=o,u.add(o),await R(o,r)})}catch(o){console.error(`[warm-pool] mint failed for ${t.kind}: ${o.message}`)}finally{a!==null&&u.delete(a),f.delete(r)}})())}n(S,"mint");const F=2;async function ne(){if(!g())return;let e;try{const r=new Set;e=[];for(const t of(await C({status:["active","idle"]})).reverse()){if(t.parent!==null||t.kind==="human")continue;const a=t.profile_id??null;if(!r.has(a??"")&&(r.add(a??""),e.push({cwd:t.cwd,profileId:a}),e.length>=F))break}}catch(r){console.error(`[warm-pool] prewarm scan failed: ${r.message}`);return}for(const r of e)try{d({kind:"general",mode:"base",cwd:r.cwd,profileId:r.profileId,model:null,situationalContext:null,name:null,creator:null}).then(S).catch(t=>console.error(`[warm-pool] prewarm failed for ${r.cwd}: ${t.message}`))}catch(t){console.error(`[warm-pool] prewarm failed for ${r.cwd}: ${t.message}`)}}n(ne,"prewarmRecentRecipes");export{re as claimWarmNode,ne as prewarmRecentRecipes,ae as reapStaleSpares,oe as refillWarmPool,te as resumeWarmClaim,g as warmPoolEnabled};
1
+ var k=Object.defineProperty;var n=(e,r)=>k(e,"name",{value:r,configurable:!0});import{createHash as x,randomUUID as N}from"node:crypto";import{openDb as R}from"../canvas/db.js";import{claimReconcilerLease as $,releaseReconcilerLease as L,renewReconcilerLease as C}from"../canvas/reconciler-leases.js";import{claimWarmSpare as b,deleteNode as E,getNode as p,listNodes as W,listWarmSpares as M,registerWarmSpare as P,unregisterWarmSpare as A,updateNode as I,warmSpareCount as w}from"../canvas/index.js";import{recordedPidLiveness as D}from"../canvas/pid.js";import{nowIso as u}from"../fs-utils.js";import{admitNodeCreate as O}from"../command-hooks/lifecycle-create.js";import{spawnChildPrepared as T}from"./spawn.js";import{newNodeId as H}from"./nodes.js";import{checkStart as F}from"./start-check.js";import{buildLaunchSpecAsync as K}from"./launch.js";import{setModelLive as U}from"./model-swap.js";import{setSituationalContextLive as j}from"./situational-live.js";import{deliverBearingsLive as B}from"./deliver-live.js";import{closeNode as y}from"./close.js";function h(){return process.env.CRTR_WARM_POOL!=="0"}n(h,"warmPoolEnabled");function G(e,r,a){const t=Object.entries(a.env??{}).sort(([s],[i])=>s<i?-1:s>i?1:0),o=JSON.stringify([e,r,a.tools??[],a.extensions??[],a.systemPrompt??null,t]);return x("sha256").update(o).digest("hex").slice(0,32)}n(G,"warmRecipeKey");async function d(e){const{launch:r}=await K(e.kind,e.mode,{lifecycle:"resident",hasManager:!1,...e.model!==null?{model:e.model}:{},cwd:e.cwd,profileId:e.profileId});return{key:G(e.cwd,e.profileId,r),launch:r,request:e}}n(d,"resolveRecipe");async function g(e){const r=e.creator===null?null:await p(e.creator);await F({grantee:r?.grantee??"app:terminal",sub:r?.sub,grant_id:r?.grant_id})}n(g,"checkClaimantStart");async function pe(e,r={},a){await g(e);const t=await d(e);if(await w(t.key)===0)return null;const o=u(),s=await O({kind:e.kind,mode:e.mode,cwd:e.cwd,profile:e.profileId,root:!0,parentId:null,requestingNodeId:e.creator,lifecycle:"resident",replaces:null},e.creator===null?"app:terminal":await(async()=>{const c=await p(e.creator);if(!c?.grantee)throw new Error("warm node creator has no app");return c.grantee})());let i;try{i=await b(t.key,o,r)}finally{s()}return i===null?null:v(i,t,o,a)}n(pe,"claimWarmNode");async function fe(e,r,a){return await g(e),v(r,await d(e),u(),a)}n(fe,"resumeWarmClaim");async function v(e,r,a,t){const{request:o}=r,i=(await p(e))?.launch?.model;await I(e,{created:a,kind:o.kind,mode:o.mode,name:o.name??o.kind,creator:o.creator,launch:r.launch,persona_ack:{kind:o.kind,mode:o.mode,lifecycle:"resident"},...o.model!==null?{model_override:o.model}:{}});try{t?.(e)}catch(l){return await m(e,"birth preparation",l)}try{await B(e)}catch(l){return await m(e,"bearings delivery",l)}const c=r.launch.model;if(c!==void 0&&c!==i)try{await U(e,c,r.launch.modelIntent)}catch(l){return await m(e,"model swap",l)}if(o.situationalContext!==null)try{await j(e,o.situationalContext)}catch(l){return await m(e,"situational-context delivery",l)}return e}n(v,"completeWarmClaim");async function m(e,r,a){console.error(`[warm-pool] ${r} failed on claim; closing the spare: ${a.message}`);try{await y(e)}catch{}return null}n(m,"abandonSpare");const J=3600*1e3;async function we(){const e=[];let r;try{r=await M()}catch(t){return console.error(`[warm-pool] spare scan failed: ${t.message}`),e}const a=Date.now()-J;for(const t of r){if(await z(t.node_id))continue;const o=Date.parse(t.created),s=Number.isNaN(o)||o<a,i=D(t.pi_pid,t.pi_pid_identity),c=(t.status==="active"||t.status==="idle")&&i==="alive";if(!(c&&!s)&&!(i==="indeterminate"&&!s))try{if(!await A(t.node_id))continue;if(c)try{await y(t.node_id)}catch{}await E(t.node_id),e.push(t.node_id)}catch(l){console.error(`[warm-pool] reap failed for ${t.node_id}: ${l.message}`)}}return e}n(we,"reapStaleSpares");const f=6e4;async function _(e,r){const a=N();if(await $(e,r,a,f)===void 0)return;const t=setInterval(()=>{C(e,r,a,f).catch(()=>{})},f/3);return t.unref(),async()=>{clearInterval(t),await L(e,r,a)}}n(_,"holdMintLease");async function z(e){return await(await R()).prepare("SELECT 1 FROM reconciler_leases WHERE lane = ? AND key = ? AND expires_at > ?").get("warm-pool-mint",e,new Date().toISOString())!==void 0}n(z,"mintLeaseHeld");function ue(e){if(h())try{d({...e,model:null,situationalContext:null}).then(S).catch(r=>console.error(`[warm-pool] recipe resolution failed: ${r.message}`))}catch(r){console.error(`[warm-pool] recipe resolution failed: ${r.message}`)}}n(ue,"refillWarmPool");async function S(e){const{key:r}=e,a=await _("warm-pool",r);if(a!==void 0){if(await w(r)>0){await a();return}Q(e,await H()).finally(()=>a().catch(()=>{}))}}n(S,"mint");async function Q({key:e,request:r},a){const t=await _("warm-pool-mint",a);if(t===void 0){console.error(`[warm-pool] mint refused for ${r.kind}: the mint lease of ${a} is held elsewhere`);return}try{await T({nodeId:a,kind:r.kind,mode:r.mode,cwd:r.cwd,prompt:"",root:!0,readiness:"await",profile:r.profileId},async o=>{await P(o,e)})}catch(o){console.error(`[warm-pool] mint failed for ${r.kind}: ${o.message}`)}finally{await t().catch(()=>{})}}n(Q,"birthSpare");const V=2;async function ye(){if(!h())return;let e;try{const r=new Set;e=[];for(const a of(await W({status:["active","idle"]})).reverse()){if(a.parent!==null||a.kind==="human")continue;const t=a.profile_id??null;if(!r.has(t??"")&&(r.add(t??""),e.push({cwd:a.cwd,profileId:t}),e.length>=V))break}}catch(r){console.error(`[warm-pool] prewarm scan failed: ${r.message}`);return}for(const r of e)try{d({kind:"general",mode:"base",cwd:r.cwd,profileId:r.profileId,model:null,situationalContext:null,name:null,creator:null}).then(S).catch(a=>console.error(`[warm-pool] prewarm failed for ${r.cwd}: ${a.message}`))}catch(a){console.error(`[warm-pool] prewarm failed for ${r.cwd}: ${a.message}`)}}n(ye,"prewarmRecentRecipes");export{Q as birthSpare,pe as claimWarmNode,_ as holdMintLease,ye as prewarmRecentRecipes,we as reapStaleSpares,ue as refillWarmPool,fe as resumeWarmClaim,h as warmPoolEnabled};
@@ -0,0 +1,11 @@
1
+ import type { PersonSnapshot } from './person-store.js';
2
+ /** The old user store's contents in the shape of a person's snapshot, or null when this install never had a store. */
3
+ export declare function readLegacyUserSnapshot(root: string): PersonSnapshot | null;
4
+ /** Pre-canvas per-project memory caps (`none|name|preview`) the canvas import has not converted yet. */
5
+ export declare function listLegacyProjectCaps(root: string): Array<{
6
+ profileId: string;
7
+ path: string;
8
+ memory: string;
9
+ }>;
10
+ /** Delete every legacy cap row once the canvas import has stored the converted limits on the profile rows. */
11
+ export declare function deleteLegacyProjectCaps(root: string): void;
@@ -0,0 +1 @@
1
+ var y=Object.defineProperty;var r=(s,a)=>y(s,"name",{value:a,configurable:!0});import{prepared as o}from"../sqlite-statements.js";import{userStore as c}from"./paths.js";import{openScopedStore as u,scopedStoreExists as i,withScopedWrite as g}from"./db.js";function S(s){const a=c(s);if(!i(a))return null;const t=u(a),m=o(t,"SELECT profile_id, path FROM profile_projects ORDER BY profile_id, position").all(),E=o(t,"SELECT id, name, created_at, last_used_at, paused_at, default_kind, grantee, metadata_json, delivery_limits_json, environment_id FROM profiles ORDER BY rowid").all().map(e=>{const n=JSON.parse(e.metadata_json),f=JSON.parse(e.delivery_limits_json);return{profileId:e.id,manifest:{schema_version:1,name:e.name,projects:m.filter(_=>_.profile_id===e.id).map(_=>({path:_.path})),paused_at:e.paused_at,...e.default_kind===null?{}:{default_kind:e.default_kind},...e.grantee===null?{}:{grantee:e.grantee},...e.environment_id===null?{}:{environment_id:e.environment_id},...Object.keys(f).length===0?{}:{delivery_limits:f},...Object.keys(n).length===0?{}:{metadata:n},created_at:e.created_at,last_used_at:e.last_used_at}}}),k=Object.fromEntries(o(t,"SELECT directory, profile_id FROM profile_defaults").all().map(e=>[e.directory,e.profile_id])),p={};for(const e of o(t,"SELECT owner_key, raw_json FROM scope_settings WHERE owner_key != 'project'").all())p[e.owner_key]=JSON.parse(e.raw_json);const d={},l=r(e=>d[e]??={marketplaces:{},plugins:{},activeCanvas:null},"stateOf");for(const e of o(t,"SELECT owner_key, last_self_check, active_canvas FROM scope_bookkeeping WHERE owner_key != 'project'").all()){const n=l(e.owner_key);e.last_self_check!==null&&(n.last_self_check=e.last_self_check),n.activeCanvas=e.active_canvas}for(const e of o(t,"SELECT owner_key, name, last_updated FROM scope_marketplaces WHERE owner_key != 'project'").all())l(e.owner_key).marketplaces[e.name]=e.last_updated===null?{}:{last_updated:e.last_updated};for(const e of o(t,"SELECT owner_key, name, last_updated, etag, checked_at FROM scope_plugins WHERE owner_key != 'project'").all())l(e.owner_key).plugins[e.name]={...e.last_updated===null?{}:{last_updated:e.last_updated},...e.etag===null?{}:{etag:e.etag},...e.checked_at===null?{}:{checked_at:e.checked_at}};return{profiles:E,defaults:k,settings:p,state:d}}r(S,"readLegacyUserSnapshot");function v(s){const a=c(s);return i(a)?o(u(a),"SELECT profile_id, path, memory FROM legacy_project_caps ORDER BY profile_id, path").all().map(t=>({profileId:t.profile_id,path:t.path,memory:t.memory})):[]}r(v,"listLegacyProjectCaps");function w(s){const a=c(s);i(a)&&g(a,t=>{o(t,"DELETE FROM legacy_project_caps").run()})}r(w,"deleteLegacyProjectCaps");export{w as deleteLegacyProjectCaps,v as listLegacyProjectCaps,S as readLegacyUserSnapshot};
@@ -0,0 +1,18 @@
1
+ /** One enabled plugin row of the person's user scope, with its marketplace's url and ref. */
2
+ export interface PluginInstall {
3
+ name: string;
4
+ version: string | null;
5
+ sourcePath: string | null;
6
+ marketplace: {
7
+ name: string;
8
+ url: string | null;
9
+ ref: string | null;
10
+ } | null;
11
+ }
12
+ /** The directory holding this person's materialized plugins as `<dir>/<plugin name>`; undefined when none were materialized. */
13
+ export declare function materializedPluginsDir(person: string): string | undefined;
14
+ /** Install `installs` for `person` at `revision` into this process's plugin cache, once per (person, revision). When a plugin cannot
15
+ * be installed — a source on another machine, a marketplace that does not list it, a failed clone — the failure is held for that person
16
+ * and thrown by the next read of their plugins (`materializedPluginsDir`), so a request that never reads plugins, such as the one that
17
+ * fixes the settings, still works; the next load retries. */
18
+ export declare function materializePlugins(person: string, revision: number, installs: readonly PluginInstall[]): Promise<void>;
@@ -0,0 +1 @@
1
+ var z=Object.defineProperty;var u=(e,n)=>z(e,"name",{value:n,configurable:!0});import{cpSync as S,existsSync as h,mkdirSync as b,renameSync as M,rmSync as w}from"node:fs";import{tmpdir as A}from"node:os";import{isAbsolute as $,join as l,relative as P,resolve as v}from"node:path";import{CrtrError as c}from"../errors.js";import{gitAsync as x}from"../git.js";import{readMarketplaceManifest as D}from"../manifest.js";const m=new Map,d=new Map;function q(e){const n=m.get(e);if(n!==void 0&&"failure"in n)throw n.failure;return n?.dir}u(q,"materializedPluginsDir");function y(e){return l(A(),"crtr-plugin-cache",e.replace(/[^A-Za-z0-9._-]/g,"_"))}u(y,"cacheRoot");async function _(e,n,o,r){const t=await x(["clone","--depth","1",...n?["--branch",n]:[],e,o]);if(t.status!==0)throw new c("plugin_install_failed",`${r}: git clone ${e} failed: ${t.stderr.trim()}`)}u(_,"cloneInto");async function R(e,n){const o=new Map;b(l(e,"plugins"),{recursive:!0});for(const r of n){if(r.sourcePath!==null)throw new c("plugin_source_unreachable",`${r.name}: its source is ${r.sourcePath} on the machine that registered it, which the control plane cannot read`);const t=r.marketplace;if(t===null)throw new c("plugin_source_unreachable",`${r.name}: it names neither a marketplace nor a path`);if(t.url===null||t.url==="")throw new c("plugin_source_unreachable",`${r.name}: its marketplace ${t.name} has no url`);const s=`${t.url}\0${t.ref??""}`;let a=o.get(s);a===void 0&&(a=l(e,"marketplaces",String(o.size)),await _(t.url,t.ref,a,`${r.name}: marketplace ${t.name}`),o.set(s,a));const i=D(a)?.plugins.find(k=>k.name===r.name);if(i===void 0)throw new c("plugin_install_failed",`${r.name}: marketplace ${t.name} (${t.url}) does not list it`);const f=l(e,"plugins",r.name);if($(i.source)||/^[a-z][a-z0-9+.-]*:|^git@/i.test(i.source)||i.source.endsWith(".git")){await _(i.source,null,f,r.name);continue}const p=v(a,i.source),g=P(a,p);if(g.startsWith("..")||$(g))throw new c("plugin_install_failed",`${r.name}: its source ${i.source} leaves the marketplace`);if(!h(p))throw new c("plugin_install_failed",`${r.name}: its source ${i.source} is not in marketplace ${t.name}`);S(p,f,{recursive:!0})}w(l(e,"marketplaces"),{recursive:!0,force:!0})}u(R,"installAll");async function B(e,n,o){const r=m.get(e);if(r?.revision===n&&!("failure"in r))return;const t=l(y(e),String(n)),s=`${e}\0${n}`;let a=d.get(s);a===void 0&&(a=(async()=>{if(!h(l(t,"plugins"))){const i=l(y(e),`${n}.${process.pid}.${Date.now()}`);try{await R(i,o);try{M(i,t)}catch(f){if(!h(l(t,"plugins")))throw f}}finally{w(i,{recursive:!0,force:!0})}}return l(t,"plugins")})().finally(()=>d.delete(s)),d.set(s,a));try{m.set(e,{revision:n,dir:await a})}catch(i){if(!(i instanceof c))throw i;m.set(e,{revision:n,failure:i})}}u(B,"materializePlugins");export{B as materializePlugins,q as materializedPluginsDir};
@@ -1,4 +1,4 @@
1
- export { initializeFreshScopedStore } from './db.js';
1
+ import { type PersonSnapshot } from './person-store.js';
2
2
  /** Conversion is intentionally explicit. Deployment coordination must prove all legacy writers at these shared roots are stopped before calling it. */
3
3
  export declare function convertLegacyScopedStore(input: {
4
4
  kind: 'user' | 'project' | 'provider';
@@ -6,3 +6,10 @@ export declare function convertLegacyScopedStore(input: {
6
6
  }): void;
7
7
  /** Converts legacy provider pools only after the activation owner has stopped every writer sharing this agent directory. */
8
8
  export declare function convertLegacyProviderStore(agentDir: string): Promise<void>;
9
+ export declare function personStoresCopied(): Promise<boolean>;
10
+ /** Copy this install's files into the person's rows, once: profiles, scope settings and bookkeeping, the plugin and marketplace
11
+ * lists, managed model accounts with their cooldowns, rotation settings, the OpenAI device id, `auth.json` API keys and the profile, app and deployment env files (sealed into `env_vars`). One
12
+ * transaction, skipping any key a row already holds, ending with `canvas_meta.person_stores_copied`. The files stay, unread. */
13
+ export declare function copyPersonStoresToRows(person: string, legacyUserSnapshot: PersonSnapshot | null, agentDir: string): Promise<void>;
14
+ /** The install's person just became known: copy the old local files into their rows once, then load their snapshot. */
15
+ export declare function adoptInstallPerson(person: string): Promise<void>;