@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,2 +1,2 @@
1
- var ue=Object.defineProperty;var a=(e,n)=>ue(e,"name",{value:n,configurable:!0});import{existsSync as g,readdirSync as W,readFileSync as S,rmSync as $,statSync as k}from"node:fs";import{join as d}from"node:path";import{validateCommandManifest as de}from"../../api/command-manifest/manifest.js";import{crtrHome as z}from"../canvas/paths.js";import{withCanvasWrite as G}from"../canvas/db.js";import{bundleVersion as ce,isInstalledGeneration as fe,recordCheckedGeneration as le}from"../command-plugins/bundle.js";import{readConfig as q,readState as pe,updateConfig as me,updateState as ve}from"../config.js";import{emitEvent as m}from"../events/emit.js";import{describeOutboundFailure as he,outboundFetch as we,outboundRefusal as V,OutboundError as ge}from"../events/outbound.js";import{withExclusiveDirectoryLockAsync as Z}from"../exclusive-lock.js";import{atomicWriteText as x,ensureDir as T,pathExists as $e}from"../fs-utils.js";import{reconcilePackages as L}from"../graph/package-reconcile.js";import{readPluginManifest as C}from"../manifest.js";import{bundleSwapLockPath as J}from"../plugin-swap-lock.js";import{pluginsDir as ye,userScopeRoot as K}from"../scope.js";import{listInstalledPlugins as be}from"../resolver.js";import{localGrants as j}from"../grants/mirror.js";import{ProviderError as c}from"./errors.js";const A="[A-Za-z0-9_-]{1,64}",_e=new RegExp(`^(${A}):(${A})$`),Q=new RegExp(`^${A}$`),Pe=3e4,X=3e4;function Y(e){const n=new Set;for(const r of e)if(r.status==="active")for(const{scope:t}of r.resolved_scopes){const o=_e.exec(t);o&&o[1]!=="crtr"&&n.add(o[1])}return[...n].sort()}a(Y,"providerIdsFromGrants");function v(e){return d(ye("user"),e)}a(v,"pluginRoot");function R(){return d(z(),"providers")}a(R,"providersRoot");function ee(e,n){return d(R(),e,`v${n}`)}a(ee,"majorDir");function B(e){if(!Q.test(e))throw new c("not_found",`"${e}" is not a provider id`,{param:"provider"})}a(B,"assertId");function E(){const e=q("user").runtime?.issuer;if(!e)throw new c("not_found","provider bundles need a directory-connected runtime");return e.replace(/\/+$/,"")}a(E,"directoryBase");async function ne(e,n){const r=`${E()}/providers/${encodeURIComponent(e)}/plugin${n.version!==void 0?`?version=${n.version}`:""}`;let t;try{t=await we("bundle_fetch",r,{headers:{Accept:"application/x-tar",...n.ifNoneMatch!==void 0?{"If-None-Match":n.ifNoneMatch}:{}},signal:AbortSignal.timeout(Pe)})}catch(i){return{status:"failed",message:`could not reach ${r}: ${i instanceof Error?i.message:String(i)}`,cause:i}}if(t.status===304){if(n.ifNoneMatch===void 0){const i=`HTTP 304 from ${r} without a conditional request`;return{status:"failed",message:i,cause:V("bundle_fetch",r,i)}}return{status:304}}if(t.status===404||t.status===410)return await t.body?.cancel().catch(()=>{}),{status:t.status===404?404:410,message:`HTTP ${t.status} from ${r}`};if(t.status<200||t.status>=300){await t.body?.cancel().catch(()=>{});{const i=`HTTP ${t.status} from ${r}`;return{status:"failed",message:i,cause:V("bundle_fetch",r,i)}}}let o;try{o=new Uint8Array(await t.arrayBuffer())}catch(i){return{status:"failed",message:`reading ${r} failed: ${i instanceof Error?i.message:String(i)}`,cause:new ge("bundle_fetch",r,i)}}const s=t.headers.get("etag");return{status:200,raw:o,...s!==null?{etag:s}:{}}}a(ne,"fetchProviderBundle");const I=new WeakSet;class M extends Error{static{a(this,"BundleInvalid")}issues;constructor(n,r){super(n),this.issues=r}}function re(e,n,r){if(r.provider===void 0)return"the archive carries no provider block";if(r.provider.id!==e)return`the archive is provider "${r.provider.id}", not "${e}"`;if(n!==void 0&&r.provider.major!==n)return`the archive is major ${r.provider.major}, not ${n}`;const t=["hooks","kinds","page_components","memory_extensions"].filter(o=>r[o]!==void 0);if(t.length>0)return`a provider bundle may not carry ${t.join(", ")}`}a(re,"wrongBundle");function D(e,n,r){m({level:"error",event:"daemon.providers.bundle_invalid",fields:{provider:e,...n!==void 0?{major:n}:{},...r instanceof M?{issues:r.issues}:{}},error:r})}a(D,"logInvalid");function te(e,n,r){m({level:"warn",event:"daemon.providers.bundle_fetch_failed",fields:{provider:e,...n!==void 0?{major:n}:{},message:r instanceof Error?r.message:String(r),...he(r instanceof Error?r.cause:void 0)}})}a(te,"logFailure");async function oe(){return import("../../commands/pkg/plugin-manage.js")}a(oe,"pluginManage");const y=new Map,b=a(e=>`${z()}\0${e}`,"installKey");function Se(e){const n=e,r=n?.code??n?.cause?.code;return typeof r=="string"&&/^[A-Z][A-Z0-9_]{1,30}$/.test(r)?`${r} on provider install directory`:e instanceof c&&e.message.includes("HTTP 404")?"directory returned HTTP 404":e instanceof c&&e.message.includes("HTTP 410")?"directory returned HTTP 410":"provider bundle could not be installed"}a(Se,"publicInstallCause");function Ee(e){if(h(e)===void 0)return y.get(b(e))??{status:"installing"}}a(Ee,"providerInstallState");function Ie(e){return new c("provider_unavailable",`provider "${e}" unavailable: ${Ee(e)?.error??"bundle installation pending"}`)}a(Ie,"unavailableProviderError");function h(e){const n=C(v(e));if(!(n?.provider===void 0||n.transport?.kind!=="http"&&n.transport?.kind!=="machine")&&$e(d(v(e),"commands.json"))){try{if(k(d(v(e),"commands.json")).size===0)return}catch{return}return{provider:n.provider,transport:n.transport.kind==="machine"?{kind:"machine"}:{kind:"http",endpoint:n.transport.endpoint}}}}a(h,"installedManifest");async function N(e,n,r=!1){const t=K();h(e)===void 0&&y.set(b(e),{status:"installing"});try{return T(d(t,"tmp")),await Z(J(t,e),async()=>{const o=v(e),s=C(o);if(s!==null&&s.provider===void 0)throw new c("provider_unavailable",`plugin "${e}" is installed and is not the directory's provider bundle`);const i=h(e)!==void 0;if(i&&r)return"unchanged";const f=i&&n?pe("user").plugins[e]?.etag:void 0,u=await ne(e,f!==void 0?{ifNoneMatch:f}:{});if(u.status===304)return"unchanged";if(u.status===404||u.status===410)throw new c("not_found",`the directory serves no provider "${e}" (${u.message})`,{param:"provider"});if(u.status==="failed")throw new c("provider_unavailable",`provider "${e}" bundle fetch failed: ${u.message}`,{cause:u.cause});const l=ce(u.raw);if(i&&fe(e,"user",o,l))return le("user",e,u.etag,{swapped:!1}),"unchanged";const{installPluginArchive:w}=await oe();try{await w(e,u.raw,{scope:"user",scopeRootPath:t,root:o,version:l,etag:u.etag,enable:!i,bundle:{endpoint:`${E()}/providers/${encodeURIComponent(e)}/plugin`},transport:{kind:"http",endpoint:E()},accept:a(p=>re(e,void 0,p),"accept")})}catch(p){D(e,void 0,p);const U=new c("not_found",`provider "${e}" served an invalid bundle: ${p instanceof Error?p.message:String(p)}`,{param:"provider"});throw I.add(U),U}try{await G(async p=>await L(p))}catch(p){m({level:"error",event:"daemon.providers.docs_reconcile_failed",fields:{provider:e},error:p})}return m({level:"info",event:"daemon.providers.bundle_installed",fields:{provider:e,version:l,replaced:i}}),y.delete(b(e)),i?"updated":"installed"},{timeoutMs:X,timeoutError:a(()=>new c("provider_unavailable",`timed out waiting for another process replacing plugin "${e}"`),"timeoutError")})}catch(o){throw h(e)===void 0&&y.set(b(e),{status:"install_failed",error:Se(o)}),o instanceof c?o:(m({level:"error",event:"daemon.providers.bundle_install_failed",fields:{provider:e},error:o}),Ie(e))}}a(N,"refreshInstalled");async function en(e){B(e),h(e)===void 0&&await N(e,!1,!0)}a(en,"ensureProviderBundle");async function nn(e,n){return B(e),n.version!==void 0&&h(e)?.provider.major!==n.version?O(e,n.version,n.conditional):N(e,n.conditional)}a(nn,"refreshProviderBundle");async function ae(e,n,r){const{validatePluginArchive:t}=await oe(),o=await t(r);if(o.bundle===void 0)throw new M(`provider "${e}" major ${n} bundle is invalid: ${o.issues.map(i=>i.message).join("; ")}`,o.issues);const s=re(e,n,o.bundle);if(s!==void 0)throw new M(`provider "${e}" major ${n} bundle is invalid: ${s}`,[]);if(o.bundle.transport===void 0)throw new M(`provider "${e}" major ${n} bundle declares no transport`,[]);return o.bundle}a(ae,"validateArchive");function Me(e){T(e),x(d(e,"retired"),`${new Date().toISOString()}
2
- `),$(d(e,"bundle.tar"),{force:!0}),$(d(e,"etag"),{force:!0})}a(Me,"retire");function ie(e,n){return new c("provider_version_retired",`provider "${e}" major ${n} is retired`,{param:"version"})}a(ie,"retiredError");async function O(e,n,r){const t=ee(e,n),o=d(t,"bundle.tar"),s=g(o),i=s&&r&&g(d(t,"etag"))?S(d(t,"etag"),"utf8"):void 0,f=await ne(e,{version:n,...i!==void 0?{ifNoneMatch:i}:{}});if(f.status===304)return"unchanged";if(f.status===410)throw Me(t),m({level:"info",event:"daemon.providers.major_retired",fields:{provider:e,major:n}}),ie(e,n);if(f.status===404)throw new c("not_found",`provider "${e}" never served major ${n}`,{param:"version"});if(f.status==="failed")throw new c("provider_unavailable",`provider "${e}" major ${n} bundle fetch failed: ${f.message}`,{cause:f.cause});try{await ae(e,n,f.raw)}catch(l){D(e,n,l);const w=new c(s?"provider_unavailable":"not_found",l instanceof Error?l.message:String(l),{param:"version"});throw I.add(w),w}T(t),$(d(t,"retired"),{force:!0});const u=s&&Buffer.from(f.raw).equals(S(o));return u||x(o,f.raw),f.etag!==void 0?x(d(t,"etag"),f.etag):$(d(t,"etag"),{force:!0}),u?"unchanged":s?"updated":"installed"}a(O,"refreshPinned");function ke(){const e=[],n=R();if(!g(n))return e;for(const r of W(n)){if(!Q.test(r))continue;let t;try{t=W(d(n,r))}catch{continue}for(const o of t){const s=/^v([1-9][0-9]*)$/.exec(o);s&&g(d(n,r,o,"bundle.tar"))&&e.push([r,Number(s[1])])}}return e}a(ke,"cachedMajors");function xe(e){const n=de(e,{transport:"http",reservedCoreNames:new Set});if(n.manifest===void 0)throw new c("not_found","the provider bundle's commands.json no longer validates");return n.manifest}a(xe,"readCommands");const _=new Map,H=new Map;function Te(e,n){const r=k(n),t=`${r.ino}:${r.mtimeMs}:${r.size}`,o=H.get(e);if(o?.stamp===t)return o.commands;const s=xe(JSON.parse(S(n,"utf8")));return H.set(e,{stamp:t,commands:s}),s}a(Te,"installedCommands");async function rn(e,n){B(e);const r=h(e);if(n===void 0||r?.provider.major===n){if(r===void 0)throw new c("not_found",`provider "${e}" has no installed bundle`,{param:"provider"});const l=v(e),w=Te(e,d(l,"commands.json"));return{id:e,major:r.provider.major,provider:r.provider,commands:w,transport:r.transport,source:"installed",root:l}}if(!Number.isInteger(n)||n<1)throw new c("invalid_request","version must be an integer of at least 1",{param:"version"});const t=ee(e,n);if(g(d(t,"retired")))throw ie(e,n);const o=d(t,"bundle.tar");g(o)||await O(e,n,!1);const s=`${e}/${n}`,i=k(o),f=`${i.mtimeMs}:${i.size}`;let u=_.get(s)?.stamp===f?_.get(s).bundle:void 0;if(u===void 0){try{u=await ae(e,n,new Uint8Array(S(o)))}catch(l){throw D(e,n,l),new c("not_found",`provider "${e}" has no valid bundle for major ${n}`,{param:"version"})}_.set(s,{stamp:f,bundle:u})}return{id:e,major:n,provider:u.provider,commands:u.commands,transport:u.transport.kind==="machine"?{kind:"machine"}:{kind:"http",endpoint:u.transport.endpoint},source:"pinned"}}a(rn,"resolveProviderBundle");let P=null,F=!1;function Ce(e,n){return e?.provider?.id===n&&e.bundle?.endpoint===`${E()}/providers/${encodeURIComponent(n)}/plugin`}a(Ce,"isDirectoryBundle");async function se(e){return Y(await j()).includes(e)}a(se,"grantNames");async function je(e){await Z(J(K(),e),async()=>{if(!(await se(e)||!Ce(C(v(e)),e))){$(v(e),{recursive:!0,force:!0}),me("user",n=>{delete n.plugins[e]}),ve("user",n=>{delete n.plugins[e]}),$(d(R(),e),{recursive:!0,force:!0}),H.delete(e),y.delete(b(e));for(const n of[..._.keys()])n.startsWith(`${e}/`)&&_.delete(n);try{await G(async n=>await L(n))}catch(n){m({level:"error",event:"daemon.providers.docs_reconcile_failed",fields:{provider:e},error:n})}m({level:"info",event:"daemon.providers.bundle_uninstalled",fields:{provider:e}})}},{timeoutMs:X,timeoutError:a(()=>new c("provider_unavailable",`timed out waiting for another process replacing plugin "${e}"`),"timeoutError")})}a(je,"uninstallProvider");async function Ae(){if(!(await j()).every(e=>e.status!=="active")){for(const e of be("user"))if(!(e.manifest.provider===void 0||await se(e.name)))try{await je(e.name)}catch(n){m({level:"error",event:"daemon.providers.bundle_uninstall_failed",fields:{provider:e.name},error:n})}}}a(Ae,"uninstallDisconnected");async function Re(){if(!q("user").runtime?.issuer)return;const e=Y(await j());for(const n of e)try{await N(n,!0)}catch(r){r instanceof Object&&I.has(r)||te(n,void 0,r)}await Ae();for(const[n,r]of ke())try{await O(n,r,!0)}catch(t){if(t instanceof c&&t.code==="provider_version_retired"||t instanceof Object&&I.has(t))continue;te(n,r,t)}}a(Re,"syncOnce");function tn(){return P!==null?(F=!0,P):(P=(async()=>{try{do F=!1,await Re();while(F)}finally{P=null}})(),P)}a(tn,"syncProviderBundles");export{en as ensureProviderBundle,Y as providerIdsFromGrants,Ee as providerInstallState,nn as refreshProviderBundle,rn as resolveProviderBundle,tn as syncProviderBundles,Ie as unavailableProviderError};
1
+ var ue=Object.defineProperty;var a=(e,n)=>ue(e,"name",{value:n,configurable:!0});import{existsSync as g,readdirSync as W,readFileSync as S,rmSync as $,statSync as k}from"node:fs";import{join as d}from"node:path";import{validateCommandManifest as de}from"../../api/command-manifest/manifest.js";import{crtrHome as z}from"../canvas/paths.js";import{withCanvasWrite as G}from"../canvas/db.js";import{bundleVersion as ce,isInstalledGeneration as fe,recordCheckedGeneration as le}from"../command-plugins/bundle.js";import{readConfig as q,readState as pe,updateConfig as me,updateState as ve}from"../config.js";import{emitEvent as m}from"../events/emit.js";import{describeOutboundFailure as he,outboundFetch as we,outboundRefusal as V,OutboundError as ge}from"../events/outbound.js";import{withExclusiveDirectoryLockAsync as Z}from"../exclusive-lock.js";import{atomicWriteText as x,ensureDir as T,pathExists as $e}from"../fs-utils.js";import{reconcilePackages as L}from"../graph/package-reconcile.js";import{readPluginManifest as C}from"../manifest.js";import{bundleSwapLockPath as J}from"../plugin-swap-lock.js";import{pluginsDir as ye,userScopeRoot as K}from"../scope.js";import{listInstalledPlugins as be}from"../resolver.js";import{localGrants as j}from"../grants/mirror.js";import{ProviderError as c}from"./errors.js";const A="[A-Za-z0-9_-]{1,64}",_e=new RegExp(`^(${A}):(${A})$`),Q=new RegExp(`^${A}$`),Pe=3e4,X=3e4;function Y(e){const n=new Set;for(const r of e)if(r.status==="active")for(const{scope:t}of r.resolved_scopes){const o=_e.exec(t);o&&o[1]!=="crtr"&&n.add(o[1])}return[...n].sort()}a(Y,"providerIdsFromGrants");function v(e){return d(ye("user"),e)}a(v,"pluginRoot");function R(){return d(z(),"providers")}a(R,"providersRoot");function ee(e,n){return d(R(),e,`v${n}`)}a(ee,"majorDir");function B(e){if(!Q.test(e))throw new c("not_found",`"${e}" is not a provider id`,{param:"provider"})}a(B,"assertId");function E(){const e=q("user").runtime?.issuer;if(!e)throw new c("not_found","provider bundles need a directory-connected runtime");return e.replace(/\/+$/,"")}a(E,"directoryBase");async function ne(e,n){const r=`${E()}/providers/${encodeURIComponent(e)}/plugin${n.version!==void 0?`?version=${n.version}`:""}`;let t;try{t=await we("bundle_fetch",r,{headers:{Accept:"application/x-tar",...n.ifNoneMatch!==void 0?{"If-None-Match":n.ifNoneMatch}:{}},signal:AbortSignal.timeout(Pe)})}catch(i){return{status:"failed",message:`could not reach ${r}: ${i instanceof Error?i.message:String(i)}`,cause:i}}if(t.status===304){if(n.ifNoneMatch===void 0){const i=`HTTP 304 from ${r} without a conditional request`;return{status:"failed",message:i,cause:V("bundle_fetch",r,i)}}return{status:304}}if(t.status===404||t.status===410)return await t.body?.cancel().catch(()=>{}),{status:t.status===404?404:410,message:`HTTP ${t.status} from ${r}`};if(t.status<200||t.status>=300){await t.body?.cancel().catch(()=>{});{const i=`HTTP ${t.status} from ${r}`;return{status:"failed",message:i,cause:V("bundle_fetch",r,i)}}}let o;try{o=new Uint8Array(await t.arrayBuffer())}catch(i){return{status:"failed",message:`reading ${r} failed: ${i instanceof Error?i.message:String(i)}`,cause:new ge("bundle_fetch",r,i)}}const s=t.headers.get("etag");return{status:200,raw:o,...s!==null?{etag:s}:{}}}a(ne,"fetchProviderBundle");const I=new WeakSet;class M extends Error{static{a(this,"BundleInvalid")}issues;constructor(n,r){super(n),this.issues=r}}function re(e,n,r){if(r.provider===void 0)return"the archive carries no provider block";if(r.provider.id!==e)return`the archive is provider "${r.provider.id}", not "${e}"`;if(n!==void 0&&r.provider.major!==n)return`the archive is major ${r.provider.major}, not ${n}`;const t=["hooks","kinds","page_components","memory_extensions"].filter(o=>r[o]!==void 0);if(t.length>0)return`a provider bundle may not carry ${t.join(", ")}`}a(re,"wrongBundle");function D(e,n,r){m({level:"error",event:"daemon.providers.bundle_invalid",fields:{provider:e,...n!==void 0?{major:n}:{},...r instanceof M?{issues:r.issues}:{}},error:r})}a(D,"logInvalid");function te(e,n,r){m({level:"warn",event:"daemon.providers.bundle_fetch_failed",fields:{provider:e,...n!==void 0?{major:n}:{},message:r instanceof Error?r.message:String(r),...he(r instanceof Error?r.cause:void 0)}})}a(te,"logFailure");async function oe(){return import("../../commands/pkg/plugin-manage.js")}a(oe,"pluginManage");const y=new Map,b=a(e=>`${z()}\0${e}`,"installKey");function Se(e){const n=e,r=n?.code??n?.cause?.code;return typeof r=="string"&&/^[A-Z][A-Z0-9_]{1,30}$/.test(r)?`${r} on provider install directory`:e instanceof c&&e.message.includes("HTTP 404")?"directory returned HTTP 404":e instanceof c&&e.message.includes("HTTP 410")?"directory returned HTTP 410":"provider bundle could not be installed"}a(Se,"publicInstallCause");function Ee(e){if(h(e)===void 0)return y.get(b(e))??{status:"installing"}}a(Ee,"providerInstallState");function Ie(e){return new c("provider_unavailable",`provider "${e}" unavailable: ${Ee(e)?.error??"bundle installation pending"}`)}a(Ie,"unavailableProviderError");function h(e){const n=C(v(e));if(!(n?.provider===void 0||n.transport?.kind!=="http"&&n.transport?.kind!=="machine")&&$e(d(v(e),"commands.json"))){try{if(k(d(v(e),"commands.json")).size===0)return}catch{return}return{provider:n.provider,transport:n.transport.kind==="machine"?{kind:"machine"}:{kind:"http",endpoint:n.transport.endpoint}}}}a(h,"installedManifest");async function N(e,n,r=!1){const t=K();h(e)===void 0&&y.set(b(e),{status:"installing"});try{return T(d(t,"tmp")),await Z(J(t,e),async()=>{const o=v(e),s=C(o);if(s!==null&&s.provider===void 0)throw new c("provider_unavailable",`plugin "${e}" is installed and is not the directory's provider bundle`);const i=h(e)!==void 0;if(i&&r)return"unchanged";const f=i&&n?pe("user").plugins[e]?.etag:void 0,u=await ne(e,f!==void 0?{ifNoneMatch:f}:{});if(u.status===304)return"unchanged";if(u.status===404||u.status===410)throw new c("not_found",`the directory serves no provider "${e}" (${u.message})`,{param:"provider"});if(u.status==="failed")throw new c("provider_unavailable",`provider "${e}" bundle fetch failed: ${u.message}`,{cause:u.cause});const l=ce(u.raw);if(i&&fe(e,"user",o,l))return await le("user",e,u.etag,{swapped:!1}),"unchanged";const{installPluginArchive:w}=await oe();try{await w(e,u.raw,{scope:"user",scopeRootPath:t,root:o,version:l,etag:u.etag,enable:!i,bundle:{endpoint:`${E()}/providers/${encodeURIComponent(e)}/plugin`},transport:{kind:"http",endpoint:E()},accept:a(p=>re(e,void 0,p),"accept")})}catch(p){D(e,void 0,p);const U=new c("not_found",`provider "${e}" served an invalid bundle: ${p instanceof Error?p.message:String(p)}`,{param:"provider"});throw I.add(U),U}try{await G(async p=>await L(p))}catch(p){m({level:"error",event:"daemon.providers.docs_reconcile_failed",fields:{provider:e},error:p})}return m({level:"info",event:"daemon.providers.bundle_installed",fields:{provider:e,version:l,replaced:i}}),y.delete(b(e)),i?"updated":"installed"},{timeoutMs:X,timeoutError:a(()=>new c("provider_unavailable",`timed out waiting for another process replacing plugin "${e}"`),"timeoutError")})}catch(o){throw h(e)===void 0&&y.set(b(e),{status:"install_failed",error:Se(o)}),o instanceof c?o:(m({level:"error",event:"daemon.providers.bundle_install_failed",fields:{provider:e},error:o}),Ie(e))}}a(N,"refreshInstalled");async function en(e){B(e),h(e)===void 0&&await N(e,!1,!0)}a(en,"ensureProviderBundle");async function nn(e,n){return B(e),n.version!==void 0&&h(e)?.provider.major!==n.version?O(e,n.version,n.conditional):N(e,n.conditional)}a(nn,"refreshProviderBundle");async function ae(e,n,r){const{validatePluginArchive:t}=await oe(),o=await t(r);if(o.bundle===void 0)throw new M(`provider "${e}" major ${n} bundle is invalid: ${o.issues.map(i=>i.message).join("; ")}`,o.issues);const s=re(e,n,o.bundle);if(s!==void 0)throw new M(`provider "${e}" major ${n} bundle is invalid: ${s}`,[]);if(o.bundle.transport===void 0)throw new M(`provider "${e}" major ${n} bundle declares no transport`,[]);return o.bundle}a(ae,"validateArchive");function Me(e){T(e),x(d(e,"retired"),`${new Date().toISOString()}
2
+ `),$(d(e,"bundle.tar"),{force:!0}),$(d(e,"etag"),{force:!0})}a(Me,"retire");function ie(e,n){return new c("provider_version_retired",`provider "${e}" major ${n} is retired`,{param:"version"})}a(ie,"retiredError");async function O(e,n,r){const t=ee(e,n),o=d(t,"bundle.tar"),s=g(o),i=s&&r&&g(d(t,"etag"))?S(d(t,"etag"),"utf8"):void 0,f=await ne(e,{version:n,...i!==void 0?{ifNoneMatch:i}:{}});if(f.status===304)return"unchanged";if(f.status===410)throw Me(t),m({level:"info",event:"daemon.providers.major_retired",fields:{provider:e,major:n}}),ie(e,n);if(f.status===404)throw new c("not_found",`provider "${e}" never served major ${n}`,{param:"version"});if(f.status==="failed")throw new c("provider_unavailable",`provider "${e}" major ${n} bundle fetch failed: ${f.message}`,{cause:f.cause});try{await ae(e,n,f.raw)}catch(l){D(e,n,l);const w=new c(s?"provider_unavailable":"not_found",l instanceof Error?l.message:String(l),{param:"version"});throw I.add(w),w}T(t),$(d(t,"retired"),{force:!0});const u=s&&Buffer.from(f.raw).equals(S(o));return u||x(o,f.raw),f.etag!==void 0?x(d(t,"etag"),f.etag):$(d(t,"etag"),{force:!0}),u?"unchanged":s?"updated":"installed"}a(O,"refreshPinned");function ke(){const e=[],n=R();if(!g(n))return e;for(const r of W(n)){if(!Q.test(r))continue;let t;try{t=W(d(n,r))}catch{continue}for(const o of t){const s=/^v([1-9][0-9]*)$/.exec(o);s&&g(d(n,r,o,"bundle.tar"))&&e.push([r,Number(s[1])])}}return e}a(ke,"cachedMajors");function xe(e){const n=de(e,{transport:"http",reservedCoreNames:new Set});if(n.manifest===void 0)throw new c("not_found","the provider bundle's commands.json no longer validates");return n.manifest}a(xe,"readCommands");const _=new Map,H=new Map;function Te(e,n){const r=k(n),t=`${r.ino}:${r.mtimeMs}:${r.size}`,o=H.get(e);if(o?.stamp===t)return o.commands;const s=xe(JSON.parse(S(n,"utf8")));return H.set(e,{stamp:t,commands:s}),s}a(Te,"installedCommands");async function rn(e,n){B(e);const r=h(e);if(n===void 0||r?.provider.major===n){if(r===void 0)throw new c("not_found",`provider "${e}" has no installed bundle`,{param:"provider"});const l=v(e),w=Te(e,d(l,"commands.json"));return{id:e,major:r.provider.major,provider:r.provider,commands:w,transport:r.transport,source:"installed",root:l}}if(!Number.isInteger(n)||n<1)throw new c("invalid_request","version must be an integer of at least 1",{param:"version"});const t=ee(e,n);if(g(d(t,"retired")))throw ie(e,n);const o=d(t,"bundle.tar");g(o)||await O(e,n,!1);const s=`${e}/${n}`,i=k(o),f=`${i.mtimeMs}:${i.size}`;let u=_.get(s)?.stamp===f?_.get(s).bundle:void 0;if(u===void 0){try{u=await ae(e,n,new Uint8Array(S(o)))}catch(l){throw D(e,n,l),new c("not_found",`provider "${e}" has no valid bundle for major ${n}`,{param:"version"})}_.set(s,{stamp:f,bundle:u})}return{id:e,major:n,provider:u.provider,commands:u.commands,transport:u.transport.kind==="machine"?{kind:"machine"}:{kind:"http",endpoint:u.transport.endpoint},source:"pinned"}}a(rn,"resolveProviderBundle");let P=null,F=!1;function Ce(e,n){return e?.provider?.id===n&&e.bundle?.endpoint===`${E()}/providers/${encodeURIComponent(n)}/plugin`}a(Ce,"isDirectoryBundle");async function se(e){return Y(await j()).includes(e)}a(se,"grantNames");async function je(e){await Z(J(K(),e),async()=>{if(!(await se(e)||!Ce(C(v(e)),e))){$(v(e),{recursive:!0,force:!0}),await me("user",n=>{delete n.plugins[e]}),await ve("user",n=>{delete n.plugins[e]}),$(d(R(),e),{recursive:!0,force:!0}),H.delete(e),y.delete(b(e));for(const n of[..._.keys()])n.startsWith(`${e}/`)&&_.delete(n);try{await G(async n=>await L(n))}catch(n){m({level:"error",event:"daemon.providers.docs_reconcile_failed",fields:{provider:e},error:n})}m({level:"info",event:"daemon.providers.bundle_uninstalled",fields:{provider:e}})}},{timeoutMs:X,timeoutError:a(()=>new c("provider_unavailable",`timed out waiting for another process replacing plugin "${e}"`),"timeoutError")})}a(je,"uninstallProvider");async function Ae(){if(!(await j()).every(e=>e.status!=="active")){for(const e of be("user"))if(!(e.manifest.provider===void 0||await se(e.name)))try{await je(e.name)}catch(n){m({level:"error",event:"daemon.providers.bundle_uninstall_failed",fields:{provider:e.name},error:n})}}}a(Ae,"uninstallDisconnected");async function Re(){if(!q("user").runtime?.issuer)return;const e=Y(await j());for(const n of e)try{await N(n,!0)}catch(r){r instanceof Object&&I.has(r)||te(n,void 0,r)}await Ae();for(const[n,r]of ke())try{await O(n,r,!0)}catch(t){if(t instanceof c&&t.code==="provider_version_retired"||t instanceof Object&&I.has(t))continue;te(n,r,t)}}a(Re,"syncOnce");function tn(){return P!==null?(F=!0,P):(P=(async()=>{try{do F=!1,await Re();while(F)}finally{P=null}})(),P)}a(tn,"syncProviderBundles");export{en as ensureProviderBundle,Y as providerIdsFromGrants,Ee as providerInstallState,nn as refreshProviderBundle,rn as resolveProviderBundle,tn as syncProviderBundles,Ie as unavailableProviderError};
@@ -1,4 +1,4 @@
1
- import type { ManifestHttpLeaf, ManifestBranch, ManifestRootEntry } from '../../api/plugin-manifest-schema.js';
1
+ import type { ManifestHttpLeaf } from '../../api/plugin-manifest-schema.js';
2
2
  import type { ValidatedCommandManifest } from '../../api/command-manifest/manifest.js';
3
3
  import type { ProviderCaller, ProviderCallInput, ProviderRequest } from '../../daemon/api/handlers/providers.js';
4
4
  import { ProviderError } from './errors.js';
@@ -10,39 +10,8 @@ export interface ProviderLeaf {
10
10
  hidden: boolean;
11
11
  }
12
12
  export declare function providerLeaves(commands: ValidatedCommandManifest): ProviderLeaf[];
13
- export type ProviderHelpLeaf = Pick<ManifestHttpLeaf, 'kind' | 'name' | 'description' | 'whenToUse' | 'tier' | 'summary' | 'params' | 'output' | 'effects' | 'group'>;
14
- export interface ProviderHelpBranch extends Pick<ManifestBranch<ManifestHttpLeaf>, 'kind' | 'name' | 'description' | 'whenToUse' | 'tier' | 'summary' | 'model'> {
15
- rootEntry?: ManifestRootEntry;
16
- children: Array<ProviderHelpBranch | ProviderHelpLeaf>;
17
- }
18
- export interface ProviderToolDescription {
19
- provider: string;
20
- status: 'available';
21
- major: number;
22
- display_name: string;
23
- /** `machine`: calls go to one of the account's device machines, so its leaves take `--machine`. */
24
- transport?: 'http' | 'machine';
25
- groups: Array<{
26
- group: string;
27
- leaves: Array<{
28
- tool: string;
29
- description: string;
30
- summary: string;
31
- params: ManifestHttpLeaf['params'];
32
- output: ManifestHttpLeaf['output'];
33
- }>;
34
- }>;
35
- /** Help-only tree of every grouped leaf, including groups the caller lacks (`groups` is only the caller's). Never contains REST mappings, endpoints, credentials, or executable paths. */
36
- commands: ProviderHelpBranch[];
37
- }
38
- export interface UnavailableProviderToolDescription {
39
- provider: string;
40
- display_name: string;
41
- status: 'installing' | 'install_failed';
42
- error?: string;
43
- groups: [];
44
- commands: [];
45
- }
13
+ export type { ProviderHelpLeaf, ProviderHelpBranch, ProviderToolDescription, UnavailableProviderToolDescription } from './description.js';
14
+ import type { ProviderToolDescription } from './description.js';
46
15
  /** R8's broker help filter consumes groups[].leaves[].tool. */
47
16
  export declare function providerTools(caller: ProviderCaller, id: string): Promise<ProviderToolDescription>;
48
17
  export interface ProviderCallResult {
@@ -0,0 +1,34 @@
1
+ import type { ManifestHttpLeaf, ManifestBranch, ManifestRootEntry } from '../../api/plugin-manifest-schema.js';
2
+ export type ProviderHelpLeaf = Pick<ManifestHttpLeaf, 'kind' | 'name' | 'description' | 'whenToUse' | 'tier' | 'summary' | 'params' | 'output' | 'effects' | 'group'>;
3
+ export interface ProviderHelpBranch extends Pick<ManifestBranch<ManifestHttpLeaf>, 'kind' | 'name' | 'description' | 'whenToUse' | 'tier' | 'summary' | 'model'> {
4
+ rootEntry?: ManifestRootEntry;
5
+ children: Array<ProviderHelpBranch | ProviderHelpLeaf>;
6
+ }
7
+ export interface ProviderToolDescription {
8
+ provider: string;
9
+ status: 'available';
10
+ major: number;
11
+ display_name: string;
12
+ /** `machine`: calls go to one of the account's device machines, so its leaves take `--machine`. */
13
+ transport?: 'http' | 'machine';
14
+ groups: Array<{
15
+ group: string;
16
+ leaves: Array<{
17
+ tool: string;
18
+ description: string;
19
+ summary: string;
20
+ params: ManifestHttpLeaf['params'];
21
+ output: ManifestHttpLeaf['output'];
22
+ }>;
23
+ }>;
24
+ /** Help-only tree of every grouped leaf, including groups the caller lacks (`groups` is only the caller's). Never contains REST mappings, endpoints, credentials, or executable paths. */
25
+ commands: ProviderHelpBranch[];
26
+ }
27
+ export interface UnavailableProviderToolDescription {
28
+ provider: string;
29
+ display_name: string;
30
+ status: 'installing' | 'install_failed';
31
+ error?: string;
32
+ groups: [];
33
+ commands: [];
34
+ }
File without changes
@@ -32,23 +32,23 @@ export declare function storeToken(key: string, token: CachedToken, epoch?: numb
32
32
  export declare function discardFile(key: string): void;
33
33
  /** Discard every cached token for (`sub`, `grantee`). Returns how many went. */
34
34
  export declare function discardFor(sub: string, grantee: string, nowMs?: number): number;
35
- /** The (`sub`, `grantee`) pairs whose grant a sync revoked, removed, dropped,
36
- * replaced, or whose resolved scope set or inference endpoint it changed. */
37
- export declare function changedGrantPairs(before: readonly GrantRecord[], after: readonly GrantRecord[]): Array<{
35
+ /** The grant-change hook (D3-TOK-20, CRD-16), called with the re-read state of one grant whose row changed: discard every cached
36
+ * token of its (`sub`, `grantee`), every token of `sub` naming a provider that no active grant of `sub` (`subGrants`, all of
37
+ * them) resolves, and, when the changed grant is a connection grant (`app:<provider>`) that is not active, every token of `sub`
38
+ * naming that provider whatever its grantee — a person's own calls mint as (`sub`, `sub`), a pair a connection grant never names.
39
+ * It is idempotent, so a repeated or replayed notification discards nothing more. */
40
+ export declare function discardTokensForGrant(changed: {
38
41
  sub: string;
39
42
  grantee: string;
40
- }>;
41
- /** The (`sub`, provider) keys a sync stopped serving: a provider whose scopes
42
- * the active grants resolved before and no longer do, or whose connection
43
- * grant (`sub` to `app:<provider>`) was active before and is not now, even
44
- * while another grant still names its scopes. */
45
- export declare function droppedProviders(before: readonly GrantRecord[], after: readonly GrantRecord[]): string[];
46
- /** The grant-sync hook (D3-TOK-20, CRD-16): discard every cached token of each
47
- * changed grant's (`sub`, `grantee`) and of each (`sub`, provider) the sync
48
- * stopped resolving (whatever the token's grantee — a person's own calls mint
49
- * as (`sub`, `sub`)), and prune expired files. */
50
- export declare function discardChangedGrantTokens(before: readonly GrantRecord[], after: readonly GrantRecord[], nowMs?: number): {
43
+ active: boolean;
44
+ }, subGrants: readonly GrantRecord[], nowMs?: number): {
51
45
  pairs: number;
52
46
  providers: number;
53
47
  tokens: number;
54
48
  };
49
+ /** The catch-up form of `discardTokensForGrant`, for a changed grant whose row is gone (its `sub` and `grantee` unknown) and for
50
+ * the pass after the listen connection restarted: discard every token of an `app:` (`sub`, `grantee`) with no active grant, and
51
+ * every token naming a provider that no active grant of its `sub` resolves and that is not a connected `app:<provider>`. */
52
+ export declare function discardOrphanedTokens(grants: readonly GrantRecord[], nowMs?: number): {
53
+ tokens: number;
54
+ };
@@ -1 +1 @@
1
- var j=Object.defineProperty;var o=(t,e)=>j(t,"name",{value:e,configurable:!0});import{createHash as A}from"node:crypto";import{mkdirSync as M,readdirSync as E,readFileSync as F,rmSync as d}from"node:fs";import{join as h}from"node:path";import{crtrHome as D}from"../canvas/paths.js";import{atomicWriteJson as P}from"../fs-utils.js";const G=30;function l(){return h(D(),"secrets","outbound-tokens")}o(l,"tokenCacheDir");function U(t){return JSON.stringify([t.audience,t.sub,t.grantee,t.initiating_app,[...new Set(t.scope)].sort()])}o(U,"cacheKey");function m(t){return h(l(),`${A("sha256").update(t).digest("hex")}.json`)}o(m,"fileFor");function g(t){try{const e=JSON.parse(t);if(!Array.isArray(e)||typeof e[1]!="string"||typeof e[2]!="string")return null;const r=(Array.isArray(e[4])?e[4]:[]).flatMap(s=>typeof s=="string"?[v(s)]:[]).filter(s=>s!==null);return{sub:e[1],grantee:e[2],providers:[...new Set(r)]}}catch{return null}}o(g,"partsOf");function B(t){const e=g(t);return e===null?null:p(e.sub,e.grantee)}o(B,"pairOf");function p(t,e){return JSON.stringify([t,e])}o(p,"pairKey");function y(t,e){return JSON.stringify([t,e])}o(y,"providerKey");function v(t){const e=t.indexOf(":");return e>0?t.slice(0,e):null}o(v,"providerOf");function x(t){try{const e=JSON.parse(F(t,"utf8"));if(typeof e.key!="string"||typeof e.access_token!="string"||typeof e.jti!="string"||typeof e.exp!="number")return null;const n=typeof e.payer=="string"&&e.payer?e.payer:g(e.key)?.sub??"";return n?{...e,payer:n}:null}catch{return null}}o(x,"readFile");function K(t,e){return e<(t.exp-G)*1e3}o(K,"usable");function L(t,e=Date.now()){const n=m(t),r=x(n);return!r||r.key!==t||!K(r,e)?(d(n,{force:!0}),null):{access_token:r.access_token,jti:r.jti,exp:r.exp,payer:r.payer}}o(L,"cachedToken");const f=new Map,S=new Map;function w(t){const e=g(t);return e===null?0:(f.get(p(e.sub,e.grantee))??0)+e.providers.reduce((n,r)=>n+(S.get(y(e.sub,r))??0),0)}o(w,"discardEpoch");function Q(t,e,n=w(t)){return w(t)!==n?!1:(M(l(),{recursive:!0,mode:448}),P(m(t),{key:t,...e},{mode:384}),!0)}o(Q,"storeToken");function V(t){d(m(t),{force:!0})}o(V,"discardFile");function b(t,e,n){let r;try{r=E(l())}catch{return 0}let s=0;for(const c of r){if(!c.endsWith(".json"))continue;const i=h(l(),c),a=x(i),u=a?g(a.key):null,N=u!==null&&(t.has(p(u.sub,u.grantee))||u.providers.some(_=>e.has(y(u.sub,_))));a&&N?(d(i,{force:!0}),s++):(!a||n>=a.exp*1e3)&&d(i,{force:!0})}return s}o(b,"sweep");function X(t,e,n=Date.now()){const r=p(t,e);return f.set(r,(f.get(r)??0)+1),b(new Set([r]),new Set,n)}o(X,"discardFor");function O(t){const e=new Map;for(const n of t){const r=n.resolved_scopes.map(({scope:c,mode:i})=>`${i} ${c}`).sort(),s=p(n.sub,n.grantee);e.set(s,[...e.get(s)??[],JSON.stringify([n.id,n.status,r,n.inference_endpoint??null])])}return new Map([...e].map(([n,r])=>[n,JSON.stringify(r.sort())]))}o(O,"grantStates");function T(t,e){const n=O(t),r=O(e),s=[];for(const[c,i]of n){if(r.get(c)===i)continue;const[a,u]=JSON.parse(c);s.push({sub:a,grantee:u})}return s}o(T,"changedGrantPairs");function k(t){const e=new Set;for(const n of t)if(n.status==="active")for(const{scope:r}of n.resolved_scopes){const s=v(r);s!==null&&e.add(y(n.sub,s))}return e}o(k,"resolvedProviders");function J(t){return new Set(t.filter(e=>e.status==="active"&&e.grantee.startsWith("app:")).map(e=>p(e.sub,e.grantee)))}o(J,"connectedApps");function W(t,e){const n=k(e),r=new Set([...k(t)].filter(c=>!n.has(c))),s=J(e);for(const c of J(t)){if(s.has(c))continue;const[i,a]=JSON.parse(c);r.add(y(i,a.slice(4)))}return[...r]}o(W,"droppedProviders");function Y(t,e,n=Date.now()){const r=T(t,e),s=new Set(r.map(({sub:i,grantee:a})=>p(i,a))),c=new Set(W(t,e));for(const i of s)f.set(i,(f.get(i)??0)+1);for(const i of c)S.set(i,(S.get(i)??0)+1);return{pairs:s.size,providers:c.size,tokens:b(s,c,n)}}o(Y,"discardChangedGrantTokens");export{G as REUSE_MARGIN_S,U as cacheKey,L as cachedToken,T as changedGrantPairs,Y as discardChangedGrantTokens,w as discardEpoch,V as discardFile,X as discardFor,W as droppedProviders,Q as storeToken,l as tokenCacheDir};
1
+ var F=Object.defineProperty;var s=(e,t)=>F(e,"name",{value:t,configurable:!0});import{createHash as j}from"node:crypto";import{mkdirSync as J,readdirSync as M,readFileSync as N,rmSync as v}from"node:fs";import{join as g}from"node:path";import{crtrHome as A}from"../canvas/paths.js";import{atomicWriteJson as D}from"../fs-utils.js";const E=30;function b(){return g(A(),"secrets","outbound-tokens")}s(b,"tokenCacheDir");function C(e){return JSON.stringify([e.audience,e.sub,e.grantee,e.initiating_app,[...new Set(e.scope)].sort()])}s(C,"cacheKey");function m(e){return g(b(),`${j("sha256").update(e).digest("hex")}.json`)}s(m,"fileFor");function S(e){try{const t=JSON.parse(e);if(!Array.isArray(t)||typeof t[1]!="string"||typeof t[2]!="string")return null;const o=(Array.isArray(t[4])?t[4]:[]).flatMap(i=>typeof i=="string"?[x(i)]:[]).filter(i=>i!==null);return{sub:t[1],grantee:t[2],providers:[...new Set(o)]}}catch{return null}}s(S,"partsOf");function f(e,t){return JSON.stringify([e,t])}s(f,"pairKey");function w(e,t){return JSON.stringify([e,t])}s(w,"providerKey");function x(e){const t=e.indexOf(":");return t>0?e.slice(0,t):null}s(x,"providerOf");function k(e){try{const t=JSON.parse(N(e,"utf8"));if(typeof t.key!="string"||typeof t.access_token!="string"||typeof t.jti!="string"||typeof t.exp!="number")return null;const n=typeof t.payer=="string"&&t.payer?t.payer:S(t.key)?.sub??"";return n?{...t,payer:n}:null}catch{return null}}s(k,"readFile");function T(e,t){return t<(e.exp-E)*1e3}s(T,"usable");function I(e,t=Date.now()){const n=m(e),o=k(n);return!o||o.key!==e||!T(o,t)?(v(n,{force:!0}),null):{access_token:o.access_token,jti:o.jti,exp:o.exp,payer:o.payer}}s(I,"cachedToken");const l=new Map,d=new Map;function O(e){const t=S(e);return t===null?0:(l.get(f(t.sub,t.grantee))??0)+(d.get(t.sub)??0)}s(O,"discardEpoch");function U(e,t,n=O(e)){return O(e)!==n?!1:(J(b(),{recursive:!0,mode:448}),D(m(e),{key:e,...t},{mode:384}),!0)}s(U,"storeToken");function $(e){v(m(e),{force:!0})}s($,"discardFile");function h(e,t){let n;try{n=M(b())}catch{return 0}let o=0;for(const i of n){if(!i.endsWith(".json"))continue;const a=g(b(),i),u=k(a),r=u?S(u.key):null;u&&r!==null&&e(r)?(v(a,{force:!0}),o++):(!u||t>=u.exp*1e3)&&v(a,{force:!0})}return o}s(h,"sweep");function B(e,t,n=Date.now()){const o=f(e,t);return l.set(o,(l.get(o)??0)+1),h(i=>i.sub===e&&i.grantee===t,n)}s(B,"discardFor");function W(e){const t=new Set;for(const n of e)if(n.status==="active")for(const{scope:o}of n.resolved_scopes){const i=x(o);i!==null&&t.add(i)}return t}s(W,"resolvedProviders");function L(e,t,n=Date.now()){const o=W(t.filter(c=>c.sub===e.sub)),i=e.grantee.startsWith("app:")&&!e.active?e.grantee.slice(4):null,a=s(c=>!o.has(c)||c===i,"unserved"),u=f(e.sub,e.grantee);l.set(u,(l.get(u)??0)+1),d.set(e.sub,(d.get(e.sub)??0)+1);const r=new Set,p=h(c=>{if(c.sub!==e.sub)return!1;const y=c.providers.filter(a);for(const _ of y)r.add(_);return c.grantee===e.grantee||y.length>0},n);return{pairs:1,providers:r.size,tokens:p}}s(L,"discardTokensForGrant");function Q(e,t=Date.now()){const n=e.filter(r=>r.status==="active"),o=new Set(n.map(r=>f(r.sub,r.grantee))),i=new Set(n.flatMap(r=>r.resolved_scopes.flatMap(({scope:p})=>{const c=x(p);return c===null?[]:[w(r.sub,c)]}))),a=new Set,u=h(r=>{const p=r.grantee.startsWith("app:")&&!o.has(f(r.sub,r.grantee)),c=r.providers.some(y=>!i.has(w(r.sub,y)));return(p||c)&&a.add(r.sub),p||c},t);for(const r of a)d.set(r,(d.get(r)??0)+1);return{tokens:u}}s(Q,"discardOrphanedTokens");export{E as REUSE_MARGIN_S,C as cacheKey,I as cachedToken,O as discardEpoch,$ as discardFile,B as discardFor,Q as discardOrphanedTokens,L as discardTokensForGrant,U as storeToken,b as tokenCacheDir};
@@ -1 +1 @@
1
- var S=Object.defineProperty;var d=(e,o)=>S(e,"name",{value:o,configurable:!0});import{randomUUID as v}from"node:crypto";import{conversationIdFromPath as w,conversationStore as u,ConversationNotFoundError as p}from"../conversation-store/index.js";import{basename as F,isAbsolute as c}from"node:path";import{BrokerClient as x}from"../broker-client/index.js";import{deleteNode as M,getNode as g}from"../canvas/index.js";import{expandModelCandidates as C,selectInitialModelRoute as E}from"../model-routes.js";import{buildLaunchSpec as L}from"../runtime/launch.js";import{openModelRegistry as B}from"../runtime/model-registry.js";import{isBrokerLive as O}from"../runtime/model-swap.js";import{spawnNode as R}from"../runtime/nodes.js";import{SessionManager as D}from"../runtime/broker-sdk.js";import{isReviewBoundary as P}from"../runtime/session-visibility.js";import{forkNodeLedger as $}from"../runtime/ledger.js";import{ReviewOperationError as b}from"./types.js";const I=/^[^/\s:]+\/[^/\s:]+:(?:off|minimal|low|medium|high|xhigh|max)$/,q=100;function N(e){return new b("review_origin_missing","review origin was not found",{origin_node_id:e})}d(N,"originMissing");function f(e,o,r={}){return new b("review_origin_unforkable","review origin has no forkable exact session",{origin_node_id:e,reason:o,...r})}d(f,"originUnforkable");async function k(e,o,r){const i=w(o.sourceFile);if(!c(o.sourceFile)||i===null||i!==o.sourceSessionId||o.leafId===null||o.leafId==="")throw f(e,"no_forkable_session");try{await u().header(i)}catch(n){throw n instanceof p?f(e,"no_forkable_session"):n}if(o.modelSpec===null||!I.test(o.modelSpec))throw f(e,"model_unresolvable");const t=E({kind:"exact",spec:o.modelSpec},r??await B(),{cwd:o.cwd,profileId:o.profileId});if(t.selected===void 0)throw f(e,"model_unresolvable",{model_reason:t.rejected[0]?.reason});return{sourceFile:o.sourceFile,sourceSessionId:o.sourceSessionId,leafId:o.leafId,modelSpec:o.modelSpec}}d(k,"validateCapture");function U(e){return new Promise(async(o,r)=>{const i=new x(e);let t=!1;function n(s){t||(t=!0,i.close(),s())}d(n,"finish"),i.on("error",s=>n(()=>r(s))),i.on("close",()=>n(()=>r(new Error("origin broker closed before fork coordinates were read")))),i.on("connect",()=>{i.send({type:"hello",role:"observer",client_id:v()}),i.request({type:"get_human_fork_coordinates"}).then(s=>{if(s.kind!=="human_fork_coordinates"){n(()=>r(new Error("origin broker returned an unexpected fork-coordinate response")));return}n(()=>o(s))}).catch(s=>n(()=>r(s)))}),i.connect()})}d(U,"captureLiveOrigin");async function re(e,o={}){const r=await g(e);if(r===null)throw N(e);if(O(r)){const a=await U(e);return k(e,{...a,cwd:r.cwd,profileId:r.profile_id},o.registry)}const i=typeof r.pi_session_file=="string"?r.pi_session_file:"";let t="",n=null,s=null;const h=w(i);if(c(i)&&h!==null)try{const a=await u().read(h),m=D.inMemory(a.header.cwd,void 0,[a.header,...a.entries]);t=m.getSessionId(),n=m.getLeafId();const _=r.launch?.model,l=typeof _=="string"?C({kind:"exact",spec:_},r.cwd,r.profile_id)[0]:void 0;if(l!==void 0){const y=l.thinkingLevel??(m.buildSessionContext().thinkingLevel||"off");s=`${l.providerId}/${l.modelId}:${y}`}}catch(a){if(!(a instanceof p))throw a}return k(e,{sourceFile:i,sourceSessionId:t,leafId:n,modelSpec:s,cwd:r.cwd,profileId:r.profile_id},o.registry)}d(re,"captureOrigin");async function ie(e){if(!c(e.branchFile)||!c(e.targetFile))throw new Error("review companion requires absolute branch and target paths");if(!I.test(e.modelSpec))throw new Error("review companion requires an exact model spec");const{launch:o}=L("review/companion","base",{lifecycle:"resident",hasManager:!1,model:e.modelSpec,modelExact:!0,cwd:e.cwd,profileId:e.profileId}),r=await R({nodeId:e.nodeId,kind:"review/companion",mode:"base",lifecycle:"resident",cwd:e.cwd,profile_id:e.profileId,parent:e.originNodeId,creator:e.originNodeId,subscribe:!1,forkFrom:e.branchFile,forkSourceFile:e.branchFile,modelOverride:e.modelSpec,reviewBinding:{review_id:e.reviewId,origin_node_id:e.originNodeId,branch_file:e.branchFile,target_file:e.targetFile},name:`review ${F(e.targetFile)}`,launch:o});try{await $(r.node_id,e.originNodeId)}catch(i){throw await M(r.node_id),i}}d(ie,"spawnReviewCompanion");async function A(e){const o=await g(e),r=o?.review_binding,i=o?.pi_session_file,t=typeof i=="string"?w(i):null;if(r==null||o?.pi_session_id==null||t===null)return!1;try{return(await u().read(t)).entries.some(n=>P(n,r.review_id))}catch(n){if(n instanceof p)return!1;throw n}}d(A,"isReviewCompanionBound");async function ne(e,o){const r=Date.now()+Math.max(0,o);for(;;){if(await A(e))return!0;const i=r-Date.now();if(i<=0)return!1;await new Promise(t=>setTimeout(t,Math.min(q,i)))}}d(ne,"awaitCompanionBind");export{ne as awaitCompanionBind,re as captureOrigin,A as isReviewCompanionBound,ie as spawnReviewCompanion};
1
+ var S=Object.defineProperty;var d=(e,o)=>S(e,"name",{value:o,configurable:!0});import{randomUUID as v}from"node:crypto";import{conversationIdFromPath as w,conversationStore as u,ConversationNotFoundError as p}from"../conversation-store/index.js";import{basename as F,isAbsolute as c}from"node:path";import{BrokerClient as x}from"../broker-client/index.js";import{deleteNode as M,getNode as g}from"../canvas/index.js";import{expandModelCandidates as C}from"../model-routes.js";import{selectInitialModelRoute as E}from"../model-routes-pool.js";import{buildLaunchSpec as L}from"../runtime/launch.js";import{openModelRegistry as B}from"../runtime/model-registry.js";import{isBrokerLive as O}from"../runtime/model-swap.js";import{spawnNode as R}from"../runtime/nodes.js";import{SessionManager as D}from"../runtime/broker-sdk.js";import{isReviewBoundary as P}from"../runtime/session-visibility.js";import{forkNodeLedger as $}from"../runtime/ledger.js";import{ReviewOperationError as b}from"./types.js";const I=/^[^/\s:]+\/[^/\s:]+:(?:off|minimal|low|medium|high|xhigh|max)$/,q=100;function N(e){return new b("review_origin_missing","review origin was not found",{origin_node_id:e})}d(N,"originMissing");function f(e,o,r={}){return new b("review_origin_unforkable","review origin has no forkable exact session",{origin_node_id:e,reason:o,...r})}d(f,"originUnforkable");async function k(e,o,r){const i=w(o.sourceFile);if(!c(o.sourceFile)||i===null||i!==o.sourceSessionId||o.leafId===null||o.leafId==="")throw f(e,"no_forkable_session");try{await u().header(i)}catch(n){throw n instanceof p?f(e,"no_forkable_session"):n}if(o.modelSpec===null||!I.test(o.modelSpec))throw f(e,"model_unresolvable");const t=await E({kind:"exact",spec:o.modelSpec},r??await B(),{cwd:o.cwd,profileId:o.profileId});if(t.selected===void 0)throw f(e,"model_unresolvable",{model_reason:t.rejected[0]?.reason});return{sourceFile:o.sourceFile,sourceSessionId:o.sourceSessionId,leafId:o.leafId,modelSpec:o.modelSpec}}d(k,"validateCapture");function U(e){return new Promise(async(o,r)=>{const i=new x(e);let t=!1;function n(s){t||(t=!0,i.close(),s())}d(n,"finish"),i.on("error",s=>n(()=>r(s))),i.on("close",()=>n(()=>r(new Error("origin broker closed before fork coordinates were read")))),i.on("connect",()=>{i.send({type:"hello",role:"observer",client_id:v()}),i.request({type:"get_human_fork_coordinates"}).then(s=>{if(s.kind!=="human_fork_coordinates"){n(()=>r(new Error("origin broker returned an unexpected fork-coordinate response")));return}n(()=>o(s))}).catch(s=>n(()=>r(s)))}),i.connect()})}d(U,"captureLiveOrigin");async function ie(e,o={}){const r=await g(e);if(r===null)throw N(e);if(O(r)){const a=await U(e);return k(e,{...a,cwd:r.cwd,profileId:r.profile_id},o.registry)}const i=typeof r.pi_session_file=="string"?r.pi_session_file:"";let t="",n=null,s=null;const h=w(i);if(c(i)&&h!==null)try{const a=await u().read(h),m=D.inMemory(a.header.cwd,void 0,[a.header,...a.entries]);t=m.getSessionId(),n=m.getLeafId();const _=r.launch?.model,l=typeof _=="string"?(await C({kind:"exact",spec:_},r.cwd,r.profile_id))[0]:void 0;if(l!==void 0){const y=l.thinkingLevel??(m.buildSessionContext().thinkingLevel||"off");s=`${l.providerId}/${l.modelId}:${y}`}}catch(a){if(!(a instanceof p))throw a}return k(e,{sourceFile:i,sourceSessionId:t,leafId:n,modelSpec:s,cwd:r.cwd,profileId:r.profile_id},o.registry)}d(ie,"captureOrigin");async function ne(e){if(!c(e.branchFile)||!c(e.targetFile))throw new Error("review companion requires absolute branch and target paths");if(!I.test(e.modelSpec))throw new Error("review companion requires an exact model spec");const{launch:o}=L("review/companion","base",{lifecycle:"resident",hasManager:!1,model:e.modelSpec,modelExact:!0,cwd:e.cwd,profileId:e.profileId}),r=await R({nodeId:e.nodeId,kind:"review/companion",mode:"base",lifecycle:"resident",cwd:e.cwd,profile_id:e.profileId,parent:e.originNodeId,creator:e.originNodeId,subscribe:!1,forkFrom:e.branchFile,forkSourceFile:e.branchFile,modelOverride:e.modelSpec,reviewBinding:{review_id:e.reviewId,origin_node_id:e.originNodeId,branch_file:e.branchFile,target_file:e.targetFile},name:`review ${F(e.targetFile)}`,launch:o});try{await $(r.node_id,e.originNodeId)}catch(i){throw await M(r.node_id),i}}d(ne,"spawnReviewCompanion");async function A(e){const o=await g(e),r=o?.review_binding,i=o?.pi_session_file,t=typeof i=="string"?w(i):null;if(r==null||o?.pi_session_id==null||t===null)return!1;try{return(await u().read(t)).entries.some(n=>P(n,r.review_id))}catch(n){if(n instanceof p)return!1;throw n}}d(A,"isReviewCompanionBound");async function te(e,o){const r=Date.now()+Math.max(0,o);for(;;){if(await A(e))return!0;const i=r-Date.now();if(i<=0)return!1;await new Promise(t=>setTimeout(t,Math.min(q,i)))}}d(te,"awaitCompanionBind");export{te as awaitCompanionBind,ie as captureOrigin,A as isReviewCompanionBound,ne as spawnReviewCompanion};
@@ -8,4 +8,4 @@ export declare function toolCallSummary(args: unknown): string | null;
8
8
  * state `run.trace` `in_progress_message` reads) says what the model is
9
9
  * streaming. Null unless the run is `running`. `streaming` is that open
10
10
  * message's newest block; a test passes it in place of a live broker. */
11
- export declare function runActivity(runId: string, status: string, streaming?: () => OpenAssistantBlock | null): Promise<RunActivityDTO | null>;
11
+ export declare function runActivity(runId: string, status: string, streaming?: () => Promise<OpenAssistantBlock | null>): Promise<RunActivityDTO | null>;
@@ -1,5 +1,5 @@
1
1
  var d=Object.defineProperty;var l=(t,n)=>d(t,"name",{value:n,configurable:!0});import{openDb as _}from"../canvas/db.js";import{openAssistantBlock as f}from"../../daemon/runs/observer.js";import{SUBMIT_RESULT_TOOL as p}from"../runtime/structured-output.js";const m=120;function y(t){if(!t||typeof t!="object")return null;const n=t,s=[n.command,n.file_path,n.path].find(r=>typeof r=="string"&&r.trim()!=="");if(s===void 0)return null;const o=s.trim().split(`
2
2
  `)[0].trim();return o.length>m?`${o.slice(0,m-1)}\u2026`:o}l(y,"toolCallSummary");async function g(t,n,s=()=>f(t)){if(n!=="running")return null;const o=await _(),r=await o.prepare(`SELECT type, sequence_number FROM run_events WHERE run_id = ? AND node_id = ?
3
- AND type IN ('node.turn.started', 'node.turn.completed') ORDER BY sequence_number DESC LIMIT 1`).get(t,t);if(!r)return{phase:"starting"};if(r.type==="node.turn.completed")return{phase:"between_turns"};const i=s();if(i?.kind==="text")return{phase:"writing"};if(i?.kind==="tool_call")return i.name===p?{phase:"submitting_result"}:{phase:"tool",tool:{name:i.name,summary:null}};if(i===null){const a=(await o.prepare(`SELECT type, body_json, sequence_number FROM run_events
3
+ AND type IN ('node.turn.started', 'node.turn.completed') ORDER BY sequence_number DESC LIMIT 1`).get(t,t);if(!r)return{phase:"starting"};if(r.type==="node.turn.completed")return{phase:"between_turns"};const i=await s();if(i?.kind==="text")return{phase:"writing"};if(i?.kind==="tool_call")return i.name===p?{phase:"submitting_result"}:{phase:"tool",tool:{name:i.name,summary:null}};if(i===null){const a=(await o.prepare(`SELECT type, body_json, sequence_number FROM run_events
4
4
  WHERE run_id = ? AND node_id = ? AND type IN ('node.tool_call.started', 'node.tool_call.completed') AND sequence_number > ?
5
5
  ORDER BY sequence_number`).all(t,t,r.sequence_number)).map(e=>({...e,id:JSON.parse(e.body_json).tool_call_id})),c=new Set(a.filter(e=>e.type==="node.tool_call.completed").map(e=>e.id)),u=a.filter(e=>e.type==="node.tool_call.started"&&!c.has(e.id)).at(-1);if(u){const e=JSON.parse(u.body_json);return e.name===p?{phase:"submitting_result"}:{phase:"tool",tool:{name:e.name,summary:y(e.arguments??null)}}}}return{phase:"thinking"}}l(g,"runActivity");export{g as runActivity,y as toolCallSummary};
@@ -7,6 +7,10 @@ export declare function onRunEventAppended(hook: ((runId: string) => void | Prom
7
7
  /** Append one event to a run's log. `type` must be a declared run event and `fields` its fields. */
8
8
  export declare function appendRunEvent<T extends RunEventType>(db: CanvasDb, runId: string, nodeId: string, type: T, fields: RunEventFields<T>): Promise<RunEventOf<T>>;
9
9
  export declare function emitRunEvent<T extends RunEventType>(runId: string, nodeId: string, type: T, fields: RunEventFields<T>): Promise<RunEventOf<T>>;
10
+ /** Serializes read-then-append decisions on one run across processes. */
11
+ export declare function lockRunRoot(db: CanvasDb, runId: string): Promise<void>;
12
+ /** Append `node.status.changed` unless the node's newest status event already says `status`. Two processes that observe one change append one event. */
13
+ export declare function emitRunStatus(runId: string, nodeId: string, status: string, reason: string | null): Promise<void>;
10
14
  export declare function emitRunSettlement<T extends 'node.settled' | 'child.settled'>(runId: string, nodeId: string, type: T, fields: RunEventFields<T>): Promise<void>;
11
15
  export declare function readRunEvents(runId: string, after?: number): Promise<{
12
16
  events: RunEvent[];
@@ -16,12 +20,8 @@ export declare function readRunEvents(runId: string, after?: number): Promise<{
16
20
  backlog_bytes: number;
17
21
  }>;
18
22
  export declare function subscribeRunEvents(runId: string, wake: () => void): Promise<() => void>;
23
+ /** Wake every stream on the run, in every process; its next read observes the missing run. */
19
24
  export declare function notifyRunDeleted(runId: string): void;
20
- /** A run event cursor stays monotonic. Keep control/settlement/usage history
21
- * for the observer's 30-day recovery window, but full payload events for 14
22
- * days only; older conversation content is in the transcript store. The stream
23
- * already signals a cursor gap when events have expired. Budget one page/tick. */
24
- export declare function expireRunEvents(now: number, limit?: number): Promise<number>;
25
25
  /** The conversation store is the canonical full transcript. Keep the full
26
26
  * stream for one day, then redact settled tool calls, prompts and thinking.
27
27
  * This includes older completed events of a still-live run, but tool-call
@@ -37,3 +37,5 @@ export declare function compactRunEvents(now: number, afterSeq?: number, scanLim
37
37
  export declare function registerGrantStream(grant: string, close: () => void): () => void;
38
38
  /** Close every open stream held under a grant that is no longer active. */
39
39
  export declare function closeGrantStreams(grant: string): number;
40
+ /** The grant ids this process holds open `run.events` streams under. */
41
+ export declare function heldGrantIds(): string[];
@@ -1,7 +1,3 @@
1
- var y=Object.defineProperty;var c=(e,t)=>y(e,"name",{value:t,configurable:!0});import{afterCommit as S,withCanvasWrite as d,openDb as w}from"../canvas/db.js";import{emitEvent as g}from"../events/emit.js";import{repairRunConversations as O}from"../canvas/sessions.js";const E=new Map;let f;function D(e){f=e}c(D,"onRunEventAppended");async function R(e,t,n,r,s){const o=await e.prepare("SELECT event_cursor, grantee, metadata_json FROM node_rows WHERE node_id = ? AND run_id = ?").get(t,t);if(!o||o.event_cursor===null)throw new Error(`missing run event cursor: ${t}`);const a={type:r,run_id:t,node_id:n,sequence_number:o.event_cursor,ts:new Date().toISOString(),metadata:o.metadata_json?JSON.parse(o.metadata_json):{},...s};return await e.prepare("INSERT INTO run_events (run_id, sequence_number, node_id, type, ts, body_json, grantee) VALUES (?, ?, ?, ?, ?, ?, ?)").run(t,a.sequence_number,n,r,a.ts,JSON.stringify(a),o.grantee),await e.prepare("UPDATE nodes SET event_cursor = event_cursor + 1, last_activity_at = ? WHERE node_id = ?").run(a.ts,t),S(()=>{for(const _ of E.get(t)??[])_();const u=c(_=>{g({level:"error",event:"runs.notice_hook_failed",error:_})},"failed");try{Promise.resolve(f?.(t)).catch(u)}catch(_){u(_)}}),a}c(R,"appendRunEvent");async function M(e,t,n,r){return await d(async s=>await R(s,e,t,n,r))}c(M,"emitRunEvent");async function L(e,t,n,r){await d(async s=>{(await s.prepare("SELECT body_json FROM run_events WHERE run_id = ? AND node_id = ? AND type = ?").all(e,t,n)).some(a=>JSON.parse(a.body_json).outcome?.revision===r.outcome.revision)||await R(s,e,t,n,r)})}c(L,"emitRunSettlement");async function C(e,t=0){await O(e);const n=await w(),r=await n.prepare("SELECT event_cursor FROM nodes WHERE node_id = ? AND run_id = ?").get(e,e);if(!r)throw new Error(`run not found: ${e}`);const s=await n.prepare("SELECT MIN(sequence_number) AS sequence FROM run_events WHERE run_id = ?").get(e),o=await n.prepare("SELECT COUNT(*) AS count, COALESCE(SUM(LENGTH(body_json)), 0) AS bytes FROM run_events WHERE run_id = ? AND sequence_number > ?").get(e,t);return{events:(o.count>1e3||o.bytes>32*1024*1024?[]:await n.prepare("SELECT body_json FROM run_events WHERE run_id = ? AND sequence_number > ? ORDER BY sequence_number LIMIT 1000").all(e,t)).map(u=>JSON.parse(u.body_json)),earliest_sequence:s.sequence,latest_sequence:r.event_cursor-1,backlog_count:o.count,backlog_bytes:o.bytes}}c(C,"readRunEvents");async function A(e,t){let n=E.get(e);return n||(n=new Set,E.set(e,n)),n.add(t),()=>{n.delete(t),n.size===0&&E.delete(e)}}c(A,"subscribeRunEvents");function H(e){queueMicrotask(()=>{for(const t of E.get(e)??[])t()})}c(H,"notifyRunDeleted");async function W(e,t=128){return await d(async n=>{const r=new Date(e-12096e5).toISOString(),s=new Date(e-720*60*6e4).toISOString(),o=Number((await n.prepare(`DELETE FROM run_events WHERE seq IN
2
- (SELECT seq FROM run_events WHERE ts < ? AND type IN
3
- ('node.tool_call.completed', 'node.tool_call.started', 'node.system_prompt.set',
4
- 'node.thinking.done', 'node.output_text.done') ORDER BY ts LIMIT ?)`).run(r,t)).changes),a=Number((await n.prepare(`DELETE FROM run_events WHERE seq IN
5
- (SELECT seq FROM run_events WHERE ts < ? ORDER BY ts LIMIT ?)`).run(s,t-o)).changes);return o+a})}c(W,"expireRunEvents");async function x(e,t=0,n=256,r=8){return await d(async s=>{const o=await s.prepare(`SELECT e.seq, e.type, e.ts, length(e.body_json) AS bytes,
1
+ var O=Object.defineProperty;var r=(e,t)=>O(e,"name",{value:t,configurable:!0});import{afterCommit as N,withCanvasWrite as f,openDb as y}from"../canvas/db.js";import{emitEvent as R}from"../events/emit.js";import{repairRunConversations as T}from"../canvas/sessions.js";import{brokerSignalBus as m}from"../../daemon/broker-signals/bus.js";const p=new Map;let v;function D(){v??=m.subscribe(e=>{for(const t of p.get(e)??[])t()},{kinds:["run_event"],onListenStart:r(()=>{for(const e of[...p.values()])for(const t of e)t()},"onListenStart")})}r(D,"listenForRunEvents");let g;function h(e){g=e}r(h,"onRunEventAppended");async function S(e,t,n,s,o){const a=await e.prepare("UPDATE nodes SET event_cursor = event_cursor + 1, last_activity_at = ? WHERE node_id = ? AND run_id = ? AND event_cursor IS NOT NULL RETURNING event_cursor - 1 AS sequence_number").get(new Date().toISOString(),t,t);if(!a)throw new Error(`missing run event cursor: ${t}`);const c=await e.prepare("SELECT grantee, metadata_json FROM node_rows WHERE node_id = ?").get(t),u={type:s,run_id:t,node_id:n,sequence_number:Number(a.sequence_number),ts:new Date().toISOString(),metadata:c.metadata_json?JSON.parse(c.metadata_json):{},...o};return await e.prepare("INSERT INTO run_events (run_id, sequence_number, node_id, type, ts, body_json, grantee) VALUES (?, ?, ?, ?, ?, ?, ?)").run(t,u.sequence_number,n,s,u.ts,JSON.stringify(u),c.grantee),await e.prepare("SELECT pg_notify(?, ?)").get("crtr_signal",`run_event:${t}`),N(()=>{m.markSignal("run_event",t);const E=r(l=>{R({level:"error",event:"runs.notice_hook_failed",error:l})},"failed");try{Promise.resolve(g?.(t)).catch(E)}catch(l){E(l)}}),u}r(S,"appendRunEvent");async function j(e,t,n,s){return await f(async o=>await S(o,e,t,n,s))}r(j,"emitRunEvent");async function w(e,t){await e.prepare("SELECT 1 FROM nodes WHERE node_id = ? AND run_id = ? FOR UPDATE").get(t,t)}r(w,"lockRunRoot");async function k(e,t,n,s){await f(async o=>{await w(o,e);const a=await o.prepare("SELECT body_json FROM run_events WHERE run_id = ? AND node_id = ? AND type = 'node.status.changed' ORDER BY sequence_number DESC LIMIT 1").get(e,t);a&&JSON.parse(a.body_json).status===n||await S(o,e,t,"node.status.changed",{status:n,reason:s})})}r(k,"emitRunStatus");async function x(e,t,n,s){await f(async o=>{await w(o,e),(await o.prepare("SELECT body_json FROM run_events WHERE run_id = ? AND node_id = ? AND type = ?").all(e,t,n)).some(c=>JSON.parse(c.body_json).outcome?.revision===s.outcome.revision)||await S(o,e,t,n,s)})}r(x,"emitRunSettlement");async function H(e,t=0){await T(e);const n=await y(),s=await n.prepare("SELECT event_cursor FROM nodes WHERE node_id = ? AND run_id = ?").get(e,e);if(!s)throw new Error(`run not found: ${e}`);const o=await n.prepare("SELECT MIN(sequence_number) AS sequence FROM run_events WHERE run_id = ?").get(e),a=await n.prepare("SELECT COUNT(*) AS count, COALESCE(SUM(LENGTH(body_json)), 0) AS bytes FROM run_events WHERE run_id = ? AND sequence_number > ?").get(e,t);return{events:(a.count>1e3||a.bytes>32*1024*1024?[]:await n.prepare("SELECT body_json FROM run_events WHERE run_id = ? AND sequence_number > ? ORDER BY sequence_number LIMIT 1000").all(e,t)).map(u=>JSON.parse(u.body_json)),earliest_sequence:o.sequence,latest_sequence:s.event_cursor-1,backlog_count:a.count,backlog_bytes:a.bytes}}r(H,"readRunEvents");async function F(e,t){let n=p.get(e);return n||(n=new Set,p.set(e,n)),n.add(t),D(),()=>{if(n.delete(t),!(n.size>0)&&(p.delete(e),p.size===0)){const s=v;v=void 0,s?.then(o=>o())}}}r(F,"subscribeRunEvents");function W(e){m.markSignal("run_event",e),y().then(t=>t.prepare("SELECT pg_notify(?, ?)").get("crtr_signal",`run_event:${e}`)).catch(t=>R({level:"error",event:"runs.deleted_notice_failed",error:t}))}r(W,"notifyRunDeleted");async function J(e,t=0,n=256,s=8){return await f(async o=>{const a=await o.prepare(`SELECT e.seq, e.type, e.ts, length(e.body_json) AS bytes,
6
2
  n.finalized_at FROM run_events e LEFT JOIN nodes n ON n.node_id = e.node_id
7
- WHERE e.seq > ? ORDER BY e.seq LIMIT ?`).all(t,n);if(!o.length)return{cursor:0,compacted:0};let a=0,u=t;const _=new Date(e-1440*6e4).toISOString(),m=s.prepare("SELECT body_json FROM run_events WHERE seq = ?"),v=s.prepare("UPDATE run_events SET body_json = ? WHERE seq = ?");for(const i of o){if(u=i.seq,!["node.tool_call.completed","node.tool_call.started","node.system_prompt.set","node.thinking.done"].includes(i.type)||i.ts>=_||i.bytes<1024||i.type==="node.tool_call.started"&&!i.finalized_at)continue;const p=JSON.parse((await m.get(i.seq)).body_json);if(p.content_redacted!==!0&&(i.type==="node.tool_call.completed"?delete p.result:i.type==="node.tool_call.started"?delete p.arguments:delete p.text,p.content_redacted=!0,await v.run(JSON.stringify(p),i.seq),++a>=r))break}return{cursor:u,compacted:a}})}c(x,"compactRunEvents");const l=new Map;function h(e,t){let n=l.get(e);return n||(n=new Set,l.set(e,n)),n.add(t),()=>{n.delete(t),n.size===0&&l.delete(e)}}c(h,"registerGrantStream");function j(e){const t=[...l.get(e)??[]];for(const n of t)n();return t.length}c(j,"closeGrantStreams");export{R as appendRunEvent,j as closeGrantStreams,x as compactRunEvents,M as emitRunEvent,L as emitRunSettlement,W as expireRunEvents,H as notifyRunDeleted,D as onRunEventAppended,C as readRunEvents,h as registerGrantStream,A as subscribeRunEvents};
3
+ WHERE e.seq > ? ORDER BY e.seq LIMIT ?`).all(t,n);if(!a.length)return{cursor:0,compacted:0};let c=0,u=t;const E=new Date(e-1440*6e4).toISOString(),l=o.prepare("SELECT body_json FROM run_events WHERE seq = ?"),b=o.prepare("UPDATE run_events SET body_json = ? WHERE seq = ?");for(const i of a){if(u=i.seq,!["node.tool_call.completed","node.tool_call.started","node.system_prompt.set","node.thinking.done"].includes(i.type)||i.ts>=E||i.bytes<1024||i.type==="node.tool_call.started"&&!i.finalized_at)continue;const _=JSON.parse((await l.get(i.seq)).body_json);if(_.content_redacted!==!0&&(i.type==="node.tool_call.completed"?delete _.result:i.type==="node.tool_call.started"?delete _.arguments:delete _.text,_.content_redacted=!0,await b.run(JSON.stringify(_),i.seq),++c>=s))break}return{cursor:u,compacted:c}})}r(J,"compactRunEvents");const d=new Map;function U(e,t){let n=d.get(e);return n||(n=new Set,d.set(e,n)),n.add(t),()=>{n.delete(t),n.size===0&&d.delete(e)}}r(U,"registerGrantStream");function z(e){const t=[...d.get(e)??[]];for(const n of t)n();return t.length}r(z,"closeGrantStreams");function B(){return[...d.keys()]}r(B,"heldGrantIds");export{S as appendRunEvent,z as closeGrantStreams,J as compactRunEvents,j as emitRunEvent,x as emitRunSettlement,k as emitRunStatus,B as heldGrantIds,w as lockRunRoot,W as notifyRunDeleted,h as onRunEventAppended,H as readRunEvents,U as registerGrantStream,F as subscribeRunEvents};
@@ -3,7 +3,7 @@ import type { AppPrincipal } from '../../daemon/api/principal.js';
3
3
  import { type ResolvedAttachments } from '../storage/attachments.js';
4
4
  import { type StorageClient, type StorageConfig } from '../storage/client.js';
5
5
  /** Fetches the storage URLs of a run's text into the run's `attachments/`. */
6
- export type AttachmentResolver = (runId: string, grantee: string, text: string) => Promise<ResolvedAttachments>;
6
+ export type AttachmentResolver = (runId: string, grantee: string, text: string, taken?: readonly string[]) => Promise<ResolvedAttachments>;
7
7
  /** Storage deletes `run.delete` waits for before it answers. */
8
8
  export declare const RUN_DELETE_STORAGE_BUDGET_MS = 3000;
9
9
  export interface StorageDeps {
@@ -1,14 +1,14 @@
1
- var Oe=Object.defineProperty;var u=(e,t)=>Oe(e,"name",{value:t,configurable:!0});import{coveredByAny as be}from"../../shared/env.js";import{createHash as G}from"node:crypto";import{ApiError as De}from"../../api/errors.js";import{CrtrError as Me}from"../errors.js";import{isAbsolute as z,relative as Ie,resolve as Ae,sep as Te,join as Le}from"node:path";import{SessionManager as Ce}from"@earendil-works/pi-coding-agent";import{covers as U}from"@north-light/identity";import{openDb as B,withCanvasWrite as W}from"../canvas/db.js";import{deleteNodeWithOwned as ke}from"../graph/deletion.js";import{getById as xe}from"../graph/objects.js";import{repairRunConversations as Q}from"../canvas/sessions.js";import{getNode as O,nodeFiles as We,removeNodeFiles as Fe,updateNode as qe}from"../canvas/canvas.js";import{fullName as He}from"../canvas/labels.js";import{renameWindow as Ue}from"../runtime/placement.js";import{liveExecutionForNode as V}from"../canvas/executions.js";import{conversationStore as Z,isConversationNotFound as Be}from"../conversation-store/index.js";import{PARKED_RESIDENT_SQL as Pe}from"../canvas/canvas.js";import{WAKE_MAIL_SQL as $e}from"../canvas/deliveries.js";import{readNodeRecap as je}from"../canvas/node-recap.js";import{enqueueNodeMail as Je}from"../feed/messages.js";import{newestReportBody as Ye}from"../feed/reports.js";import{ensureAppProfile as Xe,loadExactProfileManifest as Ge}from"../profiles/manifest.js";import{stopNodeSandboxes as K}from"../spaces/stop.js";import{BrokerUnreachableError as ze}from"../runtime/broker-request.js";import{interruptLive as Qe}from"../runtime/interactive-deliver.js";import{isBrokerLive as ee}from"../runtime/model-swap.js";import{newNodeId as Ve}from"../runtime/nodes.js";import{reviveNode as P}from"../runtime/revive.js";import{spawnChildPrepared as Ze}from"../runtime/spawn.js";import{isPortableModelToken as Ke}from"../runtime/launch.js";import{parseDurationMs as et}from"../wake.js";import{expandModelCandidates as tt,parseModelSpec as nt}from"../model-routes.js";import{payerOfGrant as $}from"../grants/mirror.js";import{isolatedBrokerLauncherAvailable as st}from"../runtime/host.js";import{resolveRunKind as at,resolveRunModel as it}from"../runtime/launch-target.js";import{cycleAwareMessages as rt}from"../runtime/session-cycles.js";import{originFor as te}from"../runtime/stamp/protocol.js";import{readOutputRequest as ot,readOutputResult as ne}from"../runtime/structured-output.js";import{admitLegacyStructuredOutput as se}from"../../daemon/structured-requests/sidecar.js";import{runSchemaRepromptPending as dt}from"../runtime/stop-guard.js";import{toRunOutcomeDTO as ct}from"../../daemon/api/map.js";import{openAssistantMessageStartSequence as ut}from"../../daemon/runs/observer.js";import{closeNode as ae}from"../runtime/close.js";import{parseScope as mt}from"@north-light/identity";import{appendRunEvent as ie,subscribeRunEvents as lt}from"./events.js";import{runActivity as pt}from"./activity.js";import{cancelOpenQuestions as re,openNoticeIds as _t,openQuestionIds as oe}from"./questions.js";import{appSpace as j}from"../layout.js";import{ensureAppSpace as ft}from"../spaces/space.js";import{assertUploadsUsable as de,resolveStorageUrls as wt}from"../storage/attachments.js";import{storageClient as gt,storageConfig as Et}from"../storage/client.js";import{deleteUploadRow as yt,insertUploadUses as ce,releaseRunUploads as ht}from"../storage/tables.js";import{abortProviderCalls as ue}from"../providers/inflight.js";import{filterAsync as me,mapAsync as k}from"../async-array.js";const le=u((e,t,s)=>wt(t,e,s),"defaultResolver"),Rt=3e3;class N extends Error{static{u(this,"RunError")}status;code;param;details;scope;retryable;constructor(t,s,n,d,l,i,r=t===503){super(n),this.status=t,this.code=s,this.param=d,this.details=l,this.scope=i,this.retryable=r}}const S=u((e,t)=>new N(400,"invalid_request",e,t),"invalid"),J=u(()=>new N(404,"not_found","run not found"),"missing"),Y=u(()=>({input_tokens:0,output_tokens:0,cache_read_tokens:0,cache_write_tokens:0,cost_usd:0}),"usage"),I=u(async()=>await B(),"db");async function F(e,t,s=!1){const n=await O(e);if(!n||n.parent!==null||n.run_id!==e||n.grantee!==t||!s&&n.deleting_at)throw J();return n}u(F,"ownedRun");const pe=["waiting_on_user","idle","settled"];async function C(e){if(e.status==="canceled"||e.status==="dead"||e.status==="done"&&e.intent!=="parked")return"settled";const t=await(await I()).prepare(`SELECT 1 FROM node_rows n WHERE n.run_id = ? AND n.status = 'active' AND
1
+ var Oe=Object.defineProperty;var u=(e,t)=>Oe(e,"name",{value:t,configurable:!0});import{coveredByAny as be}from"../../shared/env.js";import{createHash as z}from"node:crypto";import{ApiError as De}from"../../api/errors.js";import{CrtrError as Me}from"../errors.js";import{isAbsolute as Q,relative as Ae,resolve as Ie,sep as Te,join as Le}from"node:path";import{SessionManager as Ce}from"@earendil-works/pi-coding-agent";import{covers as P}from"@north-light/identity";import{openDb as B,withCanvasWrite as W}from"../canvas/db.js";import{deleteNodeWithOwned as ke}from"../graph/deletion.js";import{getById as xe}from"../graph/objects.js";import{repairRunConversations as V}from"../canvas/sessions.js";import{getNode as b,nodeFiles as We,removeNodeFiles as Fe,updateNode as qe}from"../canvas/canvas.js";import{fullName as He}from"../canvas/labels.js";import{renameWindow as Ue}from"../runtime/placement.js";import{liveExecutionForNode as Z}from"../canvas/executions.js";import{conversationStore as K,isConversationNotFound as Pe}from"../conversation-store/index.js";import{PARKED_RESIDENT_SQL as Be}from"../canvas/canvas.js";import{WAKE_MAIL_SQL as $e}from"../canvas/deliveries.js";import{readNodeRecap as je}from"../canvas/node-recap.js";import{enqueueNodeMail as Je}from"../feed/messages.js";import{newestReportBody as Ye}from"../feed/reports.js";import{ensureAppProfile as Ge,loadExactProfileManifest as Xe}from"../profiles/manifest.js";import{stopNodeSandboxes as ee}from"../spaces/stop.js";import{BrokerUnreachableError as ze}from"../runtime/broker-request.js";import{interruptLive as Qe}from"../runtime/interactive-deliver.js";import{isBrokerLive as te}from"../runtime/model-swap.js";import{newNodeId as Ve}from"../runtime/nodes.js";import{reviveNode as $}from"../runtime/revive.js";import{spawnChildPrepared as Ze}from"../runtime/spawn.js";import{isPortableModelToken as Ke}from"../runtime/launch.js";import{parseDurationMs as et}from"../wake.js";import{expandModelCandidates as tt,parseModelSpec as nt}from"../model-routes.js";import{payerOfGrant as j}from"../grants/mirror.js";import{isolatedBrokerLauncherAvailable as at}from"../runtime/host.js";import{resolveRunKind as st,resolveRunModel as it}from"../runtime/launch-target.js";import{cycleAwareMessages as rt}from"../runtime/session-cycles.js";import{originFor as ne}from"../runtime/stamp/protocol.js";import{readOutputRequest as ot,readOutputResult as ae}from"../runtime/output-result.js";import{admitLegacyStructuredOutput as se}from"../../daemon/structured-requests/sidecar.js";import{runSchemaRepromptPending as dt}from"../runtime/stop-guard.js";import{toRunOutcomeDTO as ct}from"../../daemon/api/map.js";import{openAssistantMessageStartSequence as ut}from"../../daemon/runs/observer.js";import{closeNode as ie}from"../runtime/close.js";import{parseScope as mt}from"@north-light/identity";import{appendRunEvent as re,lockRunRoot as lt,subscribeRunEvents as pt}from"./events.js";import{runActivity as _t}from"./activity.js";import{cancelOpenQuestions as oe,openNoticeIds as ft,openQuestionIds as de}from"./questions.js";import{appSpace as J}from"../layout.js";import{ensureAppSpace as wt}from"../spaces/space.js";import{assertUploadsUsable as ce,resolveStorageUrls as gt}from"../storage/attachments.js";import{storageClient as Et,storageConfig as yt}from"../storage/client.js";import{deleteUploadRow as ht,insertUploadUses as ue,releaseRunUploads as Rt,runUsesPath as St}from"../storage/tables.js";import{abortProviderCalls as me}from"../providers/inflight.js";import{filterAsync as le,mapAsync as k}from"../async-array.js";const pe=u((e,t,s,n)=>gt(t,e,s,n?{taken:n}:{}),"defaultResolver"),Nt=3e3;class S extends Error{static{u(this,"RunError")}status;code;param;details;scope;retryable;constructor(t,s,n,o,m,i,r=t===503){super(n),this.status=t,this.code=s,this.param=o,this.details=m,this.scope=i,this.retryable=r}}const N=u((e,t)=>new S(400,"invalid_request",e,t),"invalid"),Y=u(()=>new S(404,"not_found","run not found"),"missing"),G=u(()=>({input_tokens:0,output_tokens:0,cache_read_tokens:0,cache_write_tokens:0,cost_usd:0}),"usage"),A=u(async()=>await B(),"db");async function F(e,t,s=!1){const n=await b(e);if(!n||n.parent!==null||n.run_id!==e||n.grantee!==t||!s&&n.deleting_at)throw Y();return n}u(F,"ownedRun");const _e=["waiting_on_user","idle","settled"];async function C(e){if(e.status==="canceled"||e.status==="dead"||e.status==="done"&&e.intent!=="parked")return"settled";const t=await(await A()).prepare(`SELECT 1 FROM node_rows n WHERE n.run_id = ? AND n.status = 'active' AND
2
2
  (n.last_settled_at IS NULL OR EXISTS (
3
3
  SELECT 1 FROM run_events e WHERE e.run_id = ? AND e.node_id = n.node_id AND e.type = 'node.turn.started'
4
4
  AND e.sequence_number > COALESCE((SELECT MAX(c.sequence_number) FROM run_events c
5
5
  WHERE c.run_id = e.run_id AND c.node_id = e.node_id AND c.type = 'node.turn.completed'), 0)
6
- )) LIMIT 1`).get(e.node_id,e.node_id),s=!e.last_settled_at&&e.status!=="done";return t||s||await dt(e)?"running":(await oe(e.node_id)).length?"waiting_on_user":await(await I()).prepare(`SELECT 1 FROM deliveries d JOIN nodes n ON n.node_id = d.destination_id
6
+ )) LIMIT 1`).get(e.node_id,e.node_id),s=!e.last_settled_at&&e.status!=="done";return t||s||await dt(e)?"running":(await de(e.node_id)).length?"waiting_on_user":await(await A()).prepare(`SELECT 1 FROM deliveries d JOIN nodes n ON n.node_id = d.destination_id
7
7
  WHERE n.run_id = ? AND ${$e("d","'armed', 'pending'")}
8
- AND (n.status IN ('active', 'idle') OR ${Pe("n")}) LIMIT 1`).get(e.node_id)?"running":"idle"}u(C,"runStatus");async function Dn(e){const t=await O(e);return t!==null&&await C(t)==="running"}u(Dn,"runIsRunning");async function x(e){await Q(e.node_id),e=await O(e.node_id)??e;const t=await C(e),s=t==="settled"?[]:await oe(e.node_id),n=await Ye(e.node_id)||void 0,d=t==="settled"?ct(e):null,l=d?.kind==="result"?ne(e.node_id,e.grantee):void 0,i=je(e.node_id);return{run_id:e.node_id,name:e.name,status:t,...d?{outcome:d}:{},...l===void 0?{}:{result:l},...n!==void 0?{last_report:n}:{},...i?{recap:i}:{},pending_question_ids:s,open_notice_ids:t==="settled"?[]:await _t(e.node_id),...e.last_turn_error_json?{last_turn_error:JSON.parse(e.last_turn_error_json)}:{},usage:JSON.parse(e.usage_json??JSON.stringify(Y())),payer:await $(e.grant_id),scopes:e.scopes,metadata:e.metadata_json?JSON.parse(e.metadata_json):{},created_at:e.created,...t==="settled"&&e.outcome_at?{settled_at:e.outcome_at}:{},latest_sequence:(e.event_cursor??1)-1,last_activity_at:e.last_activity_at,activity:await pt(e.node_id,t)}}u(x,"runObject");const X=864e5,_e=255;function Mn(e){if(e!==void 0){if(typeof e!="string"||!e.length||e.length>_e)throw S(`Idempotency-Key must be 1-${_e} characters`);return e}}u(Mn,"idempotencyKeyOf");async function q(e,t,s,n){n??=await B();const d=await n.prepare("SELECT body_hash, run_id, response_json, created_at FROM idempotency_keys WHERE grantee = ? AND key = ?").get(e,t);if(!(!d||Date.now()-Date.parse(d.created_at)>=X)){if(d.body_hash!==s)throw new N(409,"idempotency_conflict","key used with a different request");return{run_id:d.run_id,response:JSON.parse(d.response_json)}}}u(q,"findIdempotent");async function fe(e,t,s,n,d,l,i){await e.prepare("DELETE FROM idempotency_keys WHERE grantee = ? AND key = ? AND created_at <= ?").run(t,s,new Date(Date.now()-X).toISOString()),await e.prepare("INSERT INTO idempotency_keys (grantee, key, body_hash, run_id, response_json, created_at) VALUES (?, ?, ?, ?, ?, ?)").run(t,s,n,d,JSON.stringify(l),i)}u(fe,"recordIdempotent");async function In(e=Date.now()){return Number((await(await B()).prepare("DELETE FROM idempotency_keys WHERE created_at <= ?").run(new Date(e-X).toISOString())).changes)}u(In,"pruneExpiredIdempotencyKeys");async function we(e,t,s,n,d){const l=n.text;let i=0;return{messageId:(await Je(t,{kind:"message",label:l.slice(0,120),senderNodeId:"human",senderName:s,bodyJson:d?{body:l}:{body:l,start_turn:!1},urgency:d?"normal":"deferred",wake:d?1:0,withinEnqueue:u(async(c,m)=>{n.uses.length&&(await de(s,n.uses,c),await ce(n.uses.map(({upload_id:h,path:E})=>({upload_id:h,path:E,run_id:t})),c)),i=(await ie(c,t,t,"node.message.accepted",{message_id:m,start_turn:d})).sequence_number},"withinEnqueue")})).messageId,sequence:i}}u(we,"acceptRunMessage");class ge extends Error{static{u(this,"IdempotentReplay")}winner;constructor(t){super("idempotent replay"),this.winner=t}}const St=1440*60*1e3;function Ee(e){const t=typeof e=="string"?et(e):null;if(t===null||!Number.isSafeInteger(t))throw S(`deadline '${String(e)}' is not a duration; use one or more <int>[smhd] parts such as 10m or 1h30m`,"deadline");if(t<=0)throw S("deadline must be greater than zero","deadline");if(t>St)throw S("deadline must be at most 24h","deadline");return t}u(Ee,"parseRunDeadlineMs");async function An(e,t,s,n=le){if(t.isolated&&!st())throw new N(503,"isolated_unavailable","isolated runs require the Linux root launcher","isolated");t.deadline!==void 0&&Ee(t.deadline);const{causedBy:d,...l}=t,i=G("sha256").update(JSON.stringify(l)).digest("hex");if(s){const a=await q(e.grantee,s,i);if(a){const p=await F(a.run_id,e.grantee);return!p.pi_pid&&await C(p)==="running"&&(t.output_schema!==void 0&&!p.outcome_at&&ot(p.node_id).state==="absent"&&ne(p.node_id,p.grantee)===void 0&&await se(p.node_id,"terminal",t.output_schema),await P(p.node_id,{resume:!0,capacity:"freeze"})),a.response}}await ft(e.grantee);const r=t.profile===void 0?Xe(e.grantee):Ge(t.profile),c=r.manifest.grantee??"app:terminal";if(c!==e.grantee){const a=`crtr:memory:rw:${c}:profile:${r.profileId}`;if(!e.resolved.some(p=>U(p,a))||t.scopes!==null&&!t.scopes.some(p=>U(p,a)))throw new N(403,"scope_missing",`missing scope ${a}`,"profile",void 0,a)}if(t.model!==void 0){const a=t.model;if(Ke(a)){if(a.includes("/")&&await $(e.grant)!=="app"){const p=a.lastIndexOf("/"),D=a.slice(0,p),v=a.slice(p+1);if(["ultra","strong","medium","light"].includes(v)&&tt({kind:"logical",family:D,strength:v,spec:a},j(e.grantee).files,r.profileId).every(R=>R.family!==D))throw S(`model '${a}' names a model family that is not configured in this daemon`,"model")}}else if(nt(a)===void 0)throw S(`model '${a}' is not a strength (ultra, strong, medium, light), a family/strength, or a provider/model id`,"model")}const m=await Ve(),h=Le(j(e.grantee).nodes,m);if(t.isolated&&t.cwd!==void 0){const a=Ie(h,Ae(t.cwd));if(!z(t.cwd)||a===".."||a.startsWith(`..${Te}`)||z(a))throw S("cwd must be inside the isolated root node folder","cwd")}const E=await n(m,e.grantee,t.prompt),g=E.text;let o;try{o=t.message===void 0?void 0:await n(m,e.grantee,t.message)}catch(a){throw E.cleanup(),a}const _=await $(e.grant);let y;try{const a=it(r,t.model);await Ze({kind:at(r),mode:"base",root:!0,rootLifecycle:"resident",readiness:"launch",cwd:t.isolated?t.cwd??h:j(e.grantee).files,profile:r.profileId,prompt:g,nodeId:m,isolated:t.isolated??!1,...t.causedBy===void 0?{}:{causedBy:t.causedBy},...a===void 0?{}:{model:a},...t.deadline===void 0?{}:{deadlineAt:new Date(Date.now()+Ee(t.deadline)).toISOString()},...t.scopes===null?{}:{scopes:t.scopes},run:{grantee:e.grantee,sub:e.sub,grant_id:e.grant,client_id:e.client_id,metadata_json:JSON.stringify(t.metadata),run_id:m,event_cursor:1,usage_json:JSON.stringify(Y())},withinCreate:u(async(p,D)=>{if(s){const R=await q(e.grantee,s,i,p);if(R)throw new ge(R)}const v=E.uses;if(v.length&&(await de(e.grantee,v,p),await ce(v.map(({upload_id:R,path:A})=>({upload_id:R,path:A,run_id:m})),p)),y={run_id:m,node_id:m,grantee:e.grantee,grant:e.grant,rev:e.rev,scopes:t.scopes,payer:_,status:"running",created_at:D.created,metadata:t.metadata,sequence_number:0},await ie(p,m,m,"run.started",{scopes:t.scopes,payer:_,usage:Y()}),o){const R=await we(p,m,e.grantee,o,!1);y.message={run_id:m,message_id:R.messageId,sequence_number:R.sequence}}s&&await fe(p,e.grantee,s,i,m,y,D.created)},"withinCreate")},t.output_schema===void 0?void 0:async p=>{await se(p,"terminal",t.output_schema)})}catch(a){if(await O(m)||(E.cleanup(),o?.cleanup()),a instanceof ge)return a.winner.response;if(t.model!==void 0&&a instanceof Me&&a.code==="usage")throw S(a.message,"model");if(a instanceof De&&(a.code==="isolated_run"||a.code==="invalid_request")){const p=a.details&&typeof a.details=="object"&&"param"in a.details&&typeof a.details.param=="string"?a.details.param:void 0;throw new N(a.status,a.code,a.message,p)}throw a}if(!y)throw new Error("run creation did not commit");return y}u(An,"startRun");async function Tn(e,t){let s;if(t.after)try{const r=JSON.parse(Buffer.from(t.after,"base64url").toString());if(!r||typeof r!="object"||!("activity"in r)||typeof r.activity!="string"||!("id"in r)||typeof r.id!="string")throw new Error("invalid cursor");s={activity:r.activity,id:r.id}}catch{throw S("invalid list cursor","after")}const n=await(await I()).prepareUncached(`SELECT node_id, COALESCE(last_activity_at, created) AS activity FROM node_rows
8
+ AND (n.status IN ('active', 'idle') OR ${Be("n")}) LIMIT 1`).get(e.node_id)?"running":"idle"}u(C,"runStatus");async function In(e){const t=await b(e);return t!==null&&await C(t)==="running"}u(In,"runIsRunning");async function x(e){await V(e.node_id),e=await b(e.node_id)??e;const t=await C(e),s=t==="settled"?[]:await de(e.node_id),n=await Ye(e.node_id)||void 0,o=t==="settled"?await ct(e):null,m=o?.kind==="result"?await ae(e.node_id):void 0,i=je(e.node_id);return{run_id:e.node_id,name:e.name,status:t,...o?{outcome:o}:{},...m===void 0?{}:{result:m},...n!==void 0?{last_report:n}:{},...i?{recap:i}:{},pending_question_ids:s,open_notice_ids:t==="settled"?[]:await ft(e.node_id),...e.last_turn_error_json?{last_turn_error:JSON.parse(e.last_turn_error_json)}:{},usage:JSON.parse(e.usage_json??JSON.stringify(G())),payer:await j(e.grant_id),scopes:e.scopes,metadata:e.metadata_json?JSON.parse(e.metadata_json):{},created_at:e.created,...t==="settled"&&e.outcome_at?{settled_at:e.outcome_at}:{},latest_sequence:(e.event_cursor??1)-1,last_activity_at:e.last_activity_at,activity:await _t(e.node_id,t)}}u(x,"runObject");const X=864e5,fe=255;function Tn(e){if(e!==void 0){if(typeof e!="string"||!e.length||e.length>fe)throw N(`Idempotency-Key must be 1-${fe} characters`);return e}}u(Tn,"idempotencyKeyOf");async function q(e,t,s,n){n&&await n.prepare("SELECT pg_advisory_xact_lock(hashtext(?))").get(`idempotency:${e}:${t}`),n??=await B();const o=await n.prepare("SELECT body_hash, run_id, response_json, created_at FROM idempotency_keys WHERE grantee = ? AND key = ?").get(e,t);if(!(!o||Date.now()-Date.parse(o.created_at)>=X)){if(o.body_hash!==s)throw new S(409,"idempotency_conflict","key used with a different request");return{run_id:o.run_id,response:JSON.parse(o.response_json)}}}u(q,"findIdempotent");async function we(e,t,s,n,o,m,i){await e.prepare("DELETE FROM idempotency_keys WHERE grantee = ? AND key = ? AND created_at <= ?").run(t,s,new Date(Date.now()-X).toISOString()),await e.prepare("INSERT INTO idempotency_keys (grantee, key, body_hash, run_id, response_json, created_at) VALUES (?, ?, ?, ?, ?, ?)").run(t,s,n,o,JSON.stringify(m),i)}u(we,"recordIdempotent");async function Ln(e=Date.now()){return Number((await(await B()).prepare("DELETE FROM idempotency_keys WHERE created_at <= ?").run(new Date(e-X).toISOString())).changes)}u(Ln,"pruneExpiredIdempotencyKeys");async function ge(e,t,s,n,o){const m=n.text;let i=0;return{messageId:(await Je(t,{kind:"message",label:m.slice(0,120),senderNodeId:"human",senderName:s,bodyJson:o?{body:m}:{body:m,start_turn:!1},urgency:o?"normal":"deferred",wake:o?1:0,withinEnqueue:u(async(c,l)=>{n.uses.length&&(await ce(s,n.uses,c),await ue(n.uses.map(({upload_id:g,path:E,blob_key:y})=>({upload_id:g,path:E,blob_key:y,run_id:t})),c)),i=(await re(c,t,t,"node.message.accepted",{message_id:l,start_turn:o})).sequence_number},"withinEnqueue")})).messageId,sequence:i}}u(ge,"acceptRunMessage");class Ee extends Error{static{u(this,"IdempotentReplay")}winner;constructor(t){super("idempotent replay"),this.winner=t}}const vt=1440*60*1e3;function ye(e){const t=typeof e=="string"?et(e):null;if(t===null||!Number.isSafeInteger(t))throw N(`deadline '${String(e)}' is not a duration; use one or more <int>[smhd] parts such as 10m or 1h30m`,"deadline");if(t<=0)throw N("deadline must be greater than zero","deadline");if(t>vt)throw N("deadline must be at most 24h","deadline");return t}u(ye,"parseRunDeadlineMs");async function Cn(e,t,s,n=pe){if(t.isolated&&!at())throw new S(503,"isolated_unavailable","isolated runs require the Linux root launcher","isolated");t.deadline!==void 0&&ye(t.deadline);const{causedBy:o,...m}=t,i=z("sha256").update(JSON.stringify(m)).digest("hex");if(s){const a=await q(e.grantee,s,i);if(a){const p=await F(a.run_id,e.grantee);return!p.pi_pid&&await C(p)==="running"&&(t.output_schema!==void 0&&!p.outcome_at&&await ot(p.node_id)===null&&await ae(p.node_id)===void 0&&await se(p.node_id,"terminal",t.output_schema),await $(p.node_id,{resume:!0,capacity:"freeze"})),a.response}}await wt(e.grantee);const r=t.profile===void 0?await Ge(e.grantee):Xe(t.profile),c=r.manifest.grantee??"app:terminal";if(c!==e.grantee){const a=`crtr:memory:rw:${c}:profile:${r.profileId}`;if(!e.resolved.some(p=>P(p,a))||t.scopes!==null&&!t.scopes.some(p=>P(p,a)))throw new S(403,"scope_missing",`missing scope ${a}`,"profile",void 0,a)}if(t.model!==void 0){const a=t.model;if(Ke(a)){if(a.includes("/")&&await j(e.grant)!=="app"){const p=a.lastIndexOf("/"),D=a.slice(0,p),v=a.slice(p+1);if(["ultra","strong","medium","light"].includes(v)&&(await tt({kind:"logical",family:D,strength:v,spec:a},J(e.grantee).files,r.profileId)).every(R=>R.family!==D))throw N(`model '${a}' names a model family that is not configured in this daemon`,"model")}}else if(nt(a)===void 0)throw N(`model '${a}' is not a strength (ultra, strong, medium, light), a family/strength, or a provider/model id`,"model")}const l=await Ve(),g=Le(J(e.grantee).nodes,l);if(t.isolated&&t.cwd!==void 0){const a=Ae(g,Ie(t.cwd));if(!Q(t.cwd)||a===".."||a.startsWith(`..${Te}`)||Q(a))throw N("cwd must be inside the isolated root node folder","cwd")}const E=await n(l,e.grantee,t.prompt),y=E.text,d=t.message===void 0?void 0:await n(l,e.grantee,t.message,E.uses.map(a=>a.path)),f=await j(e.grant);let h;try{const a=it(r,t.model);await Ze({kind:st(r),mode:"base",root:!0,rootLifecycle:"resident",readiness:"launch",cwd:t.isolated?t.cwd??g:J(e.grantee).files,profile:r.profileId,prompt:y,nodeId:l,isolated:t.isolated??!1,...t.causedBy===void 0?{}:{causedBy:t.causedBy},...a===void 0?{}:{model:a},...t.deadline===void 0?{}:{deadlineAt:new Date(Date.now()+ye(t.deadline)).toISOString()},...t.scopes===null?{}:{scopes:t.scopes},run:{grantee:e.grantee,sub:e.sub,grant_id:e.grant,client_id:e.client_id,metadata_json:JSON.stringify(t.metadata),run_id:l,event_cursor:1,usage_json:JSON.stringify(G())},withinCreate:u(async(p,D)=>{if(s){const R=await q(e.grantee,s,i,p);if(R)throw new Ee(R)}const v=E.uses;if(v.length&&(await ce(e.grantee,v,p),await ue(v.map(({upload_id:R,path:I,blob_key:H})=>({upload_id:R,path:I,blob_key:H,run_id:l})),p)),h={run_id:l,node_id:l,grantee:e.grantee,grant:e.grant,rev:e.rev,scopes:t.scopes,payer:f,status:"running",created_at:D.created,metadata:t.metadata,sequence_number:0},await re(p,l,l,"run.started",{scopes:t.scopes,payer:f,usage:G()}),d){const R=await ge(p,l,e.grantee,d,!1);h.message={run_id:l,message_id:R.messageId,sequence_number:R.sequence}}s&&await we(p,e.grantee,s,i,l,h,D.created)},"withinCreate")},t.output_schema===void 0?void 0:async p=>{await se(p,"terminal",t.output_schema)})}catch(a){if(a instanceof Ee)return a.winner.response;if(t.model!==void 0&&a instanceof Me&&a.code==="usage")throw N(a.message,"model");if(a instanceof De&&(a.code==="isolated_run"||a.code==="invalid_request")){const p=a.details&&typeof a.details=="object"&&"param"in a.details&&typeof a.details.param=="string"?a.details.param:void 0;throw new S(a.status,a.code,a.message,p)}throw a}if(!h)throw new Error("run creation did not commit");return h}u(Cn,"startRun");async function kn(e,t){let s;if(t.after)try{const r=JSON.parse(Buffer.from(t.after,"base64url").toString());if(!r||typeof r!="object"||!("activity"in r)||typeof r.activity!="string"||!("id"in r)||typeof r.id!="string")throw new Error("invalid cursor");s={activity:r.activity,id:r.id}}catch{throw N("invalid list cursor","after")}const n=await(await A()).prepareUncached(`SELECT node_id, COALESCE(last_activity_at, created) AS activity FROM node_rows
9
9
  WHERE run_id = node_id AND deleting_at IS NULL ${e===null?"":"AND grantee = ?"}
10
- ORDER BY activity DESC, node_id DESC`).all(...e===null?[]:[e]),d=await me(await k((await me(n,async({node_id:r})=>!t.visible||await t.visible(r))).filter(({activity:r,node_id:c})=>!s||r<s.activity||r===s.activity&&c<s.id),async r=>({root:await O(r.node_id),activity:r.activity})),async({root:r})=>!t.status||await C(r)===t.status),l=d.slice(0,t.limit),i=l.at(-1);return{runs:await k(l,async({root:r})=>await x(r)),next:d.length>t.limit&&i?Buffer.from(JSON.stringify({activity:i.activity,id:i.root.node_id})).toString("base64url"):null}}u(Tn,"listRuns");async function Ln(e,t,s){const n=await F(e,t),d=u(async()=>await x(await F(e,t)),"read");return!s||pe.includes(await C(n))?await d():new Promise((l,i)=>{let r=u(()=>{},"unsubscribe");const c=u(()=>{clearTimeout(o),clearInterval(g),r()},"settle"),m=u(async()=>{c();try{l(await d())}catch(_){i(_)}},"finish"),h=u(async()=>{pe.includes(String((await d()).status))&&await m()},"check"),E=u(()=>{h().catch(_=>{c(),i(_)})},"run"),g=setInterval(E,250),o=setTimeout(()=>{m()},s*1e3);lt(e,E).then(_=>{r=_},_=>{c(),i(_)})})}u(Ln,"waitRun");async function Cn(e,t,s=le,n=!0,d){const l=e.status==="canceled"||e.outcome_reason==="closed",i=e.grantee??"app:terminal",r=G("sha256").update(JSON.stringify(["run.message",e.node_id,t,n])).digest("hex"),c=u(async g=>{const o=await O(e.node_id),_=await(await I()).prepare("SELECT 1 FROM deliveries WHERE message_id = ? AND state = 'pending' AND canceled_at IS NULL").get(String(g.message_id));return o&&!l&&n&&!o.pi_pid&&_&&await P(e.node_id,{resume:!0,capacity:"freeze"}),g},"replay");if(d){const g=await q(i,d,r);if(g)return c(g.response)}if(l)throw new N(409,"run_settled","canceled run cannot receive a message");const m=await s(e.node_id,i,t),h=n&&e.final_report&&!e.pi_pid?(await import("../runtime/reopen.js")).commitReopenResident:void 0;let E;try{E=await W(async g=>{if(d){const y=await q(i,d,r,g);if(y)return{replayed:y.response}}await h?.(e.node_id);const o=await we(g,e.node_id,i,m,n),_={run_id:e.node_id,message_id:o.messageId,sequence_number:o.sequence};return d&&await fe(g,i,d,r,e.node_id,_,new Date().toISOString()),{result:_}})}catch(g){throw m.cleanup(),g}return"replayed"in E?(m.cleanup(),c(E.replayed)):(n&&!e.pi_pid&&await P(e.node_id,{resume:!0,capacity:"freeze"}),E.result)}u(Cn,"messageRun");async function Nt(e){const t=u(()=>new N(503,"service_unavailable",`node ${e} broker was unavailable before the interrupt reached it`),"unavailable");for(let s=0;s<2;s++){const n=await O(e);if(!n)throw J();if(!ee(n)){if(n.streaming)throw t();return}const d=(await V(e))?.executionId;try{await Qe(e)==="turn"&&ue({nodes:[e]});return}catch(l){if(!(l instanceof ze))throw l;const i=await O(e);if(!i)throw J();if(!i.streaming)return;if(s===0&&ee(i)&&(await V(e))?.executionId!==d)continue;throw t()}}throw t()}u(Nt,"interruptNode");async function kn(e,t="stop"){const s=t==="stop"?(await(await I()).prepare("SELECT node_id FROM nodes WHERE run_id = ?").all(e.node_id)).map(({node_id:n})=>n):[e.node_id];return await Promise.all(s.map(n=>Nt(n))),await x(await O(e.node_id)??e)}u(kn,"interruptRun");async function xn(e,t={}){const s=(await(await I()).prepare("SELECT node_id FROM nodes WHERE run_id = ? ORDER BY created DESC").all(e.node_id)).map(i=>i.node_id);ue({run:e.node_id});const n=[];if(await C(e)!=="settled")n.push(...(await ae(e.node_id,{preserveEmpty:!0,stopReason:"run_canceled"})).closed);else for(const i of s){if(i===e.node_id)continue;const r=await O(i);r&&r.status!=="done"&&r.status!=="canceled"&&r.status!=="dead"&&n.push(...(await ae(i,{preserveEmpty:!0,stopReason:"run_canceled"})).closed)}if(await re({run_id:e.node_id},"the run was canceled"),(await Promise.all([...new Set([e.node_id,...n])].map(i=>K(i,"run_canceled")))).some(i=>!i.confirmed))throw new N(500,"server_error","run process teardown could not be confirmed",void 0,void 0,void 0,!0);const l=await O(e.node_id);return await x(l??e)}u(xn,"cancelRun");const ye=200;async function Wn(e,t){if(typeof t!="string"||!t.trim())throw S("name is required","name");const s=t.trim();if(s.length>ye)throw S(`name exceeds ${ye} characters`,"name");const n=await qe(e.node_id,{name:s});return n.window&&Ue(n.window,He(n)),await x(n)}u(Wn,"renameRun");async function Fn(e,t={config:Et,client:gt}){await re({run_id:e.node_id},"the run was deleted");const s=await W(async c=>(await c.prepare("UPDATE nodes SET deleting_at = COALESCE(deleting_at, ?) WHERE node_id = ?").run(new Date().toISOString(),e.node_id),(await c.prepare("SELECT node_id FROM nodes WHERE run_id = ? ORDER BY created DESC").all(e.node_id)).map(m=>m.node_id)));if((await Promise.all(s.map(c=>K(c,"run_deleted",{deleting:!0})))).some(c=>!c.confirmed))throw new N(500,"server_error","run process teardown could not be confirmed",void 0,void 0,void 0,!0);const d=await k(s,async c=>{const m=await We(c);if(m.app===null)throw new Error(`run node missing during deletion: ${c}`);return m}),l=await(await I()).prepare("SELECT DISTINCT session_id FROM sessions WHERE session_id IS NOT NULL AND node_id IN (SELECT node_id FROM nodes WHERE run_id = ?)").all(e.node_id);for(const{session_id:c}of l)try{await Z().delete(c)}catch(m){if(!Be(m))throw m}const i=await W(async c=>{for(const g of s){const o=await xe(c,g);o!==null&&o.deleted_at===null&&await ke(c,o)}const m=await ht([e.node_id],c);await c.prepare("DELETE FROM run_events WHERE run_id = ?").run(e.node_id),await c.prepare("DELETE FROM idempotency_keys WHERE run_id = ?").run(e.node_id);const h=s.map(()=>"?").join(","),E=await c.prepareUncached(`SELECT message_id FROM messages WHERE sender_node_id IN (${h}) UNION SELECT message_id FROM deliveries WHERE destination_id IN (${h})`).all(...s,...s);await c.prepareUncached(`DELETE FROM deliveries WHERE destination_id IN (${h})`).run(...s);for(const{message_id:g}of E)await c.prepare("DELETE FROM messages WHERE message_id = ? AND NOT EXISTS (SELECT 1 FROM deliveries WHERE message_id = ?)").run(g,g);return m});for(const c of d)await Fe(c);const{notifyRunDeleted:r}=await import("./events.js");return r(e.node_id),{uploads_pending:await vt(i,t)}}u(Fn,"deleteRun");async function vt(e,t){if(!e.length||!t.config())return e.length;let s;try{s=t.client()}catch{return e.length}const n=new Set,d=e.map(i=>s.deleteUpload(i).then(async()=>{await yt(i),n.add(i)},()=>{}));let l;return await Promise.race([Promise.all(d),new Promise(i=>{l=setTimeout(i,t.budgetMs??Rt),l.unref?.()})]),clearTimeout(l),e.length-n.size}u(vt,"deleteReleasedUploads");async function qn(e,t,s){await F(e,t),await Q(e);const n=await W(async o=>{const _=await o.prepare("SELECT node_id, parent FROM nodes WHERE run_id = ? ORDER BY CASE WHEN node_id = ? THEN 0 ELSE 1 END, created, node_id").all(e,e),y=new Map;for(const R of _)y.set(R.node_id,(await o.prepare("SELECT session_id FROM sessions WHERE node_id = ? GROUP BY session_id ORDER BY min(created_at)").all(R.node_id)).map(A=>A.session_id));const p=(await o.prepare("SELECT event_cursor FROM nodes WHERE node_id = ?").get(e)).event_cursor-1,D=await o.prepare(`SELECT node_id, sequence_number FROM run_events
10
+ ORDER BY activity DESC, node_id DESC`).all(...e===null?[]:[e]),o=await le(await k((await le(n,async({node_id:r})=>!t.visible||await t.visible(r))).filter(({activity:r,node_id:c})=>!s||r<s.activity||r===s.activity&&c<s.id),async r=>({root:await b(r.node_id),activity:r.activity})),async({root:r})=>!t.status||await C(r)===t.status),m=o.slice(0,t.limit),i=m.at(-1);return{runs:await k(m,async({root:r})=>await x(r)),next:o.length>t.limit&&i?Buffer.from(JSON.stringify({activity:i.activity,id:i.root.node_id})).toString("base64url"):null}}u(kn,"listRuns");async function xn(e,t,s){const n=await F(e,t),o=u(async()=>await x(await F(e,t)),"read");return!s||_e.includes(await C(n))?await o():new Promise((m,i)=>{let r=u(()=>{},"unsubscribe");const c=u(()=>{clearTimeout(d),clearInterval(y),r()},"settle"),l=u(async()=>{c();try{m(await o())}catch(f){i(f)}},"finish"),g=u(async()=>{_e.includes(String((await o()).status))&&await l()},"check"),E=u(()=>{g().catch(f=>{c(),i(f)})},"run"),y=setInterval(E,250),d=setTimeout(()=>{l()},s*1e3);pt(e,E).then(f=>{r=f},f=>{c(),i(f)})})}u(xn,"waitRun");const Ot=5;async function Wn(e,t,s=pe,n=!0,o){const m=e.status==="canceled"||e.outcome_reason==="closed",i=e.grantee??"app:terminal",r=z("sha256").update(JSON.stringify(["run.message",e.node_id,t,n])).digest("hex"),c=u(async g=>{const E=await b(e.node_id),y=await(await A()).prepare("SELECT 1 FROM deliveries WHERE message_id = ? AND state = 'pending' AND canceled_at IS NULL").get(String(g.message_id));return E&&!m&&n&&!E.pi_pid&&y&&await $(e.node_id,{resume:!0,capacity:"freeze"}),g},"replay");if(o){const g=await q(i,o,r);if(g)return c(g.response)}if(m)throw new S(409,"run_settled","canceled run cannot receive a message");const l=n&&e.final_report&&!e.pi_pid?(await import("../runtime/reopen.js")).commitReopenResident:void 0;for(let g=1;;g++){const E=await s(e.node_id,i,t),y=await W(async d=>{if(o){const a=await q(i,o,r,d);if(a)return{replayed:a.response}}if(E.uses.length){await lt(d,e.node_id);for(const a of E.uses)if(await St(e.node_id,a.path,d))return"path_taken"}await l?.(e.node_id);const f=await ge(d,e.node_id,i,E,n),h={run_id:e.node_id,message_id:f.messageId,sequence_number:f.sequence};return o&&await we(d,i,o,r,e.node_id,h,new Date().toISOString()),{result:h}});if(y==="path_taken"){if(g>=Ot)throw new S(503,"service_unavailable","attachments of concurrent messages kept taking each other's file names; retry");continue}return"replayed"in y?c(y.replayed):(n&&!e.pi_pid&&await $(e.node_id,{resume:!0,capacity:"freeze"}),y.result)}}u(Wn,"messageRun");async function bt(e){const t=u(()=>new S(503,"service_unavailable",`node ${e} broker was unavailable before the interrupt reached it`),"unavailable");for(let s=0;s<2;s++){const n=await b(e);if(!n)throw Y();if(!te(n)){if(n.streaming)throw t();return}const o=(await Z(e))?.executionId;try{await Qe(e)==="turn"&&me({nodes:[e]});return}catch(m){if(!(m instanceof ze))throw m;const i=await b(e);if(!i)throw Y();if(!i.streaming)return;if(s===0&&te(i)&&(await Z(e))?.executionId!==o)continue;throw t()}}throw t()}u(bt,"interruptNode");async function Fn(e,t="stop"){const s=t==="stop"?(await(await A()).prepare("SELECT node_id FROM nodes WHERE run_id = ?").all(e.node_id)).map(({node_id:n})=>n):[e.node_id];return await Promise.all(s.map(n=>bt(n))),await x(await b(e.node_id)??e)}u(Fn,"interruptRun");async function qn(e,t={}){const s=(await(await A()).prepare("SELECT node_id FROM nodes WHERE run_id = ? ORDER BY created DESC").all(e.node_id)).map(i=>i.node_id);me({run:e.node_id});const n=[];if(await C(e)!=="settled")n.push(...(await ie(e.node_id,{preserveEmpty:!0,stopReason:"run_canceled"})).closed);else for(const i of s){if(i===e.node_id)continue;const r=await b(i);r&&r.status!=="done"&&r.status!=="canceled"&&r.status!=="dead"&&n.push(...(await ie(i,{preserveEmpty:!0,stopReason:"run_canceled"})).closed)}if(await oe({run_id:e.node_id},"the run was canceled"),(await Promise.all([...new Set([e.node_id,...n])].map(i=>ee(i,"run_canceled")))).some(i=>!i.confirmed))throw new S(500,"server_error","run process teardown could not be confirmed",void 0,void 0,void 0,!0);const m=await b(e.node_id);return await x(m??e)}u(qn,"cancelRun");const he=200;async function Hn(e,t){if(typeof t!="string"||!t.trim())throw N("name is required","name");const s=t.trim();if(s.length>he)throw N(`name exceeds ${he} characters`,"name");const n=await qe(e.node_id,{name:s});return n.window&&Ue(n.window,He(n)),await x(n)}u(Hn,"renameRun");async function Un(e,t={config:yt,client:Et}){await oe({run_id:e.node_id},"the run was deleted");const s=await W(async c=>(await c.prepare("UPDATE nodes SET deleting_at = COALESCE(deleting_at, ?) WHERE node_id = ?").run(new Date().toISOString(),e.node_id),(await c.prepare("SELECT node_id FROM nodes WHERE run_id = ? ORDER BY created DESC").all(e.node_id)).map(l=>l.node_id)));if((await Promise.all(s.map(c=>ee(c,"run_deleted",{deleting:!0})))).some(c=>!c.confirmed))throw new S(500,"server_error","run process teardown could not be confirmed",void 0,void 0,void 0,!0);const o=await k(s,async c=>{const l=await We(c);if(l.app===null)throw new Error(`run node missing during deletion: ${c}`);return l}),m=await(await A()).prepare("SELECT DISTINCT session_id FROM sessions WHERE session_id IS NOT NULL AND node_id IN (SELECT node_id FROM nodes WHERE run_id = ?)").all(e.node_id);for(const{session_id:c}of m)try{await K().delete(c)}catch(l){if(!Pe(l))throw l}const i=await W(async c=>{for(const y of s){const d=await xe(c,y);d!==null&&d.deleted_at===null&&await ke(c,d)}const l=await Rt([e.node_id],c);await c.prepare("DELETE FROM run_events WHERE run_id = ?").run(e.node_id),await c.prepare("DELETE FROM idempotency_keys WHERE run_id = ?").run(e.node_id);const g=s.map(()=>"?").join(","),E=await c.prepareUncached(`SELECT message_id FROM messages WHERE sender_node_id IN (${g}) UNION SELECT message_id FROM deliveries WHERE destination_id IN (${g})`).all(...s,...s);await c.prepareUncached(`DELETE FROM deliveries WHERE destination_id IN (${g})`).run(...s);for(const{message_id:y}of E)await c.prepare("DELETE FROM messages WHERE message_id = ? AND NOT EXISTS (SELECT 1 FROM deliveries WHERE message_id = ?)").run(y,y);return l});for(const c of o)await Fe(c);const{notifyRunDeleted:r}=await import("./events.js");return r(e.node_id),{uploads_pending:await Dt(i,t)}}u(Un,"deleteRun");async function Dt(e,t){if(!e.length||!t.config())return e.length;let s;try{s=t.client()}catch{return e.length}const n=new Set,o=e.map(i=>s.deleteUpload(i).then(async()=>{await ht(i),n.add(i)},()=>{}));let m;return await Promise.race([Promise.all(o),new Promise(i=>{m=setTimeout(i,t.budgetMs??Nt),m.unref?.()})]),clearTimeout(m),e.length-n.size}u(Dt,"deleteReleasedUploads");async function Pn(e,t,s){await F(e,t),await V(e);const n=await W(async d=>{const f=await d.prepare("SELECT node_id, parent FROM nodes WHERE run_id = ? ORDER BY CASE WHEN node_id = ? THEN 0 ELSE 1 END, created, node_id").all(e,e),h=new Map;for(const R of f)h.set(R.node_id,(await d.prepare("SELECT session_id FROM sessions WHERE node_id = ? GROUP BY session_id ORDER BY min(created_at)").all(R.node_id)).map(I=>I.session_id));const p=(await d.prepare("SELECT event_cursor FROM nodes WHERE node_id = ?").get(e)).event_cursor-1,D=await d.prepare(`SELECT node_id, sequence_number FROM run_events
11
11
  WHERE run_id = ? AND sequence_number <= ? AND type IN ('node.thinking.done', 'node.output_text.done', 'usage')
12
- ORDER BY sequence_number`).all(e,p),v=await o.prepare(`SELECT node_id, sequence_number, type, body_json FROM run_events
12
+ ORDER BY sequence_number`).all(e,p),v=await d.prepare(`SELECT node_id, sequence_number, type, body_json FROM run_events
13
13
  WHERE run_id = ? AND sequence_number <= ? AND type IN ('node.thinking.delta', 'node.output_text.delta')
14
- ORDER BY sequence_number`).all(e,p);return{nodes:_,sessionIds:y,latestSequence:p,completed:D,deltas:v}}),{nodes:d,sessionIds:l,latestSequence:i,completed:r,deltas:c}=n,m=await k(d,async o=>({node_id:o.node_id,parent_node_id:o.parent,conversations:await k(l.get(o.node_id)??[],async _=>{const{header:y,entries:a}=await Z().read(_);if(s==="entries")return{conversation_id:_,header:y,entries:a};const p=Ce.inMemory(y.cwd,void 0,[y,...a]),D=rt(p)??[],v=new Map(a.map((w,b)=>[w.id,b])),R=a.filter(w=>w.type==="custom"&&w.customType==="crtr-system-prompt").map(w=>({id:w.id,message:{role:"custom",customType:"crtr-system-prompt",data:"data"in w?w.data:void 0,timestamp:w.timestamp}})),A=a.filter(w=>w.type==="custom_message"&&w.customType==="app_message").map(w=>({id:w.id,message:{role:"custom",customType:"app_message",content:"content"in w?w.content:"",timestamp:w.timestamp}})),he=o.node_id===e?a.find(w=>{if(w.type!=="message"||w.message.role!=="user")return!1;const b=te(a,w.message.timestamp);return b?.type==="runtime"&&b.kind==="kickoff"})?.id:void 0,Re=[...D.filter(({id:w})=>!A.some(b=>b.id===w)),...R,...A].sort((w,b)=>(v.get(w.id)??Number.MAX_SAFE_INTEGER)-(v.get(b.id)??Number.MAX_SAFE_INTEGER)).map(({id:w,message:b})=>{const f=b,T=f.usage,H=f.role==="user"?te(a,Number(f.timestamp)):null,Se=H?.type==="human"||w===he,L=f.role==="toolResult"?"tool_result":f.role==="bashExecution"?"bash_execution":f.role==="compactionSummary"?"compaction_summary":f.role==="branchSummary"?"branch_summary":f.role==="custom"&&f.customType==="crtr-system-prompt"?"system":f.role==="user"?Se?"user":"custom":f.role,Ne=L==="custom"?f.role==="custom"?f.customType:H?.type==="runtime"?H.kind:"unknown":void 0,ve=L==="system"&&f.customType==="crtr-system-prompt"?[{type:"text",text:f.data?.text??""}]:typeof f.content=="string"?[{type:"text",text:f.content}]:Array.isArray(f.content)?f.content.map(M=>M.type==="toolCall"?{type:"tool_call",tool_call_id:M.id,name:M.name,arguments:M.arguments}:M.type==="image"?{type:"image",mime_type:M.mimeType}:M.type==="thinking"?{type:"thinking",text:M.thinking}:M):[];return{entry_id:w,role:L,...L==="custom"?{custom_type:Ne}:{},time:typeof f.timestamp=="string"?f.timestamp:new Date(Number(f.timestamp??Date.now())).toISOString(),content:ve,...L==="assistant"?{model:f.model,provider:f.provider,stop_reason:f.stopReason,...f.errorMessage?{error_message:f.errorMessage}:{},...T?{usage:{input_tokens:T.input??0,output_tokens:T.output??0,cache_read_tokens:T.cacheRead??0,cache_write_tokens:T.cacheWrite??0,cost_usd:T.cost?.total??0}}:{}}:{},...L==="tool_result"?{tool_call_id:f.toolCallId,tool_name:f.toolName,is_error:f.isError}:{}}})??[];return{conversation_id:_,messages:Re}})})),h=new Map(m.map(o=>[o.node_id,ut(o.node_id)]));for(const o of r){const _=h.get(o.node_id);_!=null&&o.sequence_number>=_&&h.set(o.node_id,null)}const E=new Map;for(const o of c){const _=h.get(o.node_id);if(_==null||o.sequence_number<_)continue;const y=JSON.parse(o.body_json),a=E.get(o.node_id)??{thinking:"",text:""};o.type==="node.thinking.delta"?a.thinking+=y.delta:a.text+=y.delta,E.set(o.node_id,a)}const g=m.map(o=>({...o,in_progress_message:h.get(o.node_id)==null?null:E.get(o.node_id)??{thinking:"",text:""}}));return{run_id:e,latest_sequence:i,nodes:g}}u(qn,"traceRun");function Hn(e,t,s){if(t===void 0){if(!e.some(n=>U(n,"crtr:llm")))throw new N(403,"scope_missing","missing scope crtr:llm",void 0,void 0,"crtr:llm");return null}if(!Array.isArray(t)||t.some(n=>typeof n!="string"))throw S("scopes must be a list of scope strings","scopes");for(const n of t){try{mt(n)}catch{throw S(`invalid scope ${n}`,"scopes")}if(/^crtr:files:(?:read|rw):app:/.test(n)&&n.split(":")[4]===s.slice(4))throw S(`own-app files cannot narrow a run: ${n}`,"scopes");if(!(/^crtr:memory:(?:read|rw):app:/.test(n)&&n.split(":")[4]===s.slice(4))&&!be(e,n))throw new N(403,"scope_missing",`missing scope ${n}`,void 0,void 0,n)}if(!t.includes("crtr:llm"))throw new N(403,"scope_missing","missing scope crtr:llm",void 0,void 0,"crtr:llm");return t}u(Hn,"requestedScopes");export{X as IDEMPOTENCY_WINDOW_MS,St as RUN_DEADLINE_MAX_MS,Rt as RUN_DELETE_STORAGE_BUDGET_MS,ye as RUN_NAME_MAX,N as RunError,xn as cancelRun,Fn as deleteRun,Mn as idempotencyKeyOf,kn as interruptRun,Tn as listRuns,Cn as messageRun,F as ownedRun,Ee as parseRunDeadlineMs,In as pruneExpiredIdempotencyKeys,Wn as renameRun,Hn as requestedScopes,Dn as runIsRunning,x as runObject,An as startRun,qn as traceRun,Ln as waitRun};
14
+ ORDER BY sequence_number`).all(e,p);return{nodes:f,sessionIds:h,latestSequence:p,completed:D,deltas:v}}),{nodes:o,sessionIds:m,latestSequence:i,completed:r,deltas:c}=n,l=await k(o,async d=>({node_id:d.node_id,parent_node_id:d.parent,conversations:await k(m.get(d.node_id)??[],async f=>{const{header:h,entries:a}=await K().read(f);if(s==="entries")return{conversation_id:f,header:h,entries:a};const p=Ce.inMemory(h.cwd,void 0,[h,...a]),D=rt(p)??[],v=new Map(a.map((w,O)=>[w.id,O])),R=a.filter(w=>w.type==="custom"&&w.customType==="crtr-system-prompt").map(w=>({id:w.id,message:{role:"custom",customType:"crtr-system-prompt",data:"data"in w?w.data:void 0,timestamp:w.timestamp}})),I=a.filter(w=>w.type==="custom_message"&&w.customType==="app_message").map(w=>({id:w.id,message:{role:"custom",customType:"app_message",content:"content"in w?w.content:"",timestamp:w.timestamp}})),H=d.node_id===e?a.find(w=>{if(w.type!=="message"||w.message.role!=="user")return!1;const O=ne(a,w.message.timestamp);return O?.type==="runtime"&&O.kind==="kickoff"})?.id:void 0,Re=[...D.filter(({id:w})=>!I.some(O=>O.id===w)),...R,...I].sort((w,O)=>(v.get(w.id)??Number.MAX_SAFE_INTEGER)-(v.get(O.id)??Number.MAX_SAFE_INTEGER)).map(({id:w,message:O})=>{const _=O,T=_.usage,U=_.role==="user"?ne(a,Number(_.timestamp)):null,Se=U?.type==="human"||w===H,L=_.role==="toolResult"?"tool_result":_.role==="bashExecution"?"bash_execution":_.role==="compactionSummary"?"compaction_summary":_.role==="branchSummary"?"branch_summary":_.role==="custom"&&_.customType==="crtr-system-prompt"?"system":_.role==="user"?Se?"user":"custom":_.role,Ne=L==="custom"?_.role==="custom"?_.customType:U?.type==="runtime"?U.kind:"unknown":void 0,ve=L==="system"&&_.customType==="crtr-system-prompt"?[{type:"text",text:_.data?.text??""}]:typeof _.content=="string"?[{type:"text",text:_.content}]:Array.isArray(_.content)?_.content.map(M=>M.type==="toolCall"?{type:"tool_call",tool_call_id:M.id,name:M.name,arguments:M.arguments}:M.type==="image"?{type:"image",mime_type:M.mimeType}:M.type==="thinking"?{type:"thinking",text:M.thinking}:M):[];return{entry_id:w,role:L,...L==="custom"?{custom_type:Ne}:{},time:typeof _.timestamp=="string"?_.timestamp:new Date(Number(_.timestamp??Date.now())).toISOString(),content:ve,...L==="assistant"?{model:_.model,provider:_.provider,stop_reason:_.stopReason,..._.errorMessage?{error_message:_.errorMessage}:{},...T?{usage:{input_tokens:T.input??0,output_tokens:T.output??0,cache_read_tokens:T.cacheRead??0,cache_write_tokens:T.cacheWrite??0,cost_usd:T.cost?.total??0}}:{}}:{},...L==="tool_result"?{tool_call_id:_.toolCallId,tool_name:_.toolName,is_error:_.isError}:{}}})??[];return{conversation_id:f,messages:Re}})})),g=new Map(await Promise.all(l.map(async d=>[d.node_id,await ut(d.node_id)])));for(const d of r){const f=g.get(d.node_id);f!=null&&d.sequence_number>=f&&g.set(d.node_id,null)}const E=new Map;for(const d of c){const f=g.get(d.node_id);if(f==null||d.sequence_number<f)continue;const h=JSON.parse(d.body_json),a=E.get(d.node_id)??{thinking:"",text:""};d.type==="node.thinking.delta"?a.thinking+=h.delta:a.text+=h.delta,E.set(d.node_id,a)}const y=l.map(d=>({...d,in_progress_message:g.get(d.node_id)==null?null:E.get(d.node_id)??{thinking:"",text:""}}));return{run_id:e,latest_sequence:i,nodes:y}}u(Pn,"traceRun");function Bn(e,t,s){if(t===void 0){if(!e.some(n=>P(n,"crtr:llm")))throw new S(403,"scope_missing","missing scope crtr:llm",void 0,void 0,"crtr:llm");return null}if(!Array.isArray(t)||t.some(n=>typeof n!="string"))throw N("scopes must be a list of scope strings","scopes");for(const n of t){try{mt(n)}catch{throw N(`invalid scope ${n}`,"scopes")}if(/^crtr:files:(?:read|rw):app:/.test(n)&&n.split(":")[4]===s.slice(4))throw N(`own-app files cannot narrow a run: ${n}`,"scopes");if(!(/^crtr:memory:(?:read|rw):app:/.test(n)&&n.split(":")[4]===s.slice(4))&&!be(e,n))throw new S(403,"scope_missing",`missing scope ${n}`,void 0,void 0,n)}if(!t.includes("crtr:llm"))throw new S(403,"scope_missing","missing scope crtr:llm",void 0,void 0,"crtr:llm");return t}u(Bn,"requestedScopes");export{X as IDEMPOTENCY_WINDOW_MS,vt as RUN_DEADLINE_MAX_MS,Nt as RUN_DELETE_STORAGE_BUDGET_MS,he as RUN_NAME_MAX,S as RunError,qn as cancelRun,Un as deleteRun,Tn as idempotencyKeyOf,Fn as interruptRun,kn as listRuns,Wn as messageRun,F as ownedRun,ye as parseRunDeadlineMs,Ln as pruneExpiredIdempotencyKeys,Hn as renameRun,Bn as requestedScopes,In as runIsRunning,x as runObject,Cn as startRun,Pn as traceRun,xn as waitRun};
@@ -2,6 +2,6 @@ var b=Object.defineProperty;var a=(e,n)=>b(e,"name",{value:n,configurable:!0});i
2
2
  ${n?`A SCHEDULE woke you, not a message \u2014 a recurring cron firing ${r} revived you fresh. Nothing new happened on the canvas and nobody is waiting on a reply: the clock came round. Re-read your bearings below, do this cycle's pass of the standing job, and stop.`:"A SCHEDULE woke you, not a message \u2014 a one-shot cron armed to fire now revived you fresh. Nothing new happened on the canvas and nobody is waiting on a reply: the time you were waiting for arrived. Re-read your bearings below and continue from there."}
3
3
  </crtr-wake>`;const t=T(e);return`<crtr-wake>
4
4
  ${n?`You were BORN by a scheduled wake, not spawned on demand \u2014 a recurring spawn-cron armed by ${t}, firing ${r}. The runtime re-births a fresh node like you on this cadence whether or not earlier runs survived: you are one run of a standing job, not a one-off, and you inherit nothing from prior runs but this task. Your task follows.`:`You were BORN by a scheduled wake, not spawned on demand \u2014 a one-shot deferred birth armed by ${t} to fire now. You are its only run, not a recurring job. Your task follows.`}
5
- </crtr-wake>`}a(q,"buildWakeBearings");function D(e){return O(e?.managed_worktree)}a(D,"managedWorktreeNote");async function W(e,n,r){const t=await i(e),o=["<crtr-bearings>",await R(e)],s=await B(e);s!==""&&o.push("","## Your place in the canvas",s),o.push("","## Your documents and context directory",f(e,t?.grantee));const u=await A(e);u!==""&&o.push("",u);const c=D(t);c!==""&&o.push("","## Your managed worktree",c),t?.mode==="orchestrator"&&o.push("",p()),o.push("</crtr-bearings>");const h=_(e)??"",m=t?.cwd!==void 0?w(t.cwd):"";return[o.join(`
5
+ </crtr-wake>`}a(q,"buildWakeBearings");function D(e){return O(e?.managed_worktree)}a(D,"managedWorktreeNote");async function W(e,n,r){const t=await i(e),o=["<crtr-bearings>",await R(e)],s=await B(e);s!==""&&o.push("","## Your place in the canvas",s),o.push("","## Your documents and context directory",f(e,t?.grantee));const u=await A(e);u!==""&&o.push("",u);const c=D(t);c!==""&&o.push("","## Your managed worktree",c),t?.mode==="orchestrator"&&o.push("",p()),o.push("</crtr-bearings>");const h=await _(e)??"",m=t?.cwd!==void 0?w(t.cwd):"";return[o.join(`
6
6
  `),n,r,h,m].filter(y=>y!=="").join(`
7
7
  `)}a(W,"bearingsShell");async function z(e,n){const r=await v(n),t=await x(n);return{content:await W(e,r.content,t.content),delivered:[...r.delivered,...t.delivered]}}a(z,"buildContextBearings");export{V as CONTEXT_INTRO_CUSTOM_TYPE,z as buildContextBearings,B as buildGraphMap,w as buildProjectContextBlock,q as buildWakeBearings,f as contextDirNote,K as cronWakeOrigin,p as orchestratorContextNote,A as profileNote};
@@ -0,0 +1,5 @@
1
+ /** Download every attachment of this node's run that is not already on the broker's disk (D98). The control plane puts
2
+ * each fetched upload in the blob store and records it on the run; the files are written where the run's prompt names
3
+ * them. Run before the broker hands the agent a prompt or mail. A failed download throws: the agent must not be told
4
+ * of a path that holds nothing. */
5
+ export declare function fetchRunAttachments(nodeId: string): Promise<void>;
@@ -0,0 +1 @@
1
+ var r=Object.defineProperty;var i=(a,e)=>r(a,"name",{value:e,configurable:!0});import{existsSync as s,mkdirSync as m,renameSync as h,writeFileSync as p}from"node:fs";import{dirname as f}from"node:path";import{daemonClient as l}from"./daemon-ops.js";async function w(a){const e=l(),{attachments:c}=await e.listNodeAttachments(a);for(const t of c){if(s(t.path))continue;const o=await e.readNodeAttachment(a,t.sha256);m(f(t.path),{recursive:!0});const n=`${t.path}.partial`;p(n,o),h(n,t.path)}}i(w,"fetchRunAttachments");export{w as fetchRunAttachments};
@@ -1,6 +1,8 @@
1
1
  import { type BashJobPaths } from '../../bash-jobs.js';
2
- /** True when jobs are started by the daemon's launcher rather than this process. */
3
- export declare const BASH_JOBS_USE_LAUNCHER: boolean;
2
+ /** True when the daemon's launcher starts jobs rather than this process: a Linux broker that shares the API host's
3
+ * launcher. A sandbox broker (`CRTR_API_URL` set) runs on another machine, so it spawns its supervisor itself
4
+ * and reports the job through `report`. */
5
+ export declare function bashJobsUseLauncher(): boolean;
4
6
  /** Start the supervisor for a job whose `cmd.sh` and `job.log` are already written.
5
7
  * Resolves with the supervisor's process group and its launch-time identity, which
6
8
  * lets a later cancellation reject a stale pid; it is not a containment guarantee. */