@north-light/cli 0.3.560 → 0.3.562

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (573) hide show
  1. package/dist/api/client.d.ts +27 -4
  2. package/dist/api/client.js +3 -3
  3. package/dist/api/contract.d.ts +1 -1
  4. package/dist/api/contract.js +1 -1
  5. package/dist/api/dto/bash-jobs.d.ts +5 -1
  6. package/dist/api/dto/broker-ops.d.ts +25 -1
  7. package/dist/api/dto/charges.d.ts +9 -2
  8. package/dist/api/dto/delivery.d.ts +26 -2
  9. package/dist/api/dto/execution-start.d.ts +57 -0
  10. package/dist/api/dto/execution-start.js +0 -0
  11. package/dist/api/dto/modelauth.d.ts +5 -0
  12. package/dist/api/dto/node-records.d.ts +16 -0
  13. package/dist/api/dto/objects.d.ts +1 -1
  14. package/dist/api/dto/reports.d.ts +0 -3
  15. package/dist/api/dto/run-events.d.ts +7 -1
  16. package/dist/api/dto/settings.d.ts +55 -0
  17. package/dist/api/dto/settings.js +0 -0
  18. package/dist/api/index.d.ts +2 -0
  19. package/dist/api/index.js +1 -1
  20. package/dist/api/routes.d.ts +11 -0
  21. package/dist/api/routes.js +1 -1
  22. package/dist/builtin-memory/crouter-sdk/release-notes.md +4 -0
  23. package/dist/cli.js +7 -7
  24. package/dist/clients/attach/chrome/bash-jobs.d.ts +11 -1
  25. package/dist/clients/attach/chrome/bash-jobs.js +1 -1
  26. package/dist/clients/attach/chrome/canvas-panels.d.ts +1 -1
  27. package/dist/clients/attach/chrome/roster.js +6 -4
  28. package/dist/clients/attach/overlays/auth.js +2 -2
  29. package/dist/clients/attach/render/chat-view.js +1 -1
  30. package/dist/clients/attach/viewer.js +550 -567
  31. package/dist/commands/canvas-config.js +2 -2
  32. package/dist/commands/canvas-use.js +1 -1
  33. package/dist/commands/human.js +2 -2
  34. package/dist/commands/node/bash.js +3 -3
  35. package/dist/commands/node/create.js +2 -2
  36. package/dist/commands/person-settings.d.ts +1 -0
  37. package/dist/commands/person-settings.js +1 -0
  38. package/dist/commands/pkg/market-manage.d.ts +2 -2
  39. package/dist/commands/pkg/market-manage.js +1 -1
  40. package/dist/commands/pkg/plugin-manage.js +13 -13
  41. package/dist/commands/pkg/shared.js +1 -1
  42. package/dist/commands/profile/default.js +1 -1
  43. package/dist/commands/push.js +2 -3
  44. package/dist/commands/sys/config.js +1 -1
  45. package/dist/commands/sys/connect.js +1 -1
  46. package/dist/commands/sys/context/sysprompt.js +2 -2
  47. package/dist/commands/sys/doctor.js +1 -1
  48. package/dist/commands/sys/panels/broker-limits-panel.js +1 -1
  49. package/dist/commands/sys/panels/keybindings-panel.js +1 -1
  50. package/dist/commands/sys/panels/models-panel.d.ts +8 -2
  51. package/dist/commands/sys/panels/models-panel.js +1 -1
  52. package/dist/commands/sys/panels/prefs-panel.d.ts +1 -0
  53. package/dist/commands/sys/panels/prefs-panel.js +1 -1
  54. package/dist/commands/sys/panels/profiles-panel.js +1 -1
  55. package/dist/commands/sys/panels/provider-panel.d.ts +4 -0
  56. package/dist/commands/sys/panels/provider-panel.js +1 -1
  57. package/dist/commands/sys/provider-login.js +5 -5
  58. package/dist/commands/sys/setup-core.js +3 -3
  59. package/dist/commands/sys/setup-settings-runner.js +1 -1
  60. package/dist/commands/sys/spend.js +3 -3
  61. package/dist/commands/sys/update.js +1 -1
  62. package/dist/core/auth-file.d.ts +11 -19
  63. package/dist/core/auth-file.js +1 -2
  64. package/dist/core/auto-update.d.ts +1 -1
  65. package/dist/core/auto-update.js +4 -4
  66. package/dist/core/bash-jobs.d.ts +29 -71
  67. package/dist/core/bash-jobs.js +9 -10
  68. package/dist/core/blobs/directory.d.ts +3 -0
  69. package/dist/core/blobs/directory.js +1 -0
  70. package/dist/core/blobs/fault.d.ts +3 -0
  71. package/dist/core/blobs/fault.js +1 -0
  72. package/dist/core/blobs/index.d.ts +21 -0
  73. package/dist/core/blobs/index.js +1 -0
  74. package/dist/core/blobs/r2.d.ts +9 -0
  75. package/dist/core/blobs/r2.js +4 -0
  76. package/dist/core/bootstrap.d.ts +1 -1
  77. package/dist/core/bootstrap.js +2 -2
  78. package/dist/core/canvas/canvas.d.ts +9 -7
  79. package/dist/core/canvas/canvas.js +8 -8
  80. package/dist/core/canvas/crons.d.ts +3 -2
  81. package/dist/core/canvas/crons.js +3 -3
  82. package/dist/core/canvas/daemon-owner.d.ts +5 -0
  83. package/dist/core/canvas/daemon-owner.js +1 -1
  84. package/dist/core/canvas/db.d.ts +10 -9
  85. package/dist/core/canvas/db.js +4 -4
  86. package/dist/core/canvas/executions.d.ts +100 -4
  87. package/dist/core/canvas/executions.js +1 -1
  88. package/dist/core/canvas/export-sqlite.js +1 -1
  89. package/dist/core/canvas/focuses.d.ts +4 -0
  90. package/dist/core/canvas/focuses.js +1 -1
  91. package/dist/core/canvas/history.js +9 -9
  92. package/dist/core/canvas/managed-worktree-sweep-candidates.d.ts +2 -1
  93. package/dist/core/canvas/managed-worktree-sweep-candidates.js +3 -2
  94. package/dist/core/canvas/node-tokens.d.ts +1 -4
  95. package/dist/core/canvas/node-tokens.js +3 -3
  96. package/dist/core/canvas/paths.d.ts +0 -1
  97. package/dist/core/canvas/paths.js +1 -1
  98. package/dist/core/canvas/person-state.d.ts +26 -0
  99. package/dist/core/canvas/person-state.js +1 -0
  100. package/dist/core/canvas/person.d.ts +3 -10
  101. package/dist/core/canvas/person.js +7 -7
  102. package/dist/core/canvas/reconciler-leases.d.ts +12 -0
  103. package/dist/core/canvas/reconciler-leases.js +8 -0
  104. package/dist/core/canvas/recovery.d.ts +4 -0
  105. package/dist/core/canvas/recovery.js +1 -1
  106. package/dist/core/canvas/schema-pg/003-fleet-removals.sql +1 -1
  107. package/dist/core/canvas/schema-pg/005-fleet-blobs.sql +13 -0
  108. package/dist/core/canvas/schema-pg/006-job-rows.sql +20 -0
  109. package/dist/core/canvas/schema-pg/007-ledger-check.sql +117 -0
  110. package/dist/core/canvas/schema-version.d.ts +1 -1
  111. package/dist/core/canvas/schema-version.js +1 -1
  112. package/dist/core/canvas/sessions.d.ts +8 -11
  113. package/dist/core/canvas/sessions.js +1 -4
  114. package/dist/core/canvas/tree.d.ts +4 -2
  115. package/dist/core/canvas/tree.js +6 -6
  116. package/dist/core/canvas/types.d.ts +7 -0
  117. package/dist/core/command-hooks/transport/exec-lifecycle.js +1 -1
  118. package/dist/core/command-plugins/bundle.d.ts +1 -1
  119. package/dist/core/command-plugins/bundle.js +1 -1
  120. package/dist/core/command-plugins/compose.d.ts +1 -1
  121. package/dist/core/command-plugins/discovery.d.ts +0 -1
  122. package/dist/core/command-plugins/discovery.js +1 -1
  123. package/dist/core/command-plugins/help-addenda.js +1 -1
  124. package/dist/core/command-plugins/presence.d.ts +2 -0
  125. package/dist/core/command-plugins/presence.js +1 -1
  126. package/dist/core/config.d.ts +16 -15
  127. package/dist/core/config.js +1 -1
  128. package/dist/core/conversation-store/client-worker.js +1 -1
  129. package/dist/core/conversation-store/client.js +2 -2
  130. package/dist/core/conversation-store/index.d.ts +9 -11
  131. package/dist/core/conversation-store/index.js +1 -1
  132. package/dist/core/conversation-store/patch.js +1 -1
  133. package/dist/core/conversation-store/row-store.d.ts +14 -0
  134. package/dist/core/conversation-store/row-store.js +13 -0
  135. package/dist/core/directory/join.js +1 -1
  136. package/dist/core/env-name.d.ts +1 -0
  137. package/dist/core/env-name.js +1 -1
  138. package/dist/core/environment-recipe.d.ts +15 -0
  139. package/dist/core/environment-recipe.js +1 -0
  140. package/dist/core/environments.js +1 -1
  141. package/dist/core/events/emit.js +2 -2
  142. package/dist/core/events/run-event-chunks.d.ts +25 -0
  143. package/dist/core/events/run-event-chunks.js +5 -0
  144. package/dist/core/feed/messages.js +5 -5
  145. package/dist/core/grants/mirror.d.ts +15 -0
  146. package/dist/core/grants/mirror.js +15 -3
  147. package/dist/core/grants/on-sync.d.ts +9 -5
  148. package/dist/core/grants/on-sync.js +1 -1
  149. package/dist/core/grants/remove.d.ts +1 -6
  150. package/dist/core/grants/remove.js +1 -1
  151. package/dist/core/grants/sync.js +1 -1
  152. package/dist/core/grants/watch.d.ts +15 -9
  153. package/dist/core/grants/watch.js +1 -1
  154. package/dist/core/graph/custom.js +8 -8
  155. package/dist/core/graph/jobs.d.ts +83 -5
  156. package/dist/core/graph/jobs.js +11 -2
  157. package/dist/core/graph/kinds/job.js +2 -2
  158. package/dist/core/graph/names.js +7 -7
  159. package/dist/core/graph/objects.d.ts +5 -1
  160. package/dist/core/graph/objects.js +11 -11
  161. package/dist/core/graph/reader.d.ts +3 -0
  162. package/dist/core/graph/reader.js +3 -3
  163. package/dist/core/graph/repo-sync/identity.d.ts +3 -1
  164. package/dist/core/graph/repo-sync/identity.js +1 -1
  165. package/dist/core/graph/repo-sync/repos.d.ts +1 -1
  166. package/dist/core/graph/repo-sync/repos.js +2 -2
  167. package/dist/core/graph/repo-sync/sync.js +2 -2
  168. package/dist/core/installed-plugins.js +1 -1
  169. package/dist/core/keybindings/persistence.d.ts +1 -1
  170. package/dist/core/keybindings/persistence.js +1 -1
  171. package/dist/core/layout-migrate/loose-keys.d.ts +1 -1
  172. package/dist/core/layout-migrate/loose-keys.js +1 -1
  173. package/dist/core/ledger/account.d.ts +12 -0
  174. package/dist/core/ledger/account.js +2 -0
  175. package/dist/core/ledger/charges.d.ts +2 -2
  176. package/dist/core/ledger/charges.js +1 -1
  177. package/dist/core/ledger/check.d.ts +5 -1
  178. package/dist/core/ledger/check.js +1 -7
  179. package/dist/core/ledger/chunks.d.ts +8 -0
  180. package/dist/core/ledger/chunks.js +2 -0
  181. package/dist/core/ledger/index.d.ts +2 -1
  182. package/dist/core/ledger/index.js +1 -1
  183. package/dist/core/ledger/infra-allowance.d.ts +9 -0
  184. package/dist/core/ledger/infra-allowance.js +1 -0
  185. package/dist/core/ledger/limits.js +3 -3
  186. package/dist/core/ledger/payer.d.ts +1 -1
  187. package/dist/core/ledger/payer.js +1 -1
  188. package/dist/core/ledger/read.d.ts +14 -4
  189. package/dist/core/ledger/read.js +2 -3
  190. package/dist/core/ledger/totals.d.ts +5 -16
  191. package/dist/core/ledger/totals.js +4 -4
  192. package/dist/core/ledger/types.d.ts +12 -3
  193. package/dist/core/llm/run.js +2 -2
  194. package/dist/core/managed-providers.d.ts +72 -0
  195. package/dist/core/managed-providers.js +1 -0
  196. package/dist/core/model-auth/api-credential-store.d.ts +10 -0
  197. package/dist/core/model-auth/api-credential-store.js +1 -0
  198. package/dist/core/model-auth/daemon-login.d.ts +1 -1
  199. package/dist/core/model-auth/daemon-login.js +1 -1
  200. package/dist/core/model-auth/flows.d.ts +5 -4
  201. package/dist/core/model-auth/flows.js +1 -1
  202. package/dist/core/model-auth/handoff-jti.d.ts +3 -4
  203. package/dist/core/model-auth/handoff-jti.js +1 -1
  204. package/dist/core/model-auth/readiness.js +1 -1
  205. package/dist/core/model-config.d.ts +1 -1
  206. package/dist/core/model-config.js +1 -1
  207. package/dist/core/model-routes-pool.d.ts +14 -0
  208. package/dist/core/model-routes-pool.js +1 -0
  209. package/dist/core/model-routes.d.ts +11 -16
  210. package/dist/core/model-routes.js +1 -1
  211. package/dist/core/peer/ingest.d.ts +2 -0
  212. package/dist/core/peer/ingest.js +1 -1
  213. package/dist/core/peer/stubs.d.ts +8 -0
  214. package/dist/core/peer/stubs.js +1 -1
  215. package/dist/core/permissions/evaluator.d.ts +7 -2
  216. package/dist/core/permissions/evaluator.js +2 -2
  217. package/dist/core/plugin-env.js +1 -1
  218. package/dist/core/pool-credential-store.d.ts +2 -5
  219. package/dist/core/pool-credential-store.js +1 -1
  220. package/dist/core/profiles/app-env-store.d.ts +5 -5
  221. package/dist/core/profiles/app-env-store.js +1 -2
  222. package/dist/core/profiles/default-binding.d.ts +5 -5
  223. package/dist/core/profiles/default-binding.js +1 -1
  224. package/dist/core/profiles/env-store.d.ts +10 -21
  225. package/dist/core/profiles/env-store.js +1 -2
  226. package/dist/core/profiles/manifest.d.ts +14 -18
  227. package/dist/core/profiles/manifest.js +1 -1
  228. package/dist/core/profiles/relocate.js +1 -1
  229. package/dist/core/profiles/select.js +21 -21
  230. package/dist/core/provider-credential.d.ts +1 -1
  231. package/dist/core/provider-credential.js +1 -1
  232. package/dist/core/provider-management.d.ts +3 -4
  233. package/dist/core/provider-management.js +1 -1
  234. package/dist/core/providers/bundles.js +2 -2
  235. package/dist/core/providers/call.d.ts +3 -34
  236. package/dist/core/providers/description.d.ts +34 -0
  237. package/dist/core/providers/description.js +0 -0
  238. package/dist/core/providers/token-cache.d.ts +14 -14
  239. package/dist/core/providers/token-cache.js +1 -1
  240. package/dist/core/review/companion.js +1 -1
  241. package/dist/core/runs/activity.d.ts +1 -1
  242. package/dist/core/runs/activity.js +1 -1
  243. package/dist/core/runs/events.d.ts +7 -5
  244. package/dist/core/runs/events.js +2 -6
  245. package/dist/core/runs/operations.d.ts +1 -1
  246. package/dist/core/runs/operations.js +6 -6
  247. package/dist/core/runtime/bearings.js +1 -1
  248. package/dist/core/runtime/broker/attachments-fetch.d.ts +5 -0
  249. package/dist/core/runtime/broker/attachments-fetch.js +1 -0
  250. package/dist/core/runtime/broker/bash-job-launch.d.ts +4 -2
  251. package/dist/core/runtime/broker/bash-job-launch.js +1 -1
  252. package/dist/core/runtime/broker/boot-state.d.ts +9 -0
  253. package/dist/core/runtime/broker/boot-state.js +1 -0
  254. package/dist/core/runtime/broker/cli-relay.d.ts +2 -1
  255. package/dist/core/runtime/broker/cli-relay.js +1 -1
  256. package/dist/core/runtime/broker/client-registry.d.ts +3 -3
  257. package/dist/core/runtime/broker/daemon-ops.d.ts +10 -1
  258. package/dist/core/runtime/broker/daemon-ops.js +1 -1
  259. package/dist/core/runtime/broker/fault-retry.d.ts +2 -0
  260. package/dist/core/runtime/broker/fault-retry.js +1 -1
  261. package/dist/core/runtime/broker/frame-engine-control.js +1 -1
  262. package/dist/core/runtime/broker/held-deferred-inbox.d.ts +3 -0
  263. package/dist/core/runtime/broker/held-deferred-inbox.js +1 -1
  264. package/dist/core/runtime/broker/job-reporter.d.ts +18 -0
  265. package/dist/core/runtime/broker/job-reporter.js +2 -0
  266. package/dist/core/runtime/broker/model-adapter.d.ts +3 -0
  267. package/dist/core/runtime/broker/model-adapter.js +3 -2
  268. package/dist/core/runtime/broker/signal-stream.js +1 -1
  269. package/dist/core/runtime/broker/spilled-body.d.ts +5 -0
  270. package/dist/core/runtime/broker/spilled-body.js +1 -0
  271. package/dist/core/runtime/broker/summaries-post.d.ts +5 -0
  272. package/dist/core/runtime/broker/summaries-post.js +1 -0
  273. package/dist/core/runtime/broker/tool-groups.d.ts +3 -0
  274. package/dist/core/runtime/broker/tool-groups.js +1 -1
  275. package/dist/core/runtime/broker/turn-replies.d.ts +1 -0
  276. package/dist/core/runtime/broker/turn-replies.js +1 -1
  277. package/dist/core/runtime/broker-persona-guidance.js +2 -2
  278. package/dist/core/runtime/broker.js +1 -1
  279. package/dist/core/runtime/deliver-live.js +1 -1
  280. package/dist/core/runtime/first-boot-rows.d.ts +8 -0
  281. package/dist/core/runtime/first-boot-rows.js +2 -0
  282. package/dist/core/runtime/fleet.d.ts +13 -12
  283. package/dist/core/runtime/front-door-login.js +1 -1
  284. package/dist/core/runtime/front-door.js +6 -6
  285. package/dist/core/runtime/headless-pi.js +1 -1
  286. package/dist/core/runtime/host.d.ts +14 -3
  287. package/dist/core/runtime/host.js +3 -3
  288. package/dist/core/runtime/invocation.d.ts +6 -0
  289. package/dist/core/runtime/kickoff.d.ts +2 -14
  290. package/dist/core/runtime/kickoff.js +17 -19
  291. package/dist/core/runtime/launch-config-worker.js +1 -1
  292. package/dist/core/runtime/launch.js +2 -2
  293. package/dist/core/runtime/model-registry.js +1 -1
  294. package/dist/core/runtime/node-read.d.ts +4 -6
  295. package/dist/core/runtime/node-read.js +3 -3
  296. package/dist/core/runtime/nodes.js +1 -1
  297. package/dist/core/runtime/outcome-document.d.ts +0 -1
  298. package/dist/core/runtime/outcome-document.js +1 -1
  299. package/dist/core/runtime/output-result.d.ts +15 -0
  300. package/dist/core/runtime/output-result.js +5 -0
  301. package/dist/core/runtime/placement.d.ts +17 -1
  302. package/dist/core/runtime/placement.js +1 -1
  303. package/dist/core/runtime/provider-credential-gate.d.ts +6 -2
  304. package/dist/core/runtime/provider-credential-gate.js +2 -2
  305. package/dist/core/runtime/recovery-hold.d.ts +21 -2
  306. package/dist/core/runtime/recovery-hold.js +2 -1
  307. package/dist/core/runtime/recycle.js +1 -1
  308. package/dist/core/runtime/reset.js +1 -1
  309. package/dist/core/runtime/revive.d.ts +2 -2
  310. package/dist/core/runtime/revive.js +2 -2
  311. package/dist/core/runtime/runner/blaxel/client.d.ts +81 -0
  312. package/dist/core/runtime/runner/blaxel/client.js +1 -0
  313. package/dist/core/runtime/runner/blaxel/image-build.d.ts +74 -0
  314. package/dist/core/runtime/runner/blaxel/image-build.js +5 -0
  315. package/dist/core/runtime/runner/blaxel/runner.d.ts +41 -0
  316. package/dist/core/runtime/runner/blaxel/runner.js +3 -0
  317. package/dist/core/runtime/runner/index.d.ts +8 -0
  318. package/dist/core/runtime/runner/index.js +1 -0
  319. package/dist/core/runtime/runner/process.d.ts +11 -0
  320. package/dist/core/runtime/runner/process.js +1 -0
  321. package/dist/core/runtime/runner/types.d.ts +95 -0
  322. package/dist/core/runtime/runner/types.js +0 -0
  323. package/dist/core/runtime/situational-context.d.ts +3 -6
  324. package/dist/core/runtime/situational-context.js +2 -2
  325. package/dist/core/runtime/situational-live.js +1 -1
  326. package/dist/core/runtime/spawn-env-rows.d.ts +5 -0
  327. package/dist/core/runtime/spawn-env-rows.js +1 -0
  328. package/dist/core/runtime/spawn-env.d.ts +4 -18
  329. package/dist/core/runtime/spawn-env.js +1 -1
  330. package/dist/core/runtime/spawn.js +2 -2
  331. package/dist/core/runtime/stop-guard.d.ts +1 -1
  332. package/dist/core/runtime/stop-guard.js +2 -8
  333. package/dist/core/runtime/structured-output.d.ts +0 -67
  334. package/dist/core/runtime/structured-output.js +3 -8
  335. package/dist/core/runtime/tmux-driver.d.ts +8 -0
  336. package/dist/core/runtime/tmux-driver.js +6 -6
  337. package/dist/core/runtime/view-socket.d.ts +20 -0
  338. package/dist/core/runtime/view-socket.js +3 -1
  339. package/dist/core/runtime/warm-pool.d.ts +13 -1
  340. package/dist/core/runtime/warm-pool.js +1 -1
  341. package/dist/core/scoped-state/legacy-profiles.d.ts +11 -0
  342. package/dist/core/scoped-state/legacy-profiles.js +1 -0
  343. package/dist/core/scoped-state/materialized-plugins.d.ts +18 -0
  344. package/dist/core/scoped-state/materialized-plugins.js +1 -0
  345. package/dist/core/scoped-state/migrate.d.ts +8 -1
  346. package/dist/core/scoped-state/migrate.js +3 -3
  347. package/dist/core/scoped-state/person-rows.d.ts +10 -0
  348. package/dist/core/scoped-state/person-rows.js +6 -0
  349. package/dist/core/scoped-state/person-store.d.ts +72 -0
  350. package/dist/core/scoped-state/person-store.js +1 -0
  351. package/dist/core/secrets/blaxel-launch.d.ts +24 -0
  352. package/dist/core/secrets/blaxel-launch.js +4 -0
  353. package/dist/core/secrets/blaxel-register.d.ts +2 -0
  354. package/dist/core/secrets/blaxel-register.js +1 -0
  355. package/dist/core/secrets/env-rows.d.ts +17 -0
  356. package/dist/core/secrets/env-rows.js +4 -0
  357. package/dist/core/secrets/environment-owner.d.ts +8 -0
  358. package/dist/core/secrets/environment-owner.js +1 -0
  359. package/dist/core/secrets/environment-secrets.d.ts +14 -0
  360. package/dist/core/secrets/environment-secrets.js +1 -0
  361. package/dist/core/secrets/index.d.ts +2 -0
  362. package/dist/core/secrets/index.js +1 -0
  363. package/dist/core/secrets/key.d.ts +3 -0
  364. package/dist/core/secrets/key.js +2 -0
  365. package/dist/core/secrets/seal.d.ts +18 -0
  366. package/dist/core/secrets/seal.js +1 -0
  367. package/dist/core/spaces/mounts.d.ts +1 -1
  368. package/dist/core/spaces/mounts.js +1 -1
  369. package/dist/core/spaces/process.d.ts +1 -1
  370. package/dist/core/spaces/stop.d.ts +7 -5
  371. package/dist/core/spaces/stop.js +2 -2
  372. package/dist/core/spaces/users.d.ts +2 -1
  373. package/dist/core/spaces/users.js +1 -1
  374. package/dist/core/storage/attachments.d.ts +11 -8
  375. package/dist/core/storage/attachments.js +1 -1
  376. package/dist/core/storage/tables.d.ts +4 -0
  377. package/dist/core/storage/tables.js +3 -3
  378. package/dist/core/subscription-state.d.ts +34 -72
  379. package/dist/core/subscription-state.js +1 -4
  380. package/dist/core/substrate/delivery/plan.js +1 -1
  381. package/dist/core/user-settings.js +1 -1
  382. package/dist/daemon/api/app-listener.js +10 -10
  383. package/dist/daemon/api/auth/person-bearer.d.ts +14 -0
  384. package/dist/daemon/api/auth/person-bearer.js +1 -0
  385. package/dist/daemon/api/bridge.js +4 -4
  386. package/dist/daemon/api/document-listener.js +3 -3
  387. package/dist/daemon/api/environment-of.d.ts +18 -0
  388. package/dist/daemon/api/environment-of.js +5 -0
  389. package/dist/daemon/api/handlers/analytics.js +1 -1
  390. package/dist/daemon/api/handlers/app-profiles.d.ts +2 -2
  391. package/dist/daemon/api/handlers/app-profiles.js +1 -1
  392. package/dist/daemon/api/handlers/bash-jobs.js +1 -1
  393. package/dist/daemon/api/handlers/bash.js +1 -1
  394. package/dist/daemon/api/handlers/broker-ops.d.ts +3 -0
  395. package/dist/daemon/api/handlers/broker-ops.js +1 -1
  396. package/dist/daemon/api/handlers/broker-recovery.js +1 -1
  397. package/dist/daemon/api/handlers/broker-signals.d.ts +0 -3
  398. package/dist/daemon/api/handlers/broker-signals.js +2 -2
  399. package/dist/daemon/api/handlers/canvas.js +4 -4
  400. package/dist/daemon/api/handlers/charges.d.ts +1 -1
  401. package/dist/daemon/api/handlers/charges.js +1 -1
  402. package/dist/daemon/api/handlers/conversations.d.ts +2 -0
  403. package/dist/daemon/api/handlers/conversations.js +3 -0
  404. package/dist/daemon/api/handlers/crons.js +1 -1
  405. package/dist/daemon/api/handlers/daemon.js +1 -1
  406. package/dist/daemon/api/handlers/delivery.d.ts +1 -1
  407. package/dist/daemon/api/handlers/delivery.js +1 -1
  408. package/dist/daemon/api/handlers/docs.js +1 -1
  409. package/dist/daemon/api/handlers/exec.js +1 -1
  410. package/dist/daemon/api/handlers/execution-start.d.ts +2 -0
  411. package/dist/daemon/api/handlers/execution-start.js +2 -0
  412. package/dist/daemon/api/handlers/files.js +1 -1
  413. package/dist/daemon/api/handlers/git-credential.d.ts +11 -0
  414. package/dist/daemon/api/handlers/git-credential.js +1 -0
  415. package/dist/daemon/api/handlers/hook-exec.d.ts +1 -1
  416. package/dist/daemon/api/handlers/hook-exec.js +1 -1
  417. package/dist/daemon/api/handlers/human-requests.js +1 -1
  418. package/dist/daemon/api/handlers/inbox.js +1 -1
  419. package/dist/daemon/api/handlers/messages.js +1 -1
  420. package/dist/daemon/api/handlers/model-config.js +1 -1
  421. package/dist/daemon/api/handlers/modelauth.d.ts +1 -1
  422. package/dist/daemon/api/handlers/modelauth.js +1 -1
  423. package/dist/daemon/api/handlers/node-events.d.ts +6 -0
  424. package/dist/daemon/api/handlers/node-events.js +3 -3
  425. package/dist/daemon/api/handlers/node-outcomes.js +1 -1
  426. package/dist/daemon/api/handlers/node-records.js +3 -2
  427. package/dist/daemon/api/handlers/nodes.js +1 -1
  428. package/dist/daemon/api/handlers/objects.js +3 -3
  429. package/dist/daemon/api/handlers/profiles.js +1 -1
  430. package/dist/daemon/api/handlers/providers.js +1 -1
  431. package/dist/daemon/api/handlers/reports.js +9 -13
  432. package/dist/daemon/api/handlers/reviews.js +1 -1
  433. package/dist/daemon/api/handlers/runs.js +1 -1
  434. package/dist/daemon/api/handlers/settings.d.ts +2 -0
  435. package/dist/daemon/api/handlers/settings.js +1 -0
  436. package/dist/daemon/api/handlers/structured-requests.js +1 -1
  437. package/dist/daemon/api/handlers/vendor-status.d.ts +1 -1
  438. package/dist/daemon/api/handlers/vendor-status.js +1 -1
  439. package/dist/daemon/api/handlers/worktree.js +1 -1
  440. package/dist/daemon/api/map.d.ts +2 -2
  441. package/dist/daemon/api/map.js +2 -2
  442. package/dist/daemon/api/operations.js +1 -1
  443. package/dist/daemon/api/reader.d.ts +8 -1
  444. package/dist/daemon/api/reader.js +1 -1
  445. package/dist/daemon/api/router.d.ts +4 -2
  446. package/dist/daemon/api/router.js +1 -1
  447. package/dist/daemon/api/server.d.ts +15 -3
  448. package/dist/daemon/api/server.js +1 -1
  449. package/dist/daemon/api/vendor-signin.d.ts +2 -1
  450. package/dist/daemon/api/vendor-signin.js +20 -20
  451. package/dist/daemon/api/viewer-presence.d.ts +20 -6
  452. package/dist/daemon/api/viewer-presence.js +2 -1
  453. package/dist/daemon/broker-signals/bus.d.ts +48 -11
  454. package/dist/daemon/broker-signals/bus.js +1 -1
  455. package/dist/daemon/cron/armed-context.js +1 -1
  456. package/dist/daemon/cron/lease-recovery.js +1 -1
  457. package/dist/daemon/cron/live-runs.d.ts +6 -0
  458. package/dist/daemon/cron/live-runs.js +1 -1
  459. package/dist/daemon/cron/run-socket.js +1 -1
  460. package/dist/daemon/cron-run.js +2 -2
  461. package/dist/daemon/crtrd-cli.js +1 -1
  462. package/dist/daemon/crtrd.d.ts +10 -0
  463. package/dist/daemon/crtrd.js +18 -17
  464. package/dist/daemon/delivery/run-delivery.d.ts +1 -1
  465. package/dist/daemon/delivery/run-delivery.js +1 -1
  466. package/dist/daemon/due-sources.d.ts +1 -1
  467. package/dist/daemon/due-sources.js +1 -1
  468. package/dist/daemon/due.js +7 -6
  469. package/dist/daemon/fleet.d.ts +6 -6
  470. package/dist/daemon/fleet.js +9 -9
  471. package/dist/daemon/park-activity.d.ts +2 -1
  472. package/dist/daemon/park-activity.js +1 -1
  473. package/dist/daemon/park-pending.d.ts +20 -13
  474. package/dist/daemon/park-pending.js +3 -1
  475. package/dist/daemon/profile-delete.js +1 -1
  476. package/dist/daemon/reconcilers/bash-deadline.d.ts +15 -10
  477. package/dist/daemon/reconcilers/bash-deadline.js +1 -3
  478. package/dist/daemon/reconcilers/broker-supervision.d.ts +13 -3
  479. package/dist/daemon/reconcilers/broker-supervision.js +4 -4
  480. package/dist/daemon/reconcilers/cron-lane.d.ts +0 -1
  481. package/dist/daemon/reconcilers/cron-lane.js +1 -1
  482. package/dist/daemon/reconcilers/fault-retry-backstop.d.ts +2 -9
  483. package/dist/daemon/reconcilers/fault-retry-backstop.js +1 -1
  484. package/dist/daemon/reconcilers/grant-effects.d.ts +8 -0
  485. package/dist/daemon/reconcilers/grant-effects.js +1 -0
  486. package/dist/daemon/reconcilers/grove-instance-sweep.d.ts +1 -3
  487. package/dist/daemon/reconcilers/grove-instance-sweep.js +1 -1
  488. package/dist/daemon/reconcilers/ledger-r2.d.ts +27 -0
  489. package/dist/daemon/reconcilers/ledger-r2.js +7 -0
  490. package/dist/daemon/reconcilers/ledger-sandbox.d.ts +55 -0
  491. package/dist/daemon/reconcilers/ledger-sandbox.js +9 -0
  492. package/dist/daemon/reconcilers/ledger-storage.d.ts +22 -0
  493. package/dist/daemon/reconcilers/ledger-storage.js +5 -0
  494. package/dist/daemon/reconcilers/live-obligation.d.ts +3 -2
  495. package/dist/daemon/reconcilers/live-obligation.js +1 -1
  496. package/dist/daemon/reconcilers/managed-worktree-sweep.d.ts +0 -5
  497. package/dist/daemon/reconcilers/managed-worktree-sweep.js +1 -1
  498. package/dist/daemon/reconcilers/node-deadline.d.ts +2 -1
  499. package/dist/daemon/reconcilers/node-deadline.js +1 -1
  500. package/dist/daemon/reconcilers/node-lifecycle/freeze-lane.d.ts +1 -2
  501. package/dist/daemon/reconcilers/node-lifecycle/freeze-lane.js +1 -1
  502. package/dist/daemon/reconcilers/node-lifecycle/remote-wake.d.ts +31 -0
  503. package/dist/daemon/reconcilers/node-lifecycle/remote-wake.js +1 -0
  504. package/dist/daemon/reconcilers/node-lifecycle/requested-stops.d.ts +5 -0
  505. package/dist/daemon/reconcilers/node-lifecycle/requested-stops.js +2 -0
  506. package/dist/daemon/reconcilers/node-lifecycle/tick.js +1 -1
  507. package/dist/daemon/reconcilers/pending-review-submit.js +1 -1
  508. package/dist/daemon/reconcilers/recipe-image.d.ts +49 -0
  509. package/dist/daemon/reconcilers/recipe-image.js +7 -0
  510. package/dist/daemon/reconcilers/row-claim.d.ts +19 -0
  511. package/dist/daemon/reconcilers/row-claim.js +2 -0
  512. package/dist/daemon/reconcilers/storage-due-work.d.ts +18 -3
  513. package/dist/daemon/reconcilers/storage-due-work.js +2 -1
  514. package/dist/daemon/reconcilers/storage-maintenance.d.ts +5 -13
  515. package/dist/daemon/reconcilers/storage-maintenance.js +1 -1
  516. package/dist/daemon/reconcilers/structured-request-lane.js +1 -1
  517. package/dist/daemon/reconcilers/throttled-lane.d.ts +11 -0
  518. package/dist/daemon/reconcilers/throttled-lane.js +1 -0
  519. package/dist/daemon/review/finish.js +1 -1
  520. package/dist/daemon/run-notices.d.ts +3 -0
  521. package/dist/daemon/run-notices.js +1 -1
  522. package/dist/daemon/runs/append-section.d.ts +4 -1
  523. package/dist/daemon/runs/append-section.js +2 -2
  524. package/dist/daemon/runs/observer.d.ts +3 -2
  525. package/dist/daemon/runs/observer.js +3 -2
  526. package/dist/daemon/runs/view-transport.d.ts +19 -0
  527. package/dist/daemon/runs/view-transport.js +1 -0
  528. package/dist/daemon/structured-requests/boot.d.ts +2 -1
  529. package/dist/daemon/structured-requests/boot.js +1 -1
  530. package/dist/daemon/structured-requests/effects.d.ts +4 -3
  531. package/dist/daemon/structured-requests/effects.js +1 -1
  532. package/dist/daemon/structured-requests/notifier.d.ts +2 -0
  533. package/dist/daemon/structured-requests/notifier.js +1 -1
  534. package/dist/daemon/structured-requests/sidecar.d.ts +4 -3
  535. package/dist/daemon/structured-requests/sidecar.js +1 -1
  536. package/dist/launcher/validate.js +1 -1
  537. package/dist/migrations/004-canvas-documents/index.js +2 -2
  538. package/dist/pi-extensions/broker-local.d.ts +3 -3
  539. package/dist/pi-extensions/broker-local.js +1 -2
  540. package/dist/pi-extensions/canvas-bash-valve.js +6 -6
  541. package/dist/pi-extensions/canvas-context-intro.js +2 -2
  542. package/dist/pi-extensions/canvas-elapsed.js +2 -2
  543. package/dist/pi-extensions/canvas-goal-capture.js +1 -1
  544. package/dist/pi-extensions/canvas-inbox-watcher.js +2 -2
  545. package/dist/pi-extensions/canvas-review-boundary.d.ts +11 -1
  546. package/dist/pi-extensions/canvas-review-boundary.js +3 -3
  547. package/dist/pi-extensions/canvas-stophook.js +1 -1
  548. package/dist/pi-extensions/canvas-structured-output.d.ts +5 -3
  549. package/dist/pi-extensions/canvas-structured-output.js +6 -11
  550. package/dist/pi-extensions/canvas-tool-guide.d.ts +9 -2
  551. package/dist/pi-extensions/canvas-tool-guide.js +6 -6
  552. package/dist/shared/inbox-entry-body.js +7 -7
  553. package/dist/types.d.ts +12 -0
  554. package/docs/sdk/release-notes.md +4 -0
  555. package/package.json +7 -4
  556. package/packages/crouter-identity/package.json +1 -1
  557. package/runtime.lock.json +13 -13
  558. package/scripts/git-credential-crtr +33 -0
  559. package/scripts/sandbox-bootstrap.sh +54 -0
  560. package/scripts/sandbox-start.mjs +320 -0
  561. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.d.ts +0 -78
  562. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.js +0 -1179
  563. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.ts +0 -1406
  564. package/dist/core/conversation-store/file-store.d.ts +0 -37
  565. package/dist/core/conversation-store/file-store.js +0 -9
  566. package/dist/core/conversation-store/listener.d.ts +0 -4
  567. package/dist/core/conversation-store/listener.js +0 -8
  568. package/dist/core/scoped-state/profiles.d.ts +0 -27
  569. package/dist/core/scoped-state/profiles.js +0 -1
  570. package/dist/core/scoped-state/providers.d.ts +0 -24
  571. package/dist/core/scoped-state/providers.js +0 -1
  572. package/dist/core/scoped-state/settings.d.ts +0 -28
  573. package/dist/core/scoped-state/settings.js +0 -1
@@ -1 +1 @@
1
- var $=Object.defineProperty;var c=(n,e)=>$(n,"name",{value:e,configurable:!0});import{ApiError as d}from"../../api/index.js";import{readerFor as g}from"../../core/graph/reader.js";import{canRead as E}from"../../core/graph/access.js";import{ownersByHandle as y,resolveName as F,viewOf as R}from"../../core/graph/names.js";import{ensureOwner as v,ownerForGrantee as x}from"../../core/graph/objects.js";import{checkoutsForCwd as N,reposForCwd as j}from"../../core/graph/repo-sync/repos.js";import{lookupProfile as L}from"../../core/profiles/manifest.js";import{filterAsync as _,mapAsync as A}from"../../core/async-array.js";import{personId as I}from"../../core/canvas/person.js";async function G(n,e){return await g(n,e.principal,async o=>await N(n,o))}c(G,"readerFor");async function P(n,e,o){const r=await F(n,e,o);if("object"in r)return r.object;if("deleted"in r||"remote"in r)return r;if("ambiguous"in r){const s=await A(r.ambiguous,async m=>`${await O(n,m)}/${m.name}`);throw new d(409,"ambiguous_name",`'${o}' names more than one object: ${s.join(", ")}`,{candidates:s,next:"Read one of them by its full `<type>:<owner>/<name>`."})}const t=o.replace(/^\s*\[\[(.*)\]\]\s*$/,"$1").trim(),a=/^(person|app|repo|profile):([^/]+)$/.exec(t),i=await _(a?await y(n,a[2],a[1]):(await y(n,t)).filter(s=>s.type!=="node"),async s=>await E(n,e,s));if(i.length>0){const s=await R(n,e),m=c(w=>{const f=s.findIndex(h=>h.id===w.id);return f<0?1/0:f},"rank"),l=[...i].sort((w,f)=>m(w)-m(f))[0];if(m(l)===1/0&&i.length>1){const w=i.map(f=>`${f.type}:${f.name}`);throw new d(409,"ambiguous_name",`'${o}' names more than one owner: ${w.join(", ")}`,{candidates:w,next:"Name one as `<type>:<handle>`."})}return l.deleted_at?{deleted:l}:l}const p=`'${o}' not found: no object by that name in your view`,u=`Search for it with \`crtr canvas search ${t}\`.`;throw new d(404,"not_found",p,{error:"not_found",message:p,next:u})}c(P,"resolveRef");async function O(n,e){if(e.owner===null)return"";const o=await n.prepare("SELECT type, id, name FROM objects WHERE id = ?").get(e.owner);return o.type==="node"?o.id:`${o.type}:${o.name}`}c(O,"typedOwnerHandle");async function q(n,e,o,r){const t=o??(e.class==="node"?"node":e.class==="person"?"user":"app"),a=c(i=>new d(400,"invalid_owner",i,{next:"Run `crtr doc write --owner -h`."}),"refuse");if(t==="node"){if(e.class!=="node")throw a("`--owner node` needs a node; you are not running as one");return e.node}if(t==="user")return await x(n,I());if(t==="app"){if(e.class==="person")throw a("`--owner app` needs an app; a person has none \u2014 use `--owner user`");return e.app}if(t==="profile"){if(e.class!=="node"||!e.profile)throw a("`--owner profile` needs a profile; you have none");return e.profile}if(t==="repo"){const i=r?await j(n,r):[],p=i[0]?i:e.class==="node"?e.repos:[];if(!p[0])throw a(`\`--owner repo\` needs a repo; ${r??(e.class==="node"?e.cwd:"your directory")} is not inside one`);return p[0]}if(t.startsWith("repo:"))return await S(n,"repo",t.slice(5),a);if(t.startsWith("profile:")){const i=t.slice(8),p=await n.prepare("SELECT * FROM objects WHERE type = 'profile' AND name = ? AND home_machine IS NULL").get(i);if(p)return p;const u=L(i);if(u.kind!=="resolved")throw a(`no profile named '${i}'`);const s=e.class==="person"?e.person:e.app;return await v(n,"profile","profile",u.entry.profileId,u.entry.manifest.name,s)}throw a(`unknown --owner value '${t}'`)}c(q,"ownerFromFlag");async function S(n,e,o,r){const t=await n.prepare("SELECT * FROM objects WHERE type = ? AND name = ? AND deleted_at IS NULL AND home_machine IS NULL").get(e,o);if(!t)throw r(`no ${e} named '${o}'`);return t}c(S,"namedOwner");export{q as ownerFromFlag,G as readerFor,P as resolveRef};
1
+ var R=Object.defineProperty;var c=(n,e)=>R(n,"name",{value:e,configurable:!0});import{ApiError as d}from"../../api/index.js";import{readerFor as N,warmNodeRepos as h}from"../../core/graph/reader.js";import{canRead as g}from"../../core/graph/access.js";import{ownersByHandle as y,resolveName as x,viewOf as F}from"../../core/graph/names.js";import{ensureOwner as I,ownerForGrantee as j}from"../../core/graph/objects.js";import{checkoutsForCwd as v,reposForCwd as L,warmCheckoutIdentities as O}from"../../core/graph/repo-sync/repos.js";import{lookupProfile as A}from"../../core/profiles/manifest.js";import{openDb as $}from"../../core/canvas/db.js";import{filterAsync as D,mapAsync as S}from"../../core/async-array.js";import{personId as _}from"../../core/canvas/person.js";async function K(n,e){return await N(n,e.principal,async o=>await v(n,o))}c(K,"readerFor");async function Q(n,e){e!==void 0&&await O(e),n.class==="broker"&&await h(await $(),n.node)}c(Q,"warmReaderRepos");async function V(n){const e=await $(),o=await e.prepareUncached("SELECT DISTINCT w.watcher FROM watches w JOIN objects o ON o.id = w.watcher AND o.type = 'node' WHERE w.object = ?").all(n);for(const{watcher:r}of o)await h(e,r)}c(V,"warmDocumentWatchers");async function X(n,e,o){const r=await x(n,e,o);if("object"in r)return r.object;if("deleted"in r||"remote"in r)return r;if("ambiguous"in r){const s=await S(r.ambiguous,async f=>`${await b(n,f)}/${f.name}`);throw new d(409,"ambiguous_name",`'${o}' names more than one object: ${s.join(", ")}`,{candidates:s,next:"Read one of them by its full `<type>:<owner>/<name>`."})}const t=o.replace(/^\s*\[\[(.*)\]\]\s*$/,"$1").trim(),i=/^(person|app|repo|profile):([^/]+)$/.exec(t),a=await D(i?await y(n,i[2],i[1]):(await y(n,t)).filter(s=>s.type!=="node"),async s=>await g(n,e,s));if(a.length>0){const s=await F(n,e),f=c(m=>{const w=s.findIndex(E=>E.id===m.id);return w<0?1/0:w},"rank"),l=[...a].sort((m,w)=>f(m)-f(w))[0];if(f(l)===1/0&&a.length>1){const m=a.map(w=>`${w.type}:${w.name}`);throw new d(409,"ambiguous_name",`'${o}' names more than one owner: ${m.join(", ")}`,{candidates:m,next:"Name one as `<type>:<handle>`."})}return l.deleted_at?{deleted:l}:l}const p=`'${o}' not found: no object by that name in your view`,u=`Search for it with \`crtr canvas search ${t}\`.`;throw new d(404,"not_found",p,{error:"not_found",message:p,next:u})}c(X,"resolveRef");async function b(n,e){if(e.owner===null)return"";const o=await n.prepare("SELECT type, id, name FROM objects WHERE id = ?").get(e.owner);return o.type==="node"?o.id:`${o.type}:${o.name}`}c(b,"typedOwnerHandle");async function Y(n,e,o,r){const t=o??(e.class==="node"?"node":e.class==="person"?"user":"app"),i=c(a=>new d(400,"invalid_owner",a,{next:"Run `crtr doc write --owner -h`."}),"refuse");if(t==="node"){if(e.class!=="node")throw i("`--owner node` needs a node; you are not running as one");return e.node}if(t==="user")return await j(n,_());if(t==="app"){if(e.class==="person")throw i("`--owner app` needs an app; a person has none \u2014 use `--owner user`");return e.app}if(t==="profile"){if(e.class!=="node"||!e.profile)throw i("`--owner profile` needs a profile; you have none");return e.profile}if(t==="repo"){const a=r?await L(n,r):[],p=a[0]?a:e.class==="node"?e.repos:[];if(!p[0])throw i(`\`--owner repo\` needs a repo; ${r??(e.class==="node"?e.cwd:"your directory")} is not inside one`);return p[0]}if(t.startsWith("repo:"))return await k(n,"repo",t.slice(5),i);if(t.startsWith("profile:")){const a=t.slice(8),p=await n.prepare("SELECT * FROM objects WHERE type = 'profile' AND name = ? AND home_machine IS NULL").get(a);if(p)return p;const u=A(a);if(u.kind!=="resolved")throw i(`no profile named '${a}'`);const s=e.class==="person"?e.person:e.app;return await I(n,"profile","profile",u.entry.profileId,u.entry.manifest.name,s)}throw i(`unknown --owner value '${t}'`)}c(Y,"ownerFromFlag");async function k(n,e,o,r){const t=await n.prepare("SELECT * FROM objects WHERE type = ? AND name = ? AND deleted_at IS NULL AND home_machine IS NULL").get(e,o);if(!t)throw r(`no ${e} named '${o}'`);return t}c(k,"namedOwner");export{Y as ownerFromFlag,K as readerFor,X as resolveRef,V as warmDocumentWatchers,Q as warmReaderRepos};
@@ -17,6 +17,7 @@ export type RequestPrincipal = {
17
17
  scopes: [];
18
18
  } | {
19
19
  class: 'person';
20
+ sub?: string;
20
21
  } | {
21
22
  class: 'app';
22
23
  app: string;
@@ -83,13 +84,14 @@ export type CronPrincipalClass = ({
83
84
  };
84
85
  /** The app a non-person caller acts as: a forwarded app actor's app, a forwarded person's terminal, null for the anonymous, a machine and the person. */
85
86
  export declare function appOf(principal: RequestPrincipal): string | null;
86
- /** Whether the caller is the person (a local person, or a forwarded call the envelope makes for the person). */
87
+ /** Whether the caller is the install's person, who passes the schema alone: the local person (no `sub`), or a forwarded call the envelope
88
+ * makes for the person. A person with a `sub` (a cloud role's directory person bearer) is one of many people and is confined by the evaluator. */
87
89
  export declare function actsAsPerson(principal: RequestPrincipal): boolean;
88
90
  export declare function resolvedScopes(principal: RequestPrincipal): Promise<readonly string[]>;
89
91
  export declare function runCallerApp(principal: RequestPrincipal | AppPrincipal): string | null;
90
92
  /** Whether the caller holds `permission` on a node: the evaluator, with the caller's ceiling (own-app run confinement, `objects` and
91
93
  * `conversations` scopes, `objects:message`). A person caller passes the schema alone. */
92
- export declare function mayOnNode(principal: RequestPrincipal | AppPrincipal, permission: 'read' | 'message', nodeId: string): Promise<boolean>;
94
+ export declare function mayOnNode(principal: RequestPrincipal | AppPrincipal, permission: 'read' | 'edit' | 'message', nodeId: string): Promise<boolean>;
93
95
  /** The ids of the nodes the caller may read, in one query that embeds the evaluator's condition; null when the caller reads every node (the person). */
94
96
  export declare function readableNodeIds(principal: RequestPrincipal): Promise<Set<string> | null>;
95
97
  export declare function canReadRun(principal: RequestPrincipal | AppPrincipal, grantee: string, target?: string): Promise<boolean>;
@@ -1 +1 @@
1
- var G=Object.defineProperty;var a=(e,t)=>G(e,"name",{value:t,configurable:!0});import{toErrorBody as z}from"./map.js";import{emitEvent as D}from"../../core/events/emit.js";import{scopeAllowed as m,ScopeDeniedError as H}from"../../core/scopes.js";import{coveredByAny as L}from"../../shared/env.js";import{ApiError as c}from"../../api/errors.js";import{activeGrant as j,grantFor as B}from"../../core/grants/mirror.js";import{getNode as _}from"../../core/canvas/canvas.js";import{ownedRun as I,RunError as g}from"../../core/runs/operations.js";import{openDb as k}from"../../core/canvas/db.js";import{check as J,permits as F}from"../../core/permissions/evaluator.js";import{readerFor as x}from"./reader.js";import{checkCronFire as P}from"../cron/authority.js";import{operationFor as Y}from"./operations.js";import{CONTROL_BODY_MAX_BYTES as M}from"../../core/llm/body-limits.js";import{getRequest as Z,getRequestByInboxTicket as V}from"../../core/human/requests.js";import{requireVisibleReview as S}from"../../core/review/store.js";import{getComment as R}from"../../core/review/comments.js";async function X(e,t,o,n,r){const s=e.path,u=r&&typeof r=="object"&&!Array.isArray(r)?r:{};if(s==="/v1/human/requests"||s==="/v1/human/reviews"){const d=s.endsWith("/reviews")?u.origin_node_id:u.requester_node_id,f=s==="/v1/human/requests"&&d==null;if(d!==t.node&&!f)throw new c(403,"other_app_run","a broker may create a human request only for its own node");const i=u.source;if(i&&typeof i=="object"&&"nodeId"in i&&i.nodeId!==t.node)throw new c(403,"other_app_run","request source must name the calling node")}if(s==="/v1/human/reviews/self/comments"&&e.method==="GET"&&n.get("actor_node_id")!==t.node)throw new c(403,"other_app_run","self review requires the calling node");if(s.includes("/comments")&&e.method!=="GET"&&u.actor_node_id!==t.node)throw new c(403,"other_app_run","comment author must be the calling node");if(o.comment_id&&!await R(o.comment_id))throw new c(404,"not_found","comment not found")}a(X,"authorizeHumanBody");function A(e){return e.class==="broker"||e.class==="cron"}a(A,"boundedByStoredScopes");function p(e){return e.class==="person"||e.class==="anonymous"||e.class==="machine"?null:e.class==="forwarded"?e.actor.kind==="app"?e.actor.app:null:e.app}a(p,"appOf");function y(e){return e.class==="person"||e.class==="forwarded"&&e.actor.kind==="person"}a(y,"actsAsPerson");async function q(e){const t=await B(e.actor.app,e.sub);if(!t)throw new c(403,"app_not_granted",`${e.actor.app} holds no active grant for ${e.sub} on this machine`);return t}a(q,"forwardedGrant");async function O(e){if(e.class==="person"||e.class==="anonymous"||e.class==="machine")return[];if(e.class==="forwarded"){if(e.actor.kind==="person")return[];const{resolved:o}=await q(e),n=e.actor.node_scopes;return n===null?o:n.filter(r=>L(o,r))}if(e.class==="app")return e.scopes;if(e.class==="cron"){const o=await P({grantee:e.app,sub:e.sub,grant_id:e.grant,scopes:e.scopes});if(o.allowed)return o.effectiveScopes;throw o.reason==="grant_missing"||o.reason==="grant_revoked"?new c(401,"grant_revoked",o.message):new c(403,"scope_missing",o.message)}const t=e.grant?await j(e.grant):await B(e.app,e.sub);if(t&&t.grantee===e.app&&t.sub===e.sub)return t.resolved;throw new c(401,"grant_revoked","the node grant is not active")}a(O,"resolvedScopes");function C(e){return"class"in e?p(e):e.grantee}a(C,"runCallerApp");function $(e){return"class"in e?e:{class:"app",app:e.grantee,scopes:e.resolved,sub:e.sub}}a($,"asRequestPrincipal");async function l(e,t,o){const n=$(e);if(y(n))return!0;if(n.class==="anonymous"||n.class==="machine")return!1;const r=await k();return await J(r,await x(r,{principal:n}),t,o)}a(l,"mayOnNode");async function Ae(e){if(y(e))return null;if(e.class==="anonymous"||e.class==="machine")return new Set;const t=await k(),o=await F(t,await x(t,{principal:e}),"read"),n=await t.prepareUncached(`SELECT o.id FROM objects o WHERE o.type = 'node' AND o.deleted_at IS NULL AND ${o.sql}`).all(...o.params);return new Set(n.map(r=>r.id))}a(Ae,"readableNodeIds");async function N(e,t,o){const n=$(e);return y(n)?!0:n.class==="anonymous"||n.class==="machine"?!1:p(n)===t?!0:m(await O(n),o)&&(!A(n)||m(n.scopes,o))}a(N,"mayReadApp");async function qe(e,t,o){return o===void 0?await N(e,t,`crtr:conversations:read:${t}`):await l(e,"read",o)}a(qe,"canReadRun");async function Oe(e,t,o=!1,n=!1){const r=await _(t);if(!r||r.parent!==null||r.run_id!==t||!r.grantee||r.deleting_at&&!n)throw new g(404,"not_found","run not found");if(!await l(e,"read",t))throw new g(404,"not_found","run not found");if(o&&C(e)!==null&&C(e)!==r.grantee)throw new g(403,"other_app_run","cannot change another app's run");return await I(t,r.grantee,n)}a(Oe,"requireRun");async function K(e,t,o){return o===void 0?await N(e,t,`crtr:objects:read:${t}`):await l(e,"read",o)}a(K,"canReadNode");const Q=new Set(["messages.post.58","messages.post.59"]);async function ee(e,t,o){if(!e.classes.includes(t.class)&&!(t.class!=="anonymous"&&t.class!=="machine"&&t.class!=="forwarded"&&e.classes.includes("anonymous")))throw new c(403,"permission_error","this operation is not available to the caller");if(t.class==="forwarded"&&t.actor.kind==="app"&&await q(t),t.class==="person"||t.class==="anonymous"||t.class==="machine"||y(t))return;const n=await O(t);if(e.scope&&(!m(n,e.scope)||A(t)&&!m(t.scopes,e.scope)))throw new c(403,"scope_missing",`missing scope ${e.scope}`);if(t.class==="app")return;const r=p(t);t.class==="broker"&&await te(e,t,o,n);const s=o.id;if((e.resource==="node-read"||e.resource==="node-write")&&s!==void 0){const u=await _(s);if(!u)return;if(e.resource==="node-write"){const d=Q.has(e.name);if(u.grantee!==r&&!d)throw new c(403,"other_app_run","cannot change another app's node");if(!await l(t,d&&u.grantee!==r?"message":"read",s))throw u.grantee!==r?new c(403,"other_app_run","cannot change another app's node"):new c(404,"not_found","node not found")}if(e.resource==="node-read"&&!await l(t,"read",s))throw new c(404,"not_found","node not found")}}a(ee,"authorizeOperation");async function te(e,t,o,n){if(e.resource==="daemon-bash"&&(!m(n,"crtr:files:rw:user:.")||!m(t.scopes,"crtr:files:rw:user:.")))throw new c(403,"scope_missing","missing scope crtr:files:rw:user:.");if(e.resource==="human"){const s=e.path,u=e.method==="GET";if(!u&&(s.endsWith("/respond")||s.endsWith("/submit")||s.endsWith("/dismiss")||s.endsWith("/progress")||s.endsWith("/comment-ranges")||s.includes("/feedback-comments")))throw new c(403,"permission_error","only the person may answer or edit the human inbox");const d=o.request_id?await Z(o.request_id):o.ticket_id?await V(o.ticket_id):null,f=o.comment_id?await R(o.comment_id):null,i=o.review_id?await S(o.review_id):f?await S(f.review_id):null,h=d?.requester_node_id??i?.origin_node_id;if(h!=null){const w=await _(h);if(w&&(u?!await K(t,w.grantee??"app:terminal",h):w.grantee!==t.app))throw new c(u?404:403,u?"not_found":"other_app_run","human request belongs to another app");if(w&&!u&&!await l(t,"read",h))throw new c(404,"not_found","human request not found")}else if(d||i)throw new c(403,"permission_error","only the person may access a request without a node")}const r=o.id;if(e.resource==="node-own"&&r!==void 0&&r!==t.node)throw new c(403,"other_app_run","the operation requires the calling node")}a(te,"authorizeBrokerOnly");function oe(e,t){if(!m(e,t))throw new H("the bearer token",t)}a(oe,"assertCeiling");function ne(){return new c(403,"owner_only","this operation is owner-only; a scoped token does not reach it")}a(ne,"ownerOnlyError");const re="Crtr-Caused-By",se=/^(?:message|request|cron_run):[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;function ae(e){const t=e[re.toLowerCase()];return typeof t=="string"&&se.test(t)?t:void 0}a(ae,"causedByOf");function Ce(e){return e.map(t=>({...t,ownerOnly:!0}))}a(Ce,"ownerOnly");class $e{static{a(this,"Router")}routes=[];register(t){const o=Y(t.method,t.pattern);if(!o)throw new Error(`route has no operation row: ${t.method} ${t.pattern}`);if(this.routes.some(n=>n.method===t.method.toUpperCase()&&n.operation.path===t.pattern))throw new Error(`duplicate route: ${t.method} ${t.pattern}`);return this.routes.push({operation:o,method:t.method.toUpperCase(),segments:T(t.pattern),handler:t.handler,maxBodyBytes:t.maxBodyBytes??M}),this}registerAll(t){for(const o of t)this.register(o);return this}match(t,o){const n=t.toUpperCase(),r=T(o);for(const s of this.routes){if(s.method!==n)continue;const u=ue(s.segments,r);if(u!==null)return{handler:s.handler,params:u,operation:s.operation,maxBodyBytes:s.maxBodyBytes}}return null}async handle(t,o,n,r={class:"person"}){try{const s=new URL(t.url??"/","http://127.0.0.1"),u=(t.method??"GET").toUpperCase(),d=this.match(u,s.pathname);if(d===null){W(o,404,"not_found",`no route for ${u} ${s.pathname}`);return}if(await ee(d.operation,r,d.params),n!==null){if(d.operation.classes.length===1&&d.operation.classes[0]==="person")throw ne();d.operation.scope&&oe(n,d.operation.scope)}let f;try{f=await de(t,d.maxBodyBytes)}catch(v){const E=v instanceof U?"payload_too_large":"invalid_request";W(o,E==="payload_too_large"?413:400,E,v.message);return}r.class==="broker"&&d.operation.resource==="human"&&await X(d.operation,r,d.params,s.searchParams,f);const i=ae(t.headers),h={...i===void 0?{}:{causedBy:i},method:u,path:s.pathname,params:d.params,query:s.searchParams,body:f,ceiling:n,principal:r,...r.class==="anonymous"&&typeof t.headers.authorization=="string"?{publishToken:t.headers.authorization.slice(7)}:{},req:t,res:o},w=await d.handler(h);o.writableEnded||ce(o,w)}catch(s){if(s instanceof Error&&s.code==="person_unresolved"){b(o,503,{error:{code:"runtime_starting",message:"grant sync is not ready",type:"server_error",origin:"runtime",retryable:!0}});return}const{status:u,body:d}=z(s);u>=500&&D({event:"api.request.failed",level:"error",error:s instanceof Error?s:new Error(String(s)),...r.class==="broker"?{node_id:r.node}:{},fields:{method:(t.method??"GET").toUpperCase(),path:t.url??""}}),b(o,u,d)}}}function T(e){return e.split("/").filter(t=>t.length>0)}a(T,"splitPath");function ue(e,t){if(e.length!==t.length)return null;const o={};for(let n=0;n<e.length;n++){const r=e[n],s=t[n];if(r.startsWith(":"))o[r.slice(1)]=decodeURIComponent(s);else if(r!==s)return null}return o}a(ue,"matchSegments");class U extends Error{static{a(this,"BodyTooLargeError")}}async function de(e,t){const o=[];let n=0;for await(const s of e){const u=s;if(n+=u.length,n>t)throw new U(`request body exceeds ${t} bytes`);o.push(u)}if(n===0)return;const r=Buffer.concat(o).toString("utf8").trim();if(r!=="")try{return JSON.parse(r)}catch{throw new Error("request body is not valid JSON")}}a(de,"readJsonBody");function ce(e,t){if(e.headersSent)return;const o={...t.headers??{}};if(t.rawBody!==void 0){e.writeHead(t.status,o),e.end(t.rawBody);return}if(t.status===204||t.body===void 0){e.writeHead(t.status,o),e.end();return}o["content-type"]===void 0&&(o["content-type"]="application/json; charset=utf-8"),e.writeHead(t.status,o),e.end(JSON.stringify(t.body))}a(ce,"writeResult");function b(e,t,o){if(e.headersSent){e.end();return}e.writeHead(t,{"content-type":"application/json; charset=utf-8"}),e.end(JSON.stringify(o))}a(b,"writeJson");function W(e,t,o,n){b(e,t,{error:{code:o,message:n,origin:"runtime"}})}a(W,"writeError");export{re as CAUSED_BY_HEADER,$e as Router,y as actsAsPerson,p as appOf,oe as assertCeiling,K as canReadNode,qe as canReadRun,ae as causedByOf,l as mayOnNode,Ce as ownerOnly,ne as ownerOnlyError,Ae as readableNodeIds,Oe as requireRun,O as resolvedScopes,C as runCallerApp};
1
+ var P=Object.defineProperty;var d=(e,t)=>P(e,"name",{value:t,configurable:!0});import{toErrorBody as H}from"./map.js";import{emitEvent as D}from"../../core/events/emit.js";import{scopeAllowed as _,ScopeDeniedError as I}from"../../core/scopes.js";import{coveredByAny as L}from"../../shared/env.js";import{ApiError as u}from"../../api/errors.js";import{activeGrant as F,grantFor as S}from"../../core/grants/mirror.js";import{getNode as w}from"../../core/canvas/canvas.js";import{ownedRun as J,RunError as b}from"../../core/runs/operations.js";import{openDb as x}from"../../core/canvas/db.js";import{check as Y,permits as M}from"../../core/permissions/evaluator.js";import{readerFor as R}from"./reader.js";import{checkCronFire as Z}from"../cron/authority.js";import{operationFor as V}from"./operations.js";import{CONTROL_BODY_MAX_BYTES as X}from"../../core/llm/body-limits.js";import{getRequest as p,getRequestByInboxTicket as A}from"../../core/human/requests.js";import{requireVisibleReview as y}from"../../core/review/store.js";import{getComment as v}from"../../core/review/comments.js";import{getStructuredRequest as K}from"../../core/canvas/structured-requests.js";async function Q(e,t,n,o,s){const r=e.path,a=s&&typeof s=="object"&&!Array.isArray(s)?s:{};if(r==="/v1/human/requests"||r==="/v1/human/reviews"){const i=r.endsWith("/reviews")?a.origin_node_id:a.requester_node_id,c=r==="/v1/human/requests"&&i==null;if(i!==t.node&&!c)throw new u(403,"other_app_run","a broker may create a human request only for its own node");const h=a.source;if(h&&typeof h=="object"&&"nodeId"in h&&h.nodeId!==t.node)throw new u(403,"other_app_run","request source must name the calling node")}if(r==="/v1/human/reviews/self/comments"&&e.method==="GET"&&o.get("actor_node_id")!==t.node)throw new u(403,"other_app_run","self review requires the calling node");if(r.includes("/comments")&&e.method!=="GET"&&a.actor_node_id!==t.node)throw new u(403,"other_app_run","comment author must be the calling node");if(n.comment_id&&!await v(n.comment_id))throw new u(404,"not_found","comment not found")}d(Q,"authorizeHumanBody");function O(e){return e.class==="broker"||e.class==="cron"}d(O,"boundedByStoredScopes");function k(e){return e.class==="person"||e.class==="anonymous"||e.class==="machine"?null:e.class==="forwarded"?e.actor.kind==="app"?e.actor.app:null:e.app}d(k,"appOf");function g(e){return e.class==="person"&&e.sub===void 0||e.class==="forwarded"&&e.actor.kind==="person"}d(g,"actsAsPerson");async function C(e){const t=await S(e.actor.app,e.sub);if(!t)throw new u(403,"app_not_granted",`${e.actor.app} holds no active grant for ${e.sub} on this machine`);return t}d(C,"forwardedGrant");async function $(e){if(e.class==="person"||e.class==="anonymous"||e.class==="machine")return[];if(e.class==="forwarded"){if(e.actor.kind==="person")return[];const{resolved:n}=await C(e),o=e.actor.node_scopes;return o===null?n:o.filter(s=>L(n,s))}if(e.class==="app")return e.scopes;if(e.class==="cron"){const n=await Z({grantee:e.app,sub:e.sub,grant_id:e.grant,scopes:e.scopes});if(n.allowed)return n.effectiveScopes;throw n.reason==="grant_missing"||n.reason==="grant_revoked"?new u(401,"grant_revoked",n.message):new u(403,"scope_missing",n.message)}const t=e.grant?await F(e.grant):await S(e.app,e.sub);if(t&&t.grantee===e.app&&t.sub===e.sub)return t.resolved;throw new u(401,"grant_revoked","the node grant is not active")}d($,"resolvedScopes");function N(e){return"class"in e?k(e):e.grantee}d(N,"runCallerApp");function T(e){return"class"in e?e:{class:"app",app:e.grantee,scopes:e.resolved,sub:e.sub}}d(T,"asRequestPrincipal");async function f(e,t,n){const o=T(e);if(g(o))return!0;if(o.class==="anonymous"||o.class==="machine")return!1;const s=await x();return await Y(s,await R(s,{principal:o}),t,n)}d(f,"mayOnNode");async function Te(e){if(g(e))return null;if(e.class==="anonymous"||e.class==="machine")return new Set;const t=await x(),n=await M(t,await R(t,{principal:e}),"read"),o=await t.prepareUncached(`SELECT o.id FROM objects o WHERE o.type = 'node' AND o.deleted_at IS NULL AND ${n.sql}`).all(...n.params);return new Set(o.map(s=>s.id))}d(Te,"readableNodeIds");async function W(e,t,n){const o=T(e);return g(o)?!0:o.class==="anonymous"||o.class==="machine"?!1:k(o)===t?!0:_(await $(o),n)&&(!O(o)||_(o.scopes,n))}d(W,"mayReadApp");async function We(e,t,n){return n===void 0?await W(e,t,`crtr:conversations:read:${t}`):await f(e,"read",n)}d(We,"canReadRun");async function ze(e,t,n=!1,o=!1){const s=await w(t);if(!s||s.parent!==null||s.run_id!==t||!s.grantee||s.deleting_at&&!o)throw new b(404,"not_found","run not found");if(!await f(e,"read",t))throw new b(404,"not_found","run not found");if(n&&N(e)!==null&&N(e)!==s.grantee)throw new b(403,"other_app_run","cannot change another app's run");return await J(t,s.grantee,o)}d(ze,"requireRun");async function ee(e,t,n){return n===void 0?await W(e,t,`crtr:objects:read:${t}`):await f(e,"read",n)}d(ee,"canReadNode");const z=new Set(["messages.post.58","messages.post.59"]);async function te(e,t,n){if(!e.classes.includes(t.class)&&!(t.class!=="anonymous"&&t.class!=="machine"&&t.class!=="forwarded"&&e.classes.includes("anonymous")))throw new u(403,"permission_error","this operation is not available to the caller");if(t.class==="forwarded"&&t.actor.kind==="app"&&await C(t),t.class==="anonymous"||t.class==="machine"||g(t))return;if(t.class==="person")return await ne(e,t,n);const o=await $(t);if(e.scope&&(!_(o,e.scope)||O(t)&&!_(t.scopes,e.scope)))throw new u(403,"scope_missing",`missing scope ${e.scope}`);if(t.class==="app")return;const s=k(t);t.class==="broker"&&await ae(e,t,n,o);const r=n.id;if((e.resource==="node-read"||e.resource==="node-write")&&r!==void 0){const a=await w(r);if(!a)return;if(e.resource==="node-write"){const i=z.has(e.name);if(a.grantee!==s&&!i)throw new u(403,"other_app_run","cannot change another app's node");if(!await f(t,i&&a.grantee!==s?"message":"read",r))throw a.grantee!==s?new u(403,"other_app_run","cannot change another app's node"):new u(404,"not_found","node not found")}if(e.resource==="node-read"&&!await f(t,"read",r))throw new u(404,"not_found","node not found")}}d(te,"authorizeOperation");async function ne(e,t,n){if(e.resource==="daemon-bash")throw new u(403,"permission_error","a shell on the daemon host is not available to a person bearer");if(e.resource==="human")return await oe(e,t,n);if(n.request_id!==void 0&&e.path.startsWith("/v1/structured-requests/"))return await re(e,t,n.request_id);const o=n.id;if(!(e.resource!=="node-read"&&e.resource!=="node-write"||o===void 0||!await w(o))&&!await f(t,z.has(e.name)?"message":"read",o))throw new u(404,"not_found","node not found")}d(ne,"authorizePersonNode");async function oe(e,t,n){const o=n.ticket_id!==void 0?new u(404,"ticket_not_found","no matching ticket"):new u(404,"not_found","no request with that id"),s=n.request_id?await p(n.request_id):n.ticket_id?await A(n.ticket_id):null,r=n.comment_id?await v(n.comment_id):null,a=n.review_id?await y(n.review_id).catch(()=>null):r?await y(r.review_id).catch(()=>null):null;if((n.request_id??n.ticket_id??n.review_id??n.comment_id)===void 0)return;const c=s?.requester_node_id??a?.origin_node_id;if(!c||!await w(c)||!await f(t,e.method==="GET"?"read":"edit",c))throw o}d(oe,"authorizePersonHuman");async function re(e,t,n){const o=await K(n);if(o!==null&&(o.node_id===null||!await w(o.node_id)||!await f(t,e.method==="GET"?"read":"edit",o.node_id)))throw new u(404,"structured_request_not_found",`unknown structured request: ${n}`)}d(re,"authorizePersonStructuredRequest");async function se(e,t,n){const o=n&&typeof n=="object"&&!Array.isArray(n)?n:{},s=e.path;if(s==="/v1/human/requests"||s==="/v1/human/reviews"){const r=o.source,a=s.endsWith("/reviews")?o.origin_node_id:o.requester_node_id;if(typeof a!="string")throw new u(403,"permission_error","a request must name a node the person acts on");const i=s.endsWith("/requests")&&r&&typeof r=="object"&&"nodeId"in r?r.nodeId:void 0;for(const c of[a,i])if(c!==void 0&&(typeof c!="string"||!await w(c)||!await f(t,"edit",c)))throw new u(404,"not_found","node not found")}if(s==="/v1/structured-requests"){const r=o.target,a=r&&typeof r=="object"&&"kind"in r&&r.kind==="node"&&"node_id"in r?r.node_id:void 0;if(typeof a=="string"&&await w(a)&&!await f(t,"message",a))throw new u(404,"node_not_found",`unknown node: ${a}`)}}d(se,"authorizePersonBody");async function ae(e,t,n,o){if(e.resource==="daemon-bash"&&(!_(o,"crtr:files:rw:user:.")||!_(t.scopes,"crtr:files:rw:user:.")))throw new u(403,"scope_missing","missing scope crtr:files:rw:user:.");if(e.resource==="human"){const r=e.path,a=e.method==="GET";if(!a&&(r.endsWith("/respond")||r.endsWith("/submit")||r.endsWith("/dismiss")||r.endsWith("/progress")||r.endsWith("/comment-ranges")||r.includes("/feedback-comments")))throw new u(403,"permission_error","only the person may answer or edit the human inbox");const i=n.request_id?await p(n.request_id):n.ticket_id?await A(n.ticket_id):null,c=n.comment_id?await v(n.comment_id):null,h=n.review_id?await y(n.review_id):c?await y(c.review_id):null,m=i?.requester_node_id??h?.origin_node_id;if(m!=null){const l=await w(m);if(l&&(a?!await ee(t,l.grantee??"app:terminal",m):l.grantee!==t.app))throw new u(a?404:403,a?"not_found":"other_app_run","human request belongs to another app");if(l&&!a&&!await f(t,"read",m))throw new u(404,"not_found","human request not found")}else if(i||h)throw new u(403,"permission_error","only the person may access a request without a node")}const s=n.id;if(e.resource==="node-own"&&s!==void 0&&s!==t.node)throw new u(403,"other_app_run","the operation requires the calling node")}d(ae,"authorizeBrokerOnly");function de(e,t){if(!_(e,t))throw new I("the bearer token",t)}d(de,"assertCeiling");function ue(){return new u(403,"owner_only","this operation is owner-only; a scoped token does not reach it")}d(ue,"ownerOnlyError");const ie="Crtr-Caused-By",ce=/^(?:message|request|cron_run):[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;function fe(e){const t=e[ie.toLowerCase()];return typeof t=="string"&&ce.test(t)?t:void 0}d(fe,"causedByOf");function Ue(e){return e.map(t=>({...t,ownerOnly:!0}))}d(Ue,"ownerOnly");class Ge{static{d(this,"Router")}routes=[];register(t){const n=V(t.method,t.pattern);if(!n)throw new Error(`route has no operation row: ${t.method} ${t.pattern}`);if(this.routes.some(o=>o.method===t.method.toUpperCase()&&o.operation.path===t.pattern))throw new Error(`duplicate route: ${t.method} ${t.pattern}`);return this.routes.push({operation:n,method:t.method.toUpperCase(),segments:U(t.pattern),handler:t.handler,maxBodyBytes:t.maxBodyBytes??X}),this}registerAll(t){for(const n of t)this.register(n);return this}match(t,n){const o=t.toUpperCase(),s=U(n);for(const r of this.routes){if(r.method!==o)continue;const a=he(r.segments,s);if(a!==null)return{handler:r.handler,params:a,operation:r.operation,maxBodyBytes:r.maxBodyBytes}}return null}async handle(t,n,o,s={class:"person"}){try{const r=new URL(t.url??"/","http://127.0.0.1"),a=(t.method??"GET").toUpperCase(),i=this.match(a,r.pathname);if(i===null){j(n,404,"not_found",`no route for ${a} ${r.pathname}`);return}if(await te(i.operation,s,i.params),o!==null){if(i.operation.classes.length===1&&i.operation.classes[0]==="person")throw ue();i.operation.scope&&de(o,i.operation.scope)}let c;try{c=await we(t,i.maxBodyBytes)}catch(E){const B=E instanceof G?"payload_too_large":"invalid_request";j(n,B==="payload_too_large"?413:400,B,E.message);return}s.class==="person"&&s.sub!==void 0&&await se(i.operation,s,c),s.class==="broker"&&i.operation.resource==="human"&&await Q(i.operation,s,i.params,r.searchParams,c);const h=fe(t.headers),m={...h===void 0?{}:{causedBy:h},method:a,path:r.pathname,params:i.params,query:r.searchParams,body:c,ceiling:o,principal:s,...s.class==="anonymous"&&typeof t.headers.authorization=="string"?{publishToken:t.headers.authorization.slice(7)}:{},req:t,res:n},l=await i.handler(m);n.writableEnded||me(n,l)}catch(r){if(r instanceof Error&&r.code==="person_unresolved"){q(n,503,{error:{code:"runtime_starting",message:"grant sync is not ready",type:"server_error",origin:"runtime",retryable:!0}});return}const{status:a,body:i}=H(r);a>=500&&D({event:"api.request.failed",level:"error",error:r instanceof Error?r:new Error(String(r)),...s.class==="broker"?{node_id:s.node}:{},fields:{method:(t.method??"GET").toUpperCase(),path:t.url??""}}),q(n,a,i)}}}function U(e){return e.split("/").filter(t=>t.length>0)}d(U,"splitPath");function he(e,t){if(e.length!==t.length)return null;const n={};for(let o=0;o<e.length;o++){const s=e[o],r=t[o];if(s.startsWith(":"))n[s.slice(1)]=decodeURIComponent(r);else if(s!==r)return null}return n}d(he,"matchSegments");class G extends Error{static{d(this,"BodyTooLargeError")}}async function we(e,t){const n=[];let o=0;for await(const r of e){const a=r;if(o+=a.length,o>t)throw new G(`request body exceeds ${t} bytes`);n.push(a)}if(o===0)return;const s=Buffer.concat(n).toString("utf8").trim();if(s!=="")try{return JSON.parse(s)}catch{throw new Error("request body is not valid JSON")}}d(we,"readJsonBody");function me(e,t){if(e.headersSent)return;const n={...t.headers??{}};if(t.rawBody!==void 0){e.writeHead(t.status,n),e.end(t.rawBody);return}if(t.status===204||t.body===void 0){e.writeHead(t.status,n),e.end();return}n["content-type"]===void 0&&(n["content-type"]="application/json; charset=utf-8"),e.writeHead(t.status,n),e.end(JSON.stringify(t.body))}d(me,"writeResult");function q(e,t,n){if(e.headersSent){e.end();return}e.writeHead(t,{"content-type":"application/json; charset=utf-8"}),e.end(JSON.stringify(n))}d(q,"writeJson");function j(e,t,n,o){q(e,t,{error:{code:n,message:o,origin:"runtime"}})}d(j,"writeError");export{ie as CAUSED_BY_HEADER,Ge as Router,g as actsAsPerson,k as appOf,de as assertCeiling,ee as canReadNode,We as canReadRun,fe as causedByOf,f as mayOnNode,Ue as ownerOnly,ue as ownerOnlyError,Te as readableNodeIds,ze as requireRun,$ as resolvedScopes,N as runCallerApp};
@@ -1,6 +1,10 @@
1
- import { type IncomingMessage } from 'node:http';
1
+ import { type IncomingMessage, type Server as HttpServer } from 'node:http';
2
+ import { type Server as HttpsServer } from 'node:https';
3
+ import type { Duplex } from 'node:stream';
2
4
  import { Router, type RequestPrincipal } from './router.js';
3
5
  export interface CreateApiServerOptions {
6
+ /** Where the unix socket binds. Defaults to `apiSocketPath()`; a test host binds elsewhere behind a forwarding proxy. */
7
+ socketPath?: string;
4
8
  /** Opt-in TCP listener as `host:port` (or `:port` for all interfaces).
5
9
  * Falls back to `CRTRD_TCP`, then the user setting. Absent → unix socket only. */
6
10
  tcp?: string;
@@ -12,8 +16,12 @@ export interface ApiServer {
12
16
  ready: Promise<void>;
13
17
  /** The actual bound TCP address, including a kernel-selected port; null when TCP is off or not yet bound. */
14
18
  tcpAddress(): string | null;
15
- /** Tear down both listeners and unlink the socket file. Double-close safe. */
16
- close(): Promise<void>;
19
+ /** Tear down both listeners and unlink the socket file. Double-close safe. Without `graceMs` every connection is dropped at
20
+ * once. With it the listeners stop accepting, attach sockets close, and in-flight requests run until they end or
21
+ * `graceMs` passes; then the remaining connections are dropped. */
22
+ close(opts?: {
23
+ graceMs?: number;
24
+ }): Promise<void>;
17
25
  }
18
26
  /** Build the Router loaded with every handler route table (A-7). The order is
19
27
  * irrelevant — the matcher is exact method+path — but `healthRoutes` (which
@@ -21,6 +29,10 @@ export interface ApiServer {
21
29
  export declare function buildRouter(tcpAddress: () => string | null): Router;
22
30
  export type SocketPrincipal = RequestPrincipal;
23
31
  export declare function socketPrincipal(req: IncomingMessage): SocketPrincipal | undefined;
32
+ /** Close one http.Server. Without `graceMs` every connection drops at once. With it, new connections are refused, upgraded
33
+ * (attach) sockets close with 1001 at once, idle keep-alives are dropped as they appear, and in-flight requests run until
34
+ * they end or `graceMs` passes; then every remaining connection is dropped. */
35
+ export declare function closeServer(server: HttpServer | HttpsServer, upgraded: ReadonlySet<Duplex>, graceMs?: number): Promise<void>;
24
36
  /** Create and start the crtrd API server. Returns immediately with a `close()`
25
37
  * handle and a `ready` promise for the mandatory Unix socket bind. TCP remains
26
38
  * opt-in, and its bind or post-listen accept errors are emitted but non-fatal.
@@ -1 +1 @@
1
- var pe=Object.defineProperty;var a=(t,i)=>pe(t,"name",{value:i,configurable:!0});import{createServer as F}from"node:http";import{chmodSync as de,existsSync as H,unlinkSync as G}from"node:fs";import{MINIMUM_RUNTIME_VERSION_HEADER as J,RUNTIME_VERSION_HEADER as P,minimumRuntimeRefusal as me}from"../../api/runtime-version.js";import{CONTRACT_HEADER as I,CONTRACT_LEVEL as V,REQUIRED_CONTRACT_HEADER as K,contractRefusal as fe}from"../../api/contract.js";import{crtrVersion as x}from"../../shared/crtr-version.js";import{apiSocketPath as ge}from"../../core/canvas/paths.js";import{resolveNodeToken as he}from"../../core/canvas/node-tokens.js";import{grantFor as Ae,hasSyncedGrants as Re}from"../../core/grants/mirror.js";import{readConfig as B}from"../../core/config.js";import{peerUid as ye}from"../../native/linux.js";import{findScopedApiToken as ve,getApiToken as be,listScopedApiTokens as we}from"../../core/secrets.js";import{emitEvent as g}from"../../core/events/emit.js";import{envCrtrdTcp as Ee,envCrtrdToken as _e}from"../../shared/env.js";import{Router as Q}from"./router.js";import{handleAttachUpgrade as Se,refuseUpgrade as h}from"./bridge.js";import{boundDaemonControl as Te}from"../control.js";import{attachRoutes as Ce,mayAttachNode as X}from"./handlers/attach.js";import{peerRoutes as ke}from"../peer/handlers.js";import{bashJobRoutes as Oe}from"./handlers/bash-jobs.js";import{bashRoutes as Ue}from"./handlers/bash.js";import{hookExecRoutes as Ne}from"./handlers/hook-exec.js";import{brokerOperationRoutes as Y}from"./handlers/broker-ops.js";import{brokerSignalRoutes as ze,brokerSignalStreams as He}from"./handlers/broker-signals.js";import{brokerRecoveryRoutes as Z,nodeFaultRoutes as Pe}from"./handlers/broker-recovery.js";import{canvasRoutes as Ie}from"./handlers/canvas.js";import{chatInventoryRoutes as xe}from"./handlers/chat-inventory.js";import{daemonRoutes as Be}from"./handlers/daemon.js";import{fileRoutes as $e}from"./handlers/files.js";import{focusRoutes as Le}from"./handlers/focus.js";import{analyticsRoutes as We}from"./handlers/analytics.js";import{memoryReadsRoutes as Me}from"./handlers/memory-reads.js";import{memoryRoutes as je}from"./handlers/memory.js";import{healthRoutes as De}from"./handlers/health.js";import{humanRequestRoutes as Fe}from"./handlers/human-requests.js";import{inboxRoutes as Ge}from"./handlers/inbox.js";import{feedbackCommentRoutes as Je}from"./handlers/feedback-comments.js";import{objectRoutes as Ve}from"./handlers/objects.js";import{shareRoutes as Ke}from"./handlers/shares.js";import{customObjectRoutes as Qe}from"./handlers/custom-objects.js";import{docRoutes as Xe}from"./handlers/docs.js";import{deliveryRoutes as q}from"./handlers/delivery.js";import{deliveryRetryRoutes as Ye}from"./handlers/delivery-retry.js";import{packageDocRoutes as Ze}from"./handlers/package-docs.js";import{documentAccessRoutes as qe}from"./handlers/document-access.js";import{pluginAppRoutes as er}from"./handlers/plugin-app-token.js";import{brokerMailRoutes as ee,messageRoutes as rr}from"./handlers/messages.js";import{modelAuthRoutes as tr}from"./handlers/modelauth.js";import{llmRoutes as or}from"./handlers/llm.js";import{providerRoutes as nr}from"./handlers/providers.js";import{modelConfigRoutes as ir}from"./handlers/model-config.js";import{nodeRoutes as sr}from"./handlers/nodes.js";import{nodeRecordRoutes as lr}from"./handlers/node-records.js";import{nodeOutcomeRoutes as ar}from"./handlers/node-outcomes.js";import{nodeEventRoutes as cr}from"./handlers/node-events.js";import{profileRoutes as ur}from"./handlers/profiles.js";import{prospectiveChatInventoryRoutes as pr}from"./handlers/prospective-chat-inventory.js";import{reportRoutes as dr}from"./handlers/reports.js";import{runRoutes as mr}from"./handlers/run-routes.js";import{reviewCommentRoutes as fr}from"./handlers/review-comments.js";import{reviewRoutes as gr}from"./handlers/reviews.js";import{subscriptionRoutes as hr}from"./handlers/subscriptions.js";import{structuredRequestRoutes as Ar}from"./handlers/structured-requests.js";import{cronRoutes as Rr}from"./handlers/crons.js";import{setCronRequestHandler as re}from"../cron/run-socket.js";import{worktreeRoutes as yr}from"./handlers/worktree.js";import{limitsRoutes as vr}from"./handlers/limits.js";import{chargeRoutes as br,spendLimitRoutes as wr}from"./handlers/charges.js";function Er(t){return new Q().registerAll(De(t)).registerAll(Be).registerAll(Ke).registerAll(sr).registerAll(lr).registerAll(ar).registerAll(Ye).registerAll(cr).registerAll(Oe).registerAll(Ue).registerAll(Ne).registerAll(Y).registerAll(ze).registerAll(q).registerAll(Z).registerAll(Pe).registerAll(yr).registerAll(vr).registerAll(br).registerAll(wr).registerAll(ee).registerAll(rr).registerAll(dr).registerAll(mr).registerAll(Ar).registerAll(Ce).registerAll(Ie).registerAll(We).registerAll(Me).registerAll(je).registerAll($e).registerAll(Ve).registerAll(Qe).registerAll(Xe).registerAll(Ze).registerAll(qe).registerAll(er).registerAll(Le).registerAll(hr).registerAll(Rr).registerAll(ur).registerAll(tr).registerAll(or).registerAll(nr).registerAll(ir).registerAll(gr).registerAll(fr).registerAll(Ge).registerAll(Fe).registerAll(xe).registerAll(pr).registerAll(Je).registerAll(ke)}a(Er,"buildRouter");function _r(t,i){if(t.toUpperCase()!=="GET")return null;const c=i.split("/").filter(f=>f.length>0);if(c.length!==4||c[0]!=="v1"||c[1]!=="nodes"||c[3]!=="attach")return null;const d=c[2];return d===void 0||d===""?null:decodeURIComponent(d)}a(_r,"attachNodeId");function Sr(t){const i=t.trim();if(i==="")return null;const c=i.lastIndexOf(":");if(c<0)return null;const d=i.slice(0,c),f=i.slice(c+1),m=Number(f);return!Number.isInteger(m)||m<0||m>65535?null:{host:d===""?"0.0.0.0":d,port:m}}a(Sr,"parseTcp");function Tr(t,i){return`${t.includes(":")?`[${t}]`:t}:${i}`}a(Tr,"formatTcpAddress");const R={code:"unauthorized",message:"missing or invalid bearer token"},v={code:"owner_only",message:"attach is owner-only; a scoped token does not reach it"},$={class:"anonymous",app:"",node:"",run:null,uid:-1,sub:"",grant:null,client_id:null,scopes:[]},b=new WeakMap;function O(t){return b.get(t)}a(O,"socketPrincipal");async function te(t,i){const c=process.platform==="linux"?ye(t.socket):null,d=t.headers.authorization;if(d===void 0)return c===null||i.has(c)?{class:"person"}:"unauthorized";if(typeof d!="string"||!d.startsWith("Bearer "))return"unauthorized";if(d.slice(7).startsWith("crtr_pub_"))return $;if(d.slice(7).startsWith(L)){const A=U(d.slice(7));return A!==void 0&&(c===null||i.has(c))?A.principal:"unauthorized"}const f=await he(d.slice(7));if(!f||c!==null&&c!==f.uid)return"unauthorized";const m=B("user").runtime?.issuer;if(m&&!await Re(m.replace(/\/$/,"")))return"runtime_starting";const C=f.grant??(await Ae("app:terminal",f.sub))?.id??null;return{class:"broker",...f,grant:C}}a(te,"resolveSocketPrincipal");const L="crtr_app_";function U(t){const i=t.startsWith(L)?ve(t):void 0;return i===void 0?void 0:{principal:{class:"app",app:i.grantee,scopes:i.scopes},ceiling:i.scopes}}a(U,"appBearer");function Cr(t){const i=new Map;for(const c of we("user"))i.set(c.token,{principal:{class:"app",app:c.grantee,scopes:c.scopes},ceiling:c.scopes});return i.set(t,{principal:{class:"person"},ceiling:null}),i}a(Cr,"resolveBearers");function oe(t,i){const c=t.headers.authorization;if(typeof c!="string"||!c.startsWith("Bearer "))return;const d=c.slice(7);return d.startsWith(L)?U(d):i.get(d)}a(oe,"authorize");function N(t){t.setHeader(P,x()),t.setHeader(I,V)}a(N,"advertiseRuntime");function S(t){t.setHeader("Access-Control-Allow-Origin","*"),t.setHeader("Access-Control-Expose-Headers",`${P}, ${I}`)}a(S,"exposeRuntimeHeaders");function ne(t,i){return(t.method??"GET").toUpperCase()!=="OPTIONS"?!1:(N(i),i.writeHead(204,{"Access-Control-Allow-Origin":"*","Access-Control-Expose-Headers":`${P}, ${I}`,"Access-Control-Allow-Headers":`authorization, content-type, ${J.toLowerCase()}, ${K.toLowerCase()}`,"Access-Control-Allow-Methods":"GET, POST, PATCH, PUT, DELETE, OPTIONS","Access-Control-Max-Age":"600"}),i.end(),!0)}a(ne,"answerPreflight");function T(t,i=!1){N(t),i&&S(t),t.writeHead(401,{"content-type":"application/json; charset=utf-8"}),t.end(JSON.stringify({error:{...R,origin:"runtime"}}))}a(T,"writeUnauthorized");function kr(t,i){t.writeHead(503,{"content-type":"application/json; charset=utf-8"}),t.end(JSON.stringify({error:{code:"startup_blocked",message:i,origin:"runtime"}}))}a(kr,"writeStartupBlocked");function ie(t){return new Promise(i=>{try{t.closeAllConnections()}catch{}t.close(()=>i())})}a(ie,"closeServer");function Ft(t={}){let i=null;const c=Er(()=>i),d=new Q().registerAll(Y).registerAll(q).registerAll(Z).registerAll(ee),f=a((e,r)=>{const o=Te()?.startupBlock()??null;return o===null||e==="GET"&&(r==="/healthz"||r==="/v1/status"||r==="/v1/ready")||e==="POST"&&(r==="/v1/daemon/migrate"||r==="/v1/daemon/admit")||o.phase==="recovering"&&d.match(e,r)!==null?null:o},"startupBlockFor"),m=ge(),C=new Set([process.getuid?.()??0,...B("user").runtime?.person_uids??[]]),A=a((e,r,o)=>{N(r);const l=a(u=>Array.isArray(u)?u[0]:u,"first"),w=l(e.headers[J.toLowerCase()]),n=me(w,x())??fe(l(e.headers[K.toLowerCase()]),V,{legacyMinimum:w,runtimeVersion:x()});if(n!==null){r.writeHead(n.status,{"content-type":"application/json; charset=utf-8"}),r.end(JSON.stringify({error:{code:n.code,message:n.message,type:"invalid_request_error",origin:"runtime",retryable:!1,..."param"in n?{param:n.param}:{details:n.details}}}));return}const s=a(u=>{const E=O(e);g({event:"api.request.failed",level:"error",...E?.class==="broker"?{node_id:E.node}:{},error:u instanceof Error?u:new Error(String(u))});try{r.headersSent||r.writeHead(500,{"content-type":"application/json; charset=utf-8"}),r.end(JSON.stringify({error:{code:"internal",message:"internal error",origin:"runtime"}}))}catch{}},"internalFailure");let p;try{p=new URL(e.url??"/","http://127.0.0.1")}catch{try{r.writeHead(400,{"content-type":"application/json; charset=utf-8"}),r.end(JSON.stringify({error:{code:"invalid_request",message:"request URL is invalid",origin:"runtime"}}))}catch{}return}try{const u=f((e.method??"GET").toUpperCase(),p.pathname);if(u!==null){kr(r,u.message);return}c.handle(e,r,o,O(e)??{class:"person"}).catch(s)}catch(u){s(u)}},"onRequest"),se=a(async(e,r,o)=>{const l=O(e);return l===void 0||l.class==="person"||await X(l,"either",o)?!0:(h(r,404,"Not Found","node_not_found",`no node ${o}`),!1)},"authorizeAttachUpgrade"),z=a((e,r,o)=>{r.on("error",()=>{});try{const l=new URL(e.url??"/","http://127.0.0.1"),w=f((e.method??"GET").toUpperCase(),l.pathname);if(w!==null){h(r,503,"Service Unavailable","startup_blocked",w.message);return}const n=_r(e.method??"GET",l.pathname);if(n===null){r.destroy();return}se(e,r,n).then(s=>s?Se(e,r,o,n,async p=>{const u=O(e);return u===void 0||u.class==="person"||await X(u,p,n)}):void 0).catch(()=>{try{r.destroy()}catch{}})}catch{try{r.destroy()}catch{}}},"onUpgrade"),le=a(e=>{e.on("error",r=>{g({event:"api.server.failed",level:"error",error:r})})},"bindErrorHandler"),ae=a(async(e,r)=>{try{const o=await te(e,C);if(o==="unauthorized"){g({event:"api.principal.denied",level:"warn",fields:{method:e.method}}),T(r);return}if(o==="runtime_starting"){N(r),r.writeHead(503,{"content-type":"application/json; charset=utf-8"}),r.end(JSON.stringify({error:{code:"runtime_starting",message:"grant sync is not ready",type:"server_error",origin:"runtime",retryable:!0}}));return}b.set(e,o),o.class==="broker"&&g({event:"api.request.principal",level:o.app==="app:terminal"?"debug":"info",node_id:o.node,fields:{principal:`${o.app} node:${o.node}`,method:e.method,path:e.url}}),A(e,r,o.class==="app"?o.scopes:null)}catch(o){g({event:"api.principal.failed",level:"error",error:o instanceof Error?o:new Error(String(o))}),T(r)}},"onSocketRequest"),_=F((e,r)=>{ae(e,r).catch(o=>g({event:"api.principal.failed",level:"error",error:o instanceof Error?o:new Error(String(o))}))}),ce=a(async(e,r,o)=>{try{const l=await te(e,C);if(l==="unauthorized"||l==="runtime_starting"){l==="unauthorized"&&g({event:"api.principal.denied",level:"warn",fields:{method:e.method}}),h(r,l==="unauthorized"?401:503,"Unauthorized",l,"socket principal unavailable");return}if(l.class!=="person"&&l.class!=="broker"){h(r,403,"Forbidden",v.code,v.message);return}b.set(e,l),z(e,r,o)}catch(l){g({event:"api.principal.failed",level:"error",error:l instanceof Error?l:new Error(String(l))}),h(r,401,"Unauthorized",R.code,R.message)}},"onSocketUpgrade");_.on("upgrade",(e,r,o)=>{ce(e,r,o).catch(l=>g({event:"api.principal.failed",level:"error",error:l instanceof Error?l:new Error(String(l))}))}),re((e,r,o)=>{b.set(e,o),A(e,r,null)});let W=!1,M,j;const ue=new Promise((e,r)=>{M=e,j=r});_.once("listening",()=>{W=!0,M()}),_.on("error",e=>{g({event:"api.server.failed",level:"error",error:e}),W||j(e)});try{H(m)&&G(m)}catch{}_.listen(m,()=>{try{de(m,process.platform==="linux"&&H("/run/crtr/launcher.sock")?438:384)}catch(e){g({event:"api.socket.chmod_failed",level:"error",error:e instanceof Error?e:new Error(String(e))})}});let y;const k=t.tcp??Ee()??B("user").api.tcp;if(k!==void 0&&k!==""){const e=Sr(k);if(e===null)g({event:"api.tcp.invalid",level:"error",error:new Error(`invalid CRTRD_TCP/--tcp spec: ${k}`)});else{const r=t.token??_e()??be("user"),o=r===void 0?void 0:Cr(r),l=o===void 0?(n,s)=>{if(ne(n,s))return;const p=n.headers.authorization;if(typeof p=="string"&&p.startsWith("Bearer crtr_pub_"))b.set(n,$),S(s);else if(n.headers.origin!==void 0){T(s,!0);return}else if(p!==void 0){const E=typeof p=="string"&&p.startsWith("Bearer ")?U(p.slice(7)):void 0;if(E===void 0){T(s,!0);return}b.set(n,E.principal),S(s),A(n,s,E.ceiling);return}A(n,s,null)}:(n,s)=>{if(ne(n,s))return;const p=oe(n,o);if(p===void 0&&n.headers.authorization?.startsWith("Bearer crtr_pub_")){b.set(n,$),S(s),A(n,s,null);return}if(p===void 0){T(s,!0);return}b.set(n,p.principal),S(s),A(n,s,p.ceiling)},w=o===void 0?(n,s,p)=>{if(n.headers.origin!==void 0){h(s,401,"Unauthorized",R.code,R.message);return}const u=n.headers.authorization;if(u!==void 0){if(typeof u=="string"&&u.startsWith("Bearer crtr_pub_")){h(s,403,"Forbidden",v.code,v.message);return}(typeof u=="string"&&u.startsWith("Bearer ")?U(u.slice(7)):void 0)===void 0?h(s,401,"Unauthorized",R.code,R.message):h(s,403,"Forbidden",v.code,v.message);return}z(n,s,p)}:(n,s,p)=>{const u=oe(n,o);if(u===void 0){h(s,401,"Unauthorized",R.code,R.message);return}if(u.ceiling!==null){h(s,403,"Forbidden",v.code,v.message);return}z(n,s,p)};y=F(l),y.on("upgrade",w),le(y),y.once("listening",()=>{const n=y?.address();if(n!==null&&typeof n=="object"){const{address:s,port:p}=n;i=Tr(s,p)}}),y.listen(e.port,e.host)}}let D=!1;return{ready:ue,tcpAddress:a(()=>i,"tcpAddress"),close:a(async()=>{if(!D){D=!0,re(null),He.close(),await Promise.all([ie(_),y!==void 0?ie(y):Promise.resolve()]);try{H(m)&&G(m)}catch{}}},"close")}}a(Ft,"createApiServer");export{Er as buildRouter,Ft as createApiServer,O as socketPrincipal};
1
+ var Ce=Object.defineProperty;var i=(e,r)=>Ce(e,"name",{value:r,configurable:!0});import{createServer as Q}from"node:http";import{createServer as Oe}from"node:https";import{chmodSync as Ue,existsSync as D,readFileSync as q,unlinkSync as ee}from"node:fs";import{MINIMUM_RUNTIME_VERSION_HEADER as re,RUNTIME_VERSION_HEADER as x,minimumRuntimeRefusal as ke}from"../../api/runtime-version.js";import{CONTRACT_HEADER as $,CONTRACT_LEVEL as te,REQUIRED_CONTRACT_HEADER as ne,contractRefusal as Pe}from"../../api/contract.js";import{crtrVersion as j}from"../../shared/crtr-version.js";import{apiSocketPath as Ne}from"../../core/canvas/paths.js";import{resolveNodeToken as ze}from"../../core/canvas/node-tokens.js";import{isCloudRole as J,runAsPerson as M}from"../../core/canvas/person.js";import{personBearerVerifier as oe}from"./auth/person-bearer.js";import{personHasSnapshot as ie}from"../../core/scoped-state/person-store.js";import{loadPersonSettings as se}from"../../core/scoped-state/person-rows.js";import{AppPrincipalResolver as He}from"./principal.js";import{handleVendorSignIn as Ie,isVendorSignInPath as Le}from"./vendor-signin.js";import{RunError as b}from"../../core/runs/operations.js";import{removeVendorAccount as Be,vendorStatus as De}from"./handlers/vendor-status.js";import{toErrorBody as xe}from"./map.js";import{CONTROL_BODY_MAX_BYTES as $e}from"../../core/llm/body-limits.js";import{grantFor as je,hasSyncedGrants as Je}from"../../core/grants/mirror.js";import{readConfig as V}from"../../core/config.js";import{peerUid as Me}from"../../native/linux.js";import{findScopedApiToken as Ve,getApiToken as Ge,listScopedApiTokens as We}from"../../core/secrets.js";import{emitEvent as R}from"../../core/events/emit.js";import{envCrtrdTcp as Fe,envCrtrdToken as Ye}from"../../shared/env.js";import{Router as ae,actsAsPerson as le}from"./router.js";import{handleAttachUpgrade as Ze,refuseUpgrade as y}from"./bridge.js";import{boundDaemonControl as Ke}from"../control.js";import{attachRoutes as Xe,mayAttachNode as ce}from"./handlers/attach.js";import{peerRoutes as Qe}from"../peer/handlers.js";import{bashJobRoutes as qe}from"./handlers/bash-jobs.js";import{bashRoutes as er}from"./handlers/bash.js";import{hookExecRoutes as rr}from"./handlers/hook-exec.js";import{brokerOperationRoutes as ue}from"./handlers/broker-ops.js";import{brokerSignalRoutes as tr,brokerSignalStreams as nr}from"./handlers/broker-signals.js";import{brokerRecoveryRoutes as de,nodeFaultRoutes as or}from"./handlers/broker-recovery.js";import{canvasRoutes as ir}from"./handlers/canvas.js";import{conversationRoutes as sr}from"./handlers/conversations.js";import{chatInventoryRoutes as ar}from"./handlers/chat-inventory.js";import{daemonRoutes as lr}from"./handlers/daemon.js";import{fileRoutes as cr}from"./handlers/files.js";import{focusRoutes as ur}from"./handlers/focus.js";import{analyticsRoutes as dr}from"./handlers/analytics.js";import{memoryReadsRoutes as pr}from"./handlers/memory-reads.js";import{memoryRoutes as fr}from"./handlers/memory.js";import{healthRoutes as mr}from"./handlers/health.js";import{humanRequestRoutes as gr}from"./handlers/human-requests.js";import{inboxRoutes as hr}from"./handlers/inbox.js";import{feedbackCommentRoutes as Rr}from"./handlers/feedback-comments.js";import{objectRoutes as Ar}from"./handlers/objects.js";import{shareRoutes as yr}from"./handlers/shares.js";import{customObjectRoutes as vr}from"./handlers/custom-objects.js";import{docRoutes as wr}from"./handlers/docs.js";import{deliveryRoutes as pe}from"./handlers/delivery.js";import{deliveryRetryRoutes as _r}from"./handlers/delivery-retry.js";import{packageDocRoutes as Sr}from"./handlers/package-docs.js";import{documentAccessRoutes as Er}from"./handlers/document-access.js";import{pluginAppRoutes as Tr}from"./handlers/plugin-app-token.js";import{brokerMailRoutes as fe,messageRoutes as br}from"./handlers/messages.js";import{modelAuthRoutes as Cr}from"./handlers/modelauth.js";import{llmRoutes as Or}from"./handlers/llm.js";import{providerRoutes as Ur}from"./handlers/providers.js";import{modelConfigRoutes as kr}from"./handlers/model-config.js";import{settingsRoutes as Pr}from"./handlers/settings.js";import{nodeRoutes as Nr}from"./handlers/nodes.js";import{nodeRecordRoutes as zr}from"./handlers/node-records.js";import{nodeOutcomeRoutes as Hr}from"./handlers/node-outcomes.js";import{nodeEventRoutes as Ir}from"./handlers/node-events.js";import{profileRoutes as Lr}from"./handlers/profiles.js";import{prospectiveChatInventoryRoutes as Br}from"./handlers/prospective-chat-inventory.js";import{reportRoutes as Dr}from"./handlers/reports.js";import{runRoutes as xr}from"./handlers/run-routes.js";import{reviewCommentRoutes as $r}from"./handlers/review-comments.js";import{reviewRoutes as jr}from"./handlers/reviews.js";import{subscriptionRoutes as Jr}from"./handlers/subscriptions.js";import{structuredRequestRoutes as Mr}from"./handlers/structured-requests.js";import{cronRoutes as Vr}from"./handlers/crons.js";import{setCronRequestHandler as me}from"../cron/run-socket.js";import{worktreeRoutes as Gr}from"./handlers/worktree.js";import{limitsRoutes as Wr}from"./handlers/limits.js";import{chargeRoutes as Fr,spendLimitRoutes as Yr}from"./handlers/charges.js";import{executionStartRoutes as Zr}from"./handlers/execution-start.js";import{gitCredentialRoutes as Kr}from"./handlers/git-credential.js";function Xr(e){return new ae().registerAll(mr(e)).registerAll(lr).registerAll(yr).registerAll(Nr).registerAll(zr).registerAll(Hr).registerAll(_r).registerAll(Ir).registerAll(qe).registerAll(er).registerAll(rr).registerAll(ue).registerAll(tr).registerAll(pe).registerAll(de).registerAll(or).registerAll(Gr).registerAll(Wr).registerAll(Fr).registerAll(Zr).registerAll(Kr).registerAll(Yr).registerAll(fe).registerAll(br).registerAll(Dr).registerAll(xr).registerAll(Mr).registerAll(Xe).registerAll(ir).registerAll(sr).registerAll(dr).registerAll(pr).registerAll(fr).registerAll(cr).registerAll(Ar).registerAll(vr).registerAll(wr).registerAll(Sr).registerAll(Er).registerAll(Tr).registerAll(ur).registerAll(Jr).registerAll(Vr).registerAll(Lr).registerAll(Cr).registerAll(Or).registerAll(Ur).registerAll(kr).registerAll(Pr).registerAll(jr).registerAll($r).registerAll(hr).registerAll(gr).registerAll(ar).registerAll(Br).registerAll(Rr).registerAll(Qe)}i(Xr,"buildRouter");function Qr(e,r){if(e.toUpperCase()!=="GET")return null;const s=r.split("/").filter(f=>f.length>0);if(s.length!==4||s[0]!=="v1"||s[1]!=="nodes"||s[3]!=="attach")return null;const o=s[2];return o===void 0||o===""?null:decodeURIComponent(o)}i(Qr,"attachNodeId");function qr(e){const r=e.trim();if(r==="")return null;const s=r.lastIndexOf(":");if(s<0)return null;const o=r.slice(0,s),f=r.slice(s+1),d=Number(f);return!Number.isInteger(d)||d<0||d>65535?null:{host:o===""?"0.0.0.0":o,port:d}}i(qr,"parseTcp");function et(e,r){return`${e.includes(":")?`[${e}]`:e}:${r}`}i(et,"formatTcpAddress");const E={code:"unauthorized",message:"missing or invalid bearer token"},H={code:"owner_only",message:"attach is owner-only; a scoped token does not reach it"},k={code:"person_bearer_not_supported",message:"this listener accepts a person bearer only on a cloud role with CRTR_DIRECTORY_URL and CRTR_PUBLIC_API_URL set; call with a node, app or public token"},G={class:"anonymous",app:"",node:"",run:null,uid:-1,sub:"",grant:null,client_id:null,scopes:[]},C=new WeakMap;function P(e){return C.get(e)}i(P,"socketPrincipal");async function ge(e,r){const s=process.platform==="linux"?Me(e.socket):null,o=e.headers.authorization;if(o===void 0)return s===null||r.has(s)?{class:"person"}:"unauthorized";if(typeof o!="string"||!o.startsWith("Bearer "))return"unauthorized";if(o.slice(7).startsWith("crtr_pub_"))return G;if(o.slice(7).startsWith(W)){const f=ye(o.slice(7));return f!==void 0&&(s===null||r.has(s))?f.principal:"unauthorized"}return he(o.slice(7),s)}i(ge,"resolveSocketPrincipal");async function he(e,r){const s=await ze(e);if(!s||r!==null&&r!==s.uid)return"unauthorized";const o=V("user").runtime?.issuer;if(o&&!await Je(o.replace(/\/$/,"")))return"runtime_starting";const f=s.grant??(await je("app:terminal",s.sub))?.id??null;return{class:"broker",...s,grant:f}}i(he,"brokerPrincipal");function Re(e){if(e.class!=="anonymous")return e.sub!==void 0&&e.sub!==""?e.sub:void 0}i(Re,"requestPerson");function Ae(e,r){r.class==="broker"&&R({event:"api.request.principal",level:r.app==="app:terminal"?"debug":"info",node_id:r.node,fields:{principal:`${r.app} node:${r.node}`,method:e.method,path:e.url}})}i(Ae,"noteBrokerRequest");const W="crtr_app_";function ye(e){const r=e.startsWith(W)?Ve(e):void 0;return r===void 0?void 0:{principal:{class:"app",app:r.grantee,scopes:r.scopes},ceiling:r.scopes}}i(ye,"appBearer");function rt(e){const r=new Map;for(const s of We("user"))r.set(s.token,{principal:{class:"app",app:s.grantee,scopes:s.scopes},ceiling:s.scopes});return e!==void 0&&r.set(e,{principal:{class:"person"},ceiling:null}),r}i(rt,"resolveBearers");const tt=/^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]*$/;async function ve(e,r){const s=e.headers.authorization;if(s===void 0&&(e.method??"GET").toUpperCase()==="GET"&&(e.url??"").split("?")[0]==="/healthz")return{principal:G,ceiling:null};if(typeof s!="string"||!s.startsWith("Bearer "))return"unauthorized";const o=s.slice(7);if(o.startsWith("crtr_pub_"))return{principal:G,ceiling:null};if(o.startsWith(W))return ye(o)??"unauthorized";const f=r.get(o);if(f!==void 0)return f;if(tt.test(o)){const h=J()?oe():null;if(h===null)return"person_bearer";const m=await h.verify(o);return m===null?"unauthorized":{principal:{class:"person",sub:m},ceiling:null}}const d=await he(o,null);return typeof d=="string"?d:{principal:d,ceiling:null}}i(ve,"authorizeTcp");let I;function nt(){if(I!==void 0)return I;const e=process.env.CRTR_DIRECTORY_URL||void 0,r=process.env.CRTR_PUBLIC_API_URL||void 0;return I=e===void 0||r===void 0?null:new He(e,r,async()=>{}),I}i(nt,"vendorHandoffResolver");async function ot(e,r){T(r),O(r);const s=nt();try{if(s===null)throw new b(503,"runtime_starting","vendor sign-in is not configured on this listener");await Ie(e,r,new URL(e.url??"/","http://runtime.local"),s)}catch(o){if(!(o instanceof b))throw o;if(r.headersSent){r.destroy();return}r.writeHead(o.status,{"content-type":"application/json; charset=utf-8","cache-control":"no-store"}),r.end(JSON.stringify({error:{code:o.code,message:o.message,...o.param?{param:o.param}:{},origin:"runtime"}}))}}i(ot,"serveVendorSignIn");function it(){const e=process.env.CRTRD_TLS_CERT||void 0,r=process.env.CRTRD_TLS_KEY||void 0;if(e===void 0&&r===void 0)return null;if(e===void 0||r===void 0)throw new Error("CRTRD_TLS_CERT and CRTRD_TLS_KEY must be set together");return{cert:q(e),key:q(r)}}i(it,"tcpTls");function T(e){e.setHeader(x,j()),e.setHeader($,te)}i(T,"advertiseRuntime");function O(e){e.setHeader("Access-Control-Allow-Origin","*"),e.setHeader("Access-Control-Expose-Headers",`${x}, ${$}`)}i(O,"exposeRuntimeHeaders");function st(e,r){return(e.method??"GET").toUpperCase()!=="OPTIONS"?!1:(T(r),r.writeHead(204,{"Access-Control-Allow-Origin":"*","Access-Control-Expose-Headers":`${x}, ${$}`,"Access-Control-Allow-Headers":`authorization, content-type, ${re.toLowerCase()}, ${ne.toLowerCase()}`,"Access-Control-Allow-Methods":"GET, POST, PATCH, PUT, DELETE, OPTIONS","Access-Control-Max-Age":"600"}),r.end(),!0)}i(st,"answerPreflight");function L(e,r=!1){T(e),r&&O(e),e.writeHead(401,{"content-type":"application/json; charset=utf-8"}),e.end(JSON.stringify({error:{...E,origin:"runtime"}}))}i(L,"writeUnauthorized");function at(e){T(e),O(e),e.writeHead(401,{"content-type":"application/json; charset=utf-8"}),e.end(JSON.stringify({error:{...k,origin:"runtime"}}))}i(at,"writePersonBearerRefused");const lt={"/v1/runtime/vendor-status":{method:"GET",purpose:"vendor_status"},"/v1/runtime/vendor-account-remove":{method:"POST",purpose:"vendor_account_remove"}};async function ct(e,r){if(!J())return!1;const s=new URL(e.url??"/","http://runtime.local").pathname,o=lt[s];if(o===void 0||e.method!==o.method)return!1;const f=i((d,h)=>{T(r),O(r),r.writeHead(d,{"content-type":"application/json; charset=utf-8"}),r.end(JSON.stringify(h))},"answer");try{const d=oe();if(d===null)throw new b(401,k.code,k.message);const h=e.headers.authorization,m=h?.startsWith("Bearer ")?await d.verifyPurpose(h.slice(7),o.purpose):null;if(m===null)throw new b(401,"unauthorized","invalid directory token");const B=o.purpose==="vendor_status"?void 0:await ut(e);f(200,await M(m,async()=>o.purpose==="vendor_status"?De():await Be(B)))}catch(d){const{status:h,body:m}=xe(d);f(h,m)}return!0}i(ct,"serveCloudVendorRoute");async function ut(e){const r=[];let s=0;for await(const o of e){if(s+=o.length,s>$e)throw new b(400,"invalid_request","request body too large");r.push(o)}if(s!==0)try{return JSON.parse(Buffer.concat(r).toString("utf8"))}catch{throw new b(400,"invalid_request","invalid JSON body")}}i(ut,"readVendorBody");function we(e){T(e),e.writeHead(503,{"content-type":"application/json; charset=utf-8"}),e.end(JSON.stringify({error:{code:"runtime_starting",message:"grant sync is not ready",type:"server_error",origin:"runtime",retryable:!0}}))}i(we,"writeRuntimeStarting");function dt(e,r){e.writeHead(503,{"content-type":"application/json; charset=utf-8"}),e.end(JSON.stringify({error:{code:"startup_blocked",message:r,origin:"runtime"}}))}i(dt,"writeStartupBlocked");function _e(e,r,s){return new Promise(o=>{if(s===void 0){try{e.closeAllConnections()}catch{}e.close(()=>o());return}const f=[];e.close(()=>{for(const m of f)clearTimeout(m);o()});for(const m of r)m.destroy();const d=setInterval(()=>e.closeIdleConnections(),250),h=setTimeout(()=>e.closeAllConnections(),s);f.push(d,h),e.closeIdleConnections()})}i(_e,"closeServer");function Vn(e={}){let r=null;const s=Xr(()=>r),o=new ae().registerAll(ue).registerAll(pe).registerAll(de).registerAll(fe),f=i((t,n)=>{const l=Ke()?.startupBlock()??null;return l===null||t==="GET"&&(n==="/healthz"||n==="/v1/status"||n==="/v1/ready")||t==="POST"&&(n==="/v1/daemon/migrate"||n==="/v1/daemon/admit")||l.phase==="recovering"&&o.match(t,n)!==null?null:l},"startupBlockFor"),d=e.socketPath??Ne(),h=new Set([process.getuid?.()??0,...V("user").runtime?.person_uids??[]]),m=i((t,n,l)=>{T(n);const u=i(a=>Array.isArray(a)?a[0]:a,"first"),S=u(t.headers[re.toLowerCase()]),g=ke(S,j())??Pe(u(t.headers[ne.toLowerCase()]),te,{legacyMinimum:S,runtimeVersion:j()});if(g!==null){n.writeHead(g.status,{"content-type":"application/json; charset=utf-8"}),n.end(JSON.stringify({error:{code:g.code,message:g.message,type:"invalid_request_error",origin:"runtime",retryable:!1,..."param"in g?{param:g.param}:{details:g.details}}}));return}const v=i(a=>{const c=P(t);R({event:"api.request.failed",level:"error",...c?.class==="broker"?{node_id:c.node}:{},error:a instanceof Error?a:new Error(String(a))});try{n.headersSent||n.writeHead(500,{"content-type":"application/json; charset=utf-8"}),n.end(JSON.stringify({error:{code:"internal",message:"internal error",origin:"runtime"}}))}catch{}},"internalFailure");let _;try{_=new URL(t.url??"/","http://127.0.0.1")}catch{try{n.writeHead(400,{"content-type":"application/json; charset=utf-8"}),n.end(JSON.stringify({error:{code:"invalid_request",message:"request URL is invalid",origin:"runtime"}}))}catch{}return}try{const a=f((t.method??"GET").toUpperCase(),_.pathname);if(a!==null){dt(n,a.message);return}const c=P(t)??{class:"person"},p=Re(c),A=i(()=>s.handle(t,n,l,c),"handled");(p===void 0?A():M(p,i(async()=>{ie()||await se(p),await A()},"handledAsPerson"))).catch(v)}catch(a){v(a)}},"onRequest"),B=i(async(t,n,l)=>{const u=P(t);return u===void 0||le(u)||await ce(u,"either",l)?!0:(y(n,404,"Not Found","node_not_found",`no node ${l}`),!1)},"authorizeAttachUpgrade"),N=new Set,F=i((t,n,l)=>{N.add(n),n.once("close",()=>N.delete(n)),n.on("error",()=>{});try{const u=new URL(t.url??"/","http://127.0.0.1"),S=f((t.method??"GET").toUpperCase(),u.pathname);if(S!==null){y(n,503,"Service Unavailable","startup_blocked",S.message);return}const g=Qr(t.method??"GET",u.pathname);if(g===null){n.destroy();return}const v=(()=>{const a=P(t);return a===void 0?void 0:Re(a)})(),_=i(()=>B(t,n,g).then(a=>a?Ze(t,n,l,g,async c=>{const p=P(t);return p===void 0||le(p)||await ce(p,c,g)}):void 0),"attach");(v===void 0?_():M(v,async()=>{ie()||await se(v),await _()})).catch(()=>{try{n.destroy()}catch{}})}catch{try{n.destroy()}catch{}}},"onUpgrade"),Se=i(t=>{t.on("error",n=>{R({event:"api.server.failed",level:"error",error:n})})},"bindErrorHandler"),Ee=i(async(t,n)=>{try{const l=await ge(t,h);if(l==="unauthorized"){R({event:"api.principal.denied",level:"warn",fields:{method:t.method}}),L(n);return}if(l==="runtime_starting"){we(n);return}C.set(t,l),Ae(t,l),m(t,n,l.class==="app"?l.scopes:null)}catch(l){R({event:"api.principal.failed",level:"error",error:l instanceof Error?l:new Error(String(l))}),L(n)}},"onSocketRequest"),U=Q((t,n)=>{Ee(t,n).catch(l=>R({event:"api.principal.failed",level:"error",error:l instanceof Error?l:new Error(String(l))}))}),Te=i(async(t,n,l)=>{try{const u=await ge(t,h);if(u==="unauthorized"||u==="runtime_starting"){u==="unauthorized"&&R({event:"api.principal.denied",level:"warn",fields:{method:t.method}}),y(n,u==="unauthorized"?401:503,"Unauthorized",u,"socket principal unavailable");return}if(u.class!=="person"&&u.class!=="broker"){y(n,403,"Forbidden",H.code,H.message);return}C.set(t,u),F(t,n,l)}catch(u){R({event:"api.principal.failed",level:"error",error:u instanceof Error?u:new Error(String(u))}),y(n,401,"Unauthorized",E.code,E.message)}},"onSocketUpgrade");U.on("upgrade",(t,n,l)=>{Te(t,n,l).catch(u=>R({event:"api.principal.failed",level:"error",error:u instanceof Error?u:new Error(String(u))}))}),me((t,n,l)=>{C.set(t,l),m(t,n,null)});let Y=!1,Z,K;const be=new Promise((t,n)=>{Z=t,K=n});U.once("listening",()=>{Y=!0,Z()}),U.on("error",t=>{R({event:"api.server.failed",level:"error",error:t}),Y||K(t)});try{D(d)&&ee(d)}catch{}U.listen(d,()=>{try{Ue(d,process.platform==="linux"&&D("/run/crtr/launcher.sock")?438:384)}catch(t){R({event:"api.socket.chmod_failed",level:"error",error:t instanceof Error?t:new Error(String(t))})}});let w;const z=e.tcp??Fe()??V("user").api.tcp;if(z!==void 0&&z!==""){const t=qr(z);if(t===null)R({event:"api.tcp.invalid",level:"error",error:new Error(`invalid CRTRD_TCP/--tcp spec: ${z}`)});else{const n=e.token??Ye()??Ge("user"),l=rt(n),u=i(async(a,c)=>{if(st(a,c))return;if(J()&&Le(new URL(a.url??"/","http://runtime.local").pathname)){await ot(a,c);return}if(await ct(a,c))return;const p=await ve(a,l);if(p==="runtime_starting"){O(c),we(c);return}if(p==="person_bearer"){at(c);return}if(p==="unauthorized"){R({event:"api.principal.denied",level:"warn",fields:{method:a.method,listener:"tcp"}}),L(c,!0);return}C.set(a,p.principal),Ae(a,p.principal),O(c),m(a,c,p.ceiling)},"tcpOnRequest"),S=i(async(a,c,p)=>{const A=await ve(a,l);if(A==="runtime_starting"){y(c,503,"Service Unavailable","runtime_starting","grant sync is not ready");return}if(A==="person_bearer"){y(c,401,"Unauthorized",k.code,k.message);return}if(A==="unauthorized"){y(c,401,"Unauthorized",E.code,E.message);return}if(A.ceiling!==null||A.principal.class==="anonymous"){y(c,403,"Forbidden",H.code,H.message);return}C.set(a,A.principal),F(a,c,p)},"tcpOnUpgrade"),g=i(a=>{R({event:"api.principal.failed",level:"error",error:a instanceof Error?a:new Error(String(a))})},"failed"),v=i((a,c)=>{u(a,c).catch(p=>{g(p),c.headersSent?c.destroy():L(c,!0)})},"listener"),_=it();w=_===null?Q(v):Oe(_,v),w.on("upgrade",(a,c,p)=>{c.on("error",()=>{}),S(a,c,p).catch(A=>{g(A),y(c,401,"Unauthorized",E.code,E.message)})}),Se(w),w.once("listening",()=>{const a=w?.address();if(a!==null&&typeof a=="object"){const{address:c,port:p}=a;r=et(c,p)}}),w.listen(t.port,t.host)}}let X=!1;return{ready:be,tcpAddress:i(()=>r,"tcpAddress"),close:i(async(t={})=>{if(!X){X=!0,me(null),nr.close(),await Promise.all([_e(U,N,t.graceMs),w!==void 0?_e(w,N,t.graceMs):Promise.resolve()]);try{D(d)&&ee(d)}catch{}}},"close")}}i(Vn,"createApiServer");export{Xr as buildRouter,_e as closeServer,Vn as createApiServer,P as socketPrincipal};
@@ -7,5 +7,6 @@ export declare function escapeHtml(value: string): string;
7
7
  export declare function anthropicPage(flow: StartedFlow, nonce: string, returnTo: string, handoff: string): string;
8
8
  export declare function openaiPage(flow: StartedFlow, nonce: string, returnTo: string, handoff: string, now?: number): string;
9
9
  /** Serve one `/signin/vendor*` request; errors propagate as RunErrors so the
10
- * listener answers them with contract 2's envelope (RT-LLM-53). */
10
+ * listener answers them with contract 2's envelope (RT-LLM-53). On a cloud role
11
+ * the request runs as the person the handoff's `sub` names. */
11
12
  export declare function handleVendorSignIn(req: IncomingMessage, res: ServerResponse, url: URL, principal: AppPrincipalResolver): Promise<void>;
@@ -1,4 +1,4 @@
1
- var O=Object.defineProperty;var o=(e,t)=>O(e,"name",{value:t,configurable:!0});import{randomBytes as P}from"node:crypto";import{joinedOwner as N}from"../../core/directory/join.js";import{consumeHandoffJti as R,handoffJtiConsumed as z}from"../../core/model-auth/handoff-jti.js";import{completeModelAuthFlow as H,modelAuthFlowFailure as V,modelAuthProvider as F,readModelAuthFlow as k,startModelAuthFlow as D,waitModelAuthFlow as B,VendorSignInError as x}from"../../core/model-auth/flows.js";import{emitEvent as m}from"../../core/events/emit.js";import{RunError as s}from"../../core/runs/operations.js";import{LONG_POLL_MAX_WAIT_SECONDS as I}from"../../api/long-poll.js";const f="/signin/vendor",$=900,U=I*1e3,G="https://chatgpt.com/#settings/Security";function m1(e){return e===f||e.startsWith(`${f}/`)}o(m1,"isVendorSignInPath");function p(){return new s(401,"unauthorized","invalid vendor sign-in handoff")}o(p,"unauthorized");async function _(e,t){const r=await e.verifyHandoff(t);let n;try{n=N()}catch{n=null}if(r.sub!==n)throw p();return r}o(_,"verifyOwnerHandoff");function J(e){const t=e.headers.authorization;return t?.startsWith("Bearer ")&&t.length>7?t.slice(7):void 0}o(J,"bearer");function y(e,t){const r=e.getAll(t);return r.length===1?r[0]:void 0}o(y,"single");function Z(e,t,r,n){const a=new URL(e);return a.searchParams.set("status",t),r&&a.searchParams.set("reason",r),n&&a.searchParams.set("step",n),a.toString()}o(Z,"returnUrl");function v(e){return e.replace(/[&<>"']/g,t=>({"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"})[t])}o(v,"escapeHtml");function C(e,t,r){e.writeHead(t,{"Content-Type":"application/json; charset=utf-8","Cache-Control":"no-store"}),e.end(JSON.stringify(r))}o(C,"sendJson");async function q(e){const t=[];let r=0;for await(const a of e){if(r+=a.length,r>64*1024)throw new s(400,"invalid_request","request body too large");t.push(a)}let n;try{n=JSON.parse(Buffer.concat(t).toString("utf8"))}catch{throw new s(400,"invalid_request","invalid JSON body")}if(typeof n!="object"||n===null||Array.isArray(n))throw new s(400,"invalid_request","request body must be a JSON object");return n}o(q,"jsonBody");const W=`
1
+ var R=Object.defineProperty;var o=(e,t)=>R(e,"name",{value:t,configurable:!0});import{randomBytes as H}from"node:crypto";import{joinedOwner as V}from"../../core/directory/join.js";import{isCloudRole as k,runAsPerson as F}from"../../core/canvas/person.js";import{consumeHandoffJti as D,handoffJtiConsumed as $}from"../../core/model-auth/handoff-jti.js";import{completeModelAuthFlow as I,modelAuthFlowFailure as B,modelAuthProvider as G,readModelAuthFlow as _,startModelAuthFlow as U,waitModelAuthFlow as J,VendorSignInError as y}from"../../core/model-auth/flows.js";import{emitEvent as p}from"../../core/events/emit.js";import{RunError as s}from"../../core/runs/operations.js";import{LONG_POLL_MAX_WAIT_SECONDS as Z}from"../../api/long-poll.js";const h="/signin/vendor",S=900,W=Z*1e3,q="https://chatgpt.com/#settings/Security";function b1(e){return e===h||e.startsWith(`${h}/`)}o(b1,"isVendorSignInPath");function u(){return new s(401,"unauthorized","invalid vendor sign-in handoff")}o(u,"unauthorized");async function C(e,t){const n=await e.verifyHandoff(t);if(k()){if(!n.sub.startsWith("user:"))throw u();return n}let r;try{r=V()}catch{r=null}if(n.sub!==r)throw u();return n}o(C,"verifyOwnerHandoff");function T(e){const t=e.headers.authorization;return t?.startsWith("Bearer ")&&t.length>7?t.slice(7):void 0}o(T,"bearer");function L(e,t){const n=e.getAll(t);return n.length===1?n[0]:void 0}o(L,"single");function X(e,t,n,r){const a=new URL(e);return a.searchParams.set("status",t),n&&a.searchParams.set("reason",n),r&&a.searchParams.set("step",r),a.toString()}o(X,"returnUrl");function v(e){return e.replace(/[&<>"']/g,t=>({"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"})[t])}o(v,"escapeHtml");function M(e,t,n){e.writeHead(t,{"Content-Type":"application/json; charset=utf-8","Cache-Control":"no-store"}),e.end(JSON.stringify(n))}o(M,"sendJson");async function Y(e){const t=[];let n=0;for await(const a of e){if(n+=a.length,n>64*1024)throw new s(400,"invalid_request","request body too large");t.push(a)}let r;try{r=JSON.parse(Buffer.concat(t).toString("utf8"))}catch{throw new s(400,"invalid_request","invalid JSON body")}if(typeof r!="object"||r===null||Array.isArray(r))throw new s(400,"invalid_request","request body must be a JSON object");return r}o(Y,"jsonBody");const K=`
2
2
  :root{color-scheme:light dark;
3
3
  --canvas:#f0f2f4;--surface:#fff;--sunken:#e5e7ea;--zone:#e5e7ea;--neutral:#e5e7ea;--neutral-hover:#d7d9dc;--neutral-pressed:#cbcdd0;
4
4
  --accent:#217f51;--accent-hover:#1e6e46;--accent-pressed:#1a5e3c;--accent-border:#217f51;--accent-subtle:#d5f7e1;--accent-fg:#1e6e46;--on-accent:#fff;
@@ -83,7 +83,7 @@ form{display:flex;flex-direction:column;gap:.75rem}
83
83
  @keyframes spin{to{transform:rotate(360deg)}}
84
84
  @media (min-width:40rem){.top{padding:0 1.5rem}main{padding:3.5rem 1rem}}
85
85
  @media (max-width:30rem){.card{padding:1.25rem}.btn{padding-left:.875rem;padding-right:.875rem}#device-link{font-size:.84375rem}.steps>li{gap:.75rem}.alert .act{margin-left:1.875rem}}
86
- `,X=`
86
+ `,Q=`
87
87
  (function(){
88
88
  var cfg=JSON.parse(document.getElementById('cfg').textContent);
89
89
  history.replaceState(null,'',location.pathname);
@@ -135,7 +135,7 @@ if(cfg.kind==='anthropic'){
135
135
  }
136
136
  (function poll(){
137
137
  fetch(cfg.base+'/wait',{headers:auth})
138
- .then(function(r){if(r.status===401||r.status===404)return {status:'failed',reason:'runtime'};if(!r.ok)throw new Error(String(r.status));return r.json();})
138
+ .then(function(r){if(r.status===401||r.status===404)return {status:'failed',reason:'runtime',step:'browser_wait'};if(!r.ok)throw new Error(String(r.status));return r.json();})
139
139
  .then(function(b){
140
140
  if(b.status==='pending'){poll();return;}
141
141
  if(b.status==='connected'){back('connected');return;}
@@ -146,37 +146,37 @@ if(cfg.kind==='anthropic'){
146
146
  })();
147
147
  }
148
148
  })();
149
- `,Y={arrow:'<path d="M7 7h10v10"/><path d="M7 17 17 7"/>',copy:'<rect width="14" height="14" x="8" y="8" rx="2" ry="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/>',clock:'<circle cx="12" cy="12" r="10"/><path d="M12 6v6l4 2"/>',warn:'<path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3"/><path d="M12 9v4"/><path d="M12 17h.01"/>',alert:'<circle cx="12" cy="12" r="10"/><path d="M12 8v4"/><path d="M12 16h.01"/>',check:'<path d="M20 6 9 18l-5-5"/>'};function d(e,t=""){return`<svg class="ic${t}" viewBox="0 0 24 24" aria-hidden="true" focusable="false">${Y[e]}</svg>`}o(d,"icon");const K='<svg viewBox="-77.5 12 931 931" aria-hidden="true" focusable="false"><path fill="currentColor" d="M234 294m0 0h2l-1 5-6 16-5 15-6 25-4 23-2 22-1 5v47l5 38 5 26 6 22 10 24 8 16 9 14 14 19 13 16 11 13 9 11 11 12 7 8 13 16 11 14 14 19 12 19 12 23 7 17 6 23 3 14 3-1 5-15 20-84 6-24 6-21 10-33 10-25 8-16 8-15 8-12 9-12 8-10 9-10 7-8 6-7 20-20h2l2-4 17-17 7-8 10-13 14-21 8-16 8-18 5-15 2-7 2 1 6 36 2 18v41l-4 28-5 19-7 19-10 21-8 13-10 15-13 17-11 13-12 14-9 10-7 8-9 11h-2l-2 4-9 11-14 19-8 12-15 25-11 21-12 26-9 23-5 12-13 38-12 39-5 18-5 17h-2l-9-29-9-27-14-38-13-29-8-16-11-18-10-13-7-9-25-25-3-2v-2l-3-1v-2l-4-2-10-9-8-7-14-12-20-18-13-13-9-11-12-16-12-20-12-25-7-19-6-23-4-24-1-11-1-3v-39l3-23 6-27 7-23 5-11 11-23 9-16 10-14 8-11 9-11 10-11zM430 22m0 0h2v2h2l7 8 10 11 9 11 12 16 9 15 8 16 6 15 5 19 2 11 1 12v18l-1 16-5 24-5 16-7 15-9 17-7 11-10 15-10 13-9 11-13 14-7 8-11 12-7 8-13 16-11 15-13 20-10 18-8 16-7 18-5 15-4 18-2 14-1 27 2 24 3 17 5 23 8 30 12 36 9 28 3 8 4 12v2l-4-2-68-102-13-22-11-23-9-24-7-26-4-23-2-16v-31l3-25 6-27 7-21 7-15 8-16 14-21 11-14 26-30 12-13 8-10h2l2-4 10-11 7-9 14-19 7-10 13-24 7-19 4-15 3-14 3-22 2-24v-20l-2-31zM615 384m0 0 2 1 6 36 2 18v41l-4 28-5 19-7 19-10 21-8 13-10 15-13 17-11 13-12 14-9 10-7 8-9 11h-2l-2 4-9 11-14 19-8 12-15 25-11 21-2 5h-3l-2 2h-13l-6-5-11-6 1-9h-2l2-14-2 3 1-8 9-36 6-21 10-33 10-25 8-16 8-15 8-12 9-12 8-10 9-10 7-8 6-7 20-20h2l2-4 17-17 7-8 10-13 14-21 8-16 8-18 5-15zM557 254m0 0 2 1 4 16 2 16v34l-2 18-5 20-8 24-14 28-10 16-11 16-13 15-12 14-11 13-11 14-14 19-12 20-8 16-7 19-6 20-4 20-4 35-3 41-3 52-4 28-1 3h-2l-8-42-10-52-7-33-7-43v-54l4-24 5-17 8-20 10-19 7-10 10-13 9-11 19-19 8-7 16-15 8-7 9-9 8-7 11-11 1-2h2l2-4 11-13 10-14 11-17 9-19 8-21zM185 615m0 0 4 5 6 10 9 12 2 1 3 5 5-2 1-1h8l5 5 2 3 7 3 6 3 4 5 8 6 5 3v2h2v2h6l4 3 6 1 1 8 10 3 4 2 9 2 5 6 6 1h6l8 8 7 1 9 7h5l1-4-4-6-10-13-7-9-1-3h-2l-7-9v-3l7 6 7 9 11 14 14 19 12 19 12 23 7 17 6 23 3 14 3-1 5-15 10-42 5-22h2l1-4 1 4-1 8h-2l3 4-1 8 11 6 5 4h13l4-3-1 6-8 17-9 23-5 12-13 38-12 39-5 18-5 17h-2l-9-29-9-27-14-38-13-29-8-16-11-18-10-13-7-9-25-25-3-2v-2l-3-1v-2l-4-2-10-9-8-7-14-12-20-18-13-13-9-11-12-16-9-15zM369 553m0 0h1l1 43 2 3 3 4-1 6-1 1v7l1 2 1 15 7 1 5-2 5 1v-2l3-1 4 1 1-2h-3l1-3 6-2 2 11-1 8-3 12h2v2l3-1 2-12h-2l1-4 1-1 3-21 4-21h1v10l-4 30-3 34-4 69-4 28-1 3h-2l-8-42-10-52-7-33-6-37zM430 22m0 0h2v2h2l7 8 10 11 9 11 4 5 1 5 2 4 1 7 2 2-1 3-5-1h-7l-8-2-5 1v7l-1 1h-5l-2-8-1-2-1-15h-2l-2-31zM417 598m0 0h1v10l-4 30-3 34-4 69-4 28-1 3h-2l-7-37-1-16h8l2 1v-2h2l1-2 2-35v-13l-2-3-3-5-1-8 1-9-1-4-5-2v-2l-3-1v-2l3-1 4 1 1-2h-3l1-3 6-2 2 11-1 8-3 12h2v2l3-1 2-12h-2l1-4 1-1 3-21zM417 598m0 0h1v10l-4 30-3 34-1 17h-2v15l-1 12h-1v-18l1-17v-13l-2-3-3-5-1-8 1-9-1-4-5-2v-2l-3-1v-2l3-1 4 1 1-2h-3l1-3 6-2 2 11-1 8-3 12h2v2l3-1 2-12h-2l1-4 1-1 3-21zM310 619m0 0 4 2 4 6 5 8 7 9 3 5 2-1 2 1 2 10 6-1 2 1v2h-5l3 7 9 13 6 9 3 1v-2l-4-14h3l5 16 3 8 4 12v2l-4-2-60-90zM255 597m0 0 5 3 12 16 9 11 11 13 9 11 11 12 4 5-1 3-7-7-4-1-7-4v-2l-4-2-4-4 4 1 3-1v-3l-5-2-3-5v-2h-2l-6-8v-2l-3-1-1-2-8-1 1-2-2-8-3-4v-2h-2l-4-6-3-4zM425 181m0 0 7 1 1 3 12 2 2 3 3 1v-2h3l1 3-6 2-1 3h-2v2h-2l-1 7-5 1-2-5 2-3h3l1-5-3 1-3 3-1-4-5-2v-5h-6l-3-3zM369 553m0 0h1l1 43 2 3 3 4-1 6-1 1v7l1 2 1 15 2 1h-2l3 13 2 10v5l-3-4-5-25-4-26zM340 614m0 0 1 2h2l6 20 6 18 3 15-2-1-5-15-2-4v-5h-6l-3-2-9-2 2-3v2l5-4h4 2l-1-5-3-12zM296 649m0 0 5 2 11 12 4 5-1 3-7-7-4-1-7-4v-2l-4-2-4-4 4 1 3-1zM403 625m0 0h2l2 11-1 8-2 7-2 1v-9l-1-4-5-2v-2l-3-1v-2l3-1 4 1 1-2h-3l1-3zM417 598m0 0h1v10l-4 30-2 24h-1l-1-17h-2l1-4 1-1 3-21zM163 561m0 0 2 3 5 16 2 6 2 1 3 9 2 4 4-1 1-2 1 3h-2l-2 5 3 6-1 2-3-3-11-24-4-11-2-10zM439 685m0 0 1 2h9l3 4v6l7 2 3 7-4-1-6-4-5-4v-7h-9l-2-2zM369 553m0 0h1l1 43 2 3 3 4-1 6-1 1-1 7-2-2v-7h-2zM434 687m0 0h1v6l-3 9-7 29-4 5 1-8 9-36zM317 672m0 0 6 4 9 11 11 14 6 8v2l-4-2-10-13-7-9-1-3h-2l-7-9zM276 622m0 0 5 5 11 13 7 8-1 2-7-4-3-5v-2h-2l-6-8v-2l-3-1-2-4zM310 619m0 0 4 2 4 6 5 8 7 9-1 4-4-5-8-11-7-11zM416 172m0 0 2 1-1 7h-2v5l4-1-1 3-5 2-3-1v-7l4-8zM381 664m0 0 2 4 6 27v5l-1-2h-2l-5-24zM443 655m0 0 1 4-7 25-1 2h-2l1-7 6-22h2zM163 561m0 0 2 3 5 16 2 6 2 1v5l-2 1-7-18-2-10zM490 702m0 0 1 3-10 15-3 5-4 3v-5l5-5 7-11zM387 698m0 0 1 2h2l3 16v14h-1l-5-26zM426 139m0 0 1 3-1 5-7 22-2-1 2-9 5-18h2zM466 739m0 0h2l-1 6-8 15-3 1 2-7 7-12zM411 636m0 0h2v12l-1 14h-1l-1-17h-2l1-4zM349 645m0 0h3l3 9 3 15-2-1-5-15-2-4zM335 694m0 0 5 3 9 12v2l-4-2-10-13zM386 633m0 0 7 1-3 2-4 1-2 4h-4l-2-6h5zM547 287m0 0 3 2-3 7-1 5h-2l-1 4-2-1 1-5zM557 254m0 0 2 1 3 13-4-1 1-2h-2l-1 3-1-3zM560 311m0 0 3 1-2 5-3 6-9-3v-1l9-1zM409 664m0 0h1v25h-1l-2-24zM340 614m0 0 1 2h2l4 16-4-2-3-12zM438 705m0 0 10 2 1 7-3-1-4-4h-5zM502 685m0 0 1 3-8 11-3 1 2-5zM422 191m0 0 4 1 3 4-2 4-5-3zM359 675m0 0h3l4 13-1 4-4-9zM225 599m0 0 5 2 12 6-3 1-9-4-6-3zM255 597m0 0 5 3 6 8-1 2-3-1-4-6-3-4zM414 180m0 0h1v5l4-1-1 3-5 2-3-1 1-5zM341 665m0 0 3 1 6 9-1 4-8-12zM370 608m0 0h1l1 9 3 1-2 10h-1l-2-12zM439 671m0 0 1 2-4 13h-2l1-7 3-7zM341 658m0 0 6 1v2h-5l-1 5-3-3 1-4zM373 625m0 0h2l1 9 2 1h-2l-1 5h-1l-1-6zM185 615m0 0 4 5 5 8-1 3-4-5-4-7zM434 687m0 0h1v6l-3 9-2 3 1-13zM385 686m0 0h2l2 9v5l-1-2h-2l-1-5zM390 711m0 0h2l1 8v11h-1l-2-10zM355 657m0 0 2 3 4 12v3l-3-1-2-10zM413 624m0 0h1v14l-1-2h-2l1-11zM494 120m0 0h2l2 6v10l-2-3-2-9zM163 561m0 0 2 3 4 13-1 3v-2h-2l-3-13zM489 106m0 0h2l4 10-2 4-4-11zM230 609m0 0 5 1 4 5 3 2-6-1-3-3v-2l-3-1zM392 660m0 0h2v2h2l5 5 2 1-1 4-10-10zM254 615m0 0 8 1 1 1v5l-2-1v-2l-6-2zM190 587m0 0 6 1 2-1 4 2 1 3-13-2zM417 598m0 0h1v10l-1 5-2-1 1-9zM273 545m0 0 2 3 3 8v3h-2l-3-8z"/></svg>',Q={claude:'<svg viewBox="0 0 48 48" aria-hidden="true" focusable="false"><rect width="48" height="48" fill="#F3E9D7"/><path transform="translate(24 24) scale(.13) translate(-124 -124)" fill="#D97757" d="M52.4285 162.873L98.7844 136.879L99.5485 134.602L98.7844 133.334H96.4921L88.7237 132.862L62.2346 132.153L39.3113 131.207L17.0249 130.026L11.4214 128.844L6.2 121.873L6.7094 118.447L11.4214 115.257L18.171 115.847L33.0711 116.911L55.485 118.447L71.6586 119.392L95.728 121.873H99.5485L100.058 120.337L98.7844 119.392L97.7656 118.447L74.5877 102.732L49.4995 86.1905L36.3823 76.62L29.3779 71.7757L25.8121 67.2858L24.2839 57.3608L30.6515 50.2716L39.3113 50.8623L41.4763 51.4531L50.2636 58.1879L68.9842 72.7209L93.4357 90.6804L97.0015 93.6343L98.4374 92.6652L98.6571 91.9801L97.0015 89.2625L83.757 65.2772L69.621 40.8192L63.2534 30.6579L61.5978 24.632C60.9565 22.1032 60.579 20.0111 60.579 17.4246L67.8381 7.49965L71.9133 6.19995L81.7193 7.49965L85.7946 11.0443L91.9074 24.9865L101.714 46.8451L116.996 76.62L121.453 85.4816L123.873 93.6343L124.764 96.1155H126.292V94.6976L127.566 77.9197L129.858 57.3608L132.15 30.8942L132.915 23.4505L136.608 14.4708L143.994 9.62643L149.725 12.344L154.437 19.0788L153.8 23.4505L150.998 41.6463L145.522 70.1215L141.957 89.2625H143.994L146.414 86.7813L156.093 74.0206L172.266 53.698L179.398 45.6635L187.803 36.802L193.152 32.5484H203.34L210.726 43.6549L207.415 55.1159L196.972 68.3492L188.312 79.5739L175.896 96.2095L168.191 109.585L168.882 110.689L170.738 110.53L198.755 104.504L213.91 101.787L231.994 98.7149L240.144 102.496L241.036 106.395L237.852 114.311L218.495 119.037L195.826 123.645L162.07 131.592L161.696 131.893L162.137 132.547L177.36 133.925L183.855 134.279H199.774L229.447 136.524L237.215 141.605L241.8 147.867L241.036 152.711L229.065 158.737L213.019 154.956L175.45 145.977L162.587 142.787H160.805V143.85L171.502 154.366L191.242 172.089L215.82 195.011L217.094 200.682L213.91 205.172L210.599 204.699L188.949 188.394L180.544 181.069L161.696 165.118H160.422V166.772L164.752 173.152L187.803 207.771L188.949 218.405L187.294 221.832L181.308 223.959L174.813 222.777L161.187 203.754L147.305 182.486L136.098 163.345L134.745 164.2L128.075 235.42L125.019 239.082L117.887 241.8L111.902 237.31L108.718 229.984L111.902 215.452L115.722 196.547L118.779 181.541L121.58 162.873L123.291 156.636L123.14 156.219L121.773 156.449L107.699 175.752L86.304 204.699L69.3663 222.777L65.291 224.431L58.2867 220.768L58.9235 214.27L62.8713 208.48L86.304 178.705L100.44 160.155L109.551 149.507L109.462 147.967L108.959 147.924L46.6977 188.512L35.6182 189.93L30.7788 185.44L31.4156 178.115L33.7079 175.752L52.4285 162.873Z"/></svg>',chatgpt:'<svg viewBox="0 0 48 48" aria-hidden="true" focusable="false"><rect width="48" height="48" fill="#0D0D0D"/><path transform="translate(24 24) scale(2.35) translate(-7.98 -8)" fill="#FFF" d="M12.9851 6.93777C13.1163 6.54364 13.1618 6.12607 13.1186 5.71295C13.0754 5.29983 12.9444 4.90072 12.7344 4.54231C12.4232 4.00021 11.9478 3.57101 11.3768 3.31664C10.8058 3.06227 10.1687 2.99589 9.55751 3.12706C9.28184 2.81639 8.943 2.56818 8.56362 2.39905C8.18425 2.22993 7.77314 2.14379 7.3578 2.1464C6.73292 2.1449 6.1237 2.34187 5.61797 2.70892C5.11225 3.07598 4.73616 3.59415 4.54391 4.18873C4.13684 4.27206 3.75225 4.44139 3.41591 4.68539C3.07957 4.92938 2.79924 5.24241 2.59368 5.60352C2.27994 6.14413 2.14602 6.77039 2.21123 7.39205C2.27644 8.01367 2.5374 8.59851 2.95649 9.06224C2.82527 9.45637 2.77975 9.87394 2.82297 10.2871C2.8662 10.7002 2.99718 11.0993 3.20713 11.4577C3.51841 11.9998 3.99385 12.4289 4.56484 12.6833C5.13584 12.9377 5.77289 13.0041 6.38407 12.8729C6.65975 13.1836 6.99862 13.4318 7.37796 13.601C7.75734 13.7701 8.16844 13.8562 8.58379 13.8536C9.20899 13.8552 9.81853 13.6582 10.3244 13.2909C10.8304 12.9236 11.2065 12.4051 11.3986 11.8101C11.8057 11.7268 12.1903 11.5575 12.5266 11.3135C12.8629 11.0695 13.1433 10.7564 13.3488 10.3953C13.6622 9.85477 13.7958 9.22866 13.7304 8.60726C13.6651 7.98587 13.4041 7.40129 12.9851 6.93777ZM8.58472 13.0883C8.0715 13.089 7.57441 12.9093 7.18031 12.5805C7.19808 12.5708 7.22925 12.5537 7.24956 12.5413L9.58061 11.1948C9.63911 11.1615 9.6877 11.1133 9.72136 11.055C9.75505 10.9967 9.77258 10.9305 9.77217 10.8632V7.57684L10.7575 8.14576C10.7626 8.14834 10.7671 8.15214 10.7704 8.15685C10.7738 8.16157 10.7759 8.16704 10.7766 8.17275V10.8943C10.7759 11.4756 10.5448 12.0329 10.1339 12.4441C9.72308 12.8554 9.16599 13.087 8.58472 13.0883ZM3.87091 11.075C3.61385 10.6309 3.5212 10.1105 3.60918 9.60485C3.62649 9.61524 3.65673 9.6337 3.67842 9.64617L6.00947 10.9926C6.06756 11.0266 6.13365 11.0445 6.20094 11.0445C6.2682 11.0445 6.33428 11.0266 6.39238 10.9926L9.23834 9.34936V10.4872C9.23867 10.493 9.23755 10.4988 9.23509 10.5041C9.23264 10.5094 9.22892 10.5139 9.22427 10.5174L6.86782 11.878C6.36379 12.1683 5.76516 12.2467 5.20333 12.0962C4.64148 11.9457 4.1623 11.5784 3.87091 11.075ZM3.25768 5.98617C3.51363 5.54141 3.91789 5.2009 4.39966 5.02421C4.39966 5.04429 4.39851 5.07985 4.39851 5.10452V7.79747C4.3981 7.86473 4.41561 7.93087 4.44924 7.98915C4.48287 8.04739 4.5314 8.09563 4.58984 8.1289L7.4358 9.77197L6.45054 10.3409C6.44568 10.3441 6.44009 10.346 6.43429 10.3465C6.4285 10.3471 6.42265 10.3462 6.41729 10.3439L4.06062 8.98216C3.55747 8.69077 3.19039 8.21176 3.03987 7.65013C2.88935 7.08853 2.96768 6.49014 3.25768 5.98617ZM11.3527 7.86994L8.50669 6.22667L9.49198 5.65799C9.49684 5.6548 9.50243 5.65283 9.50823 5.65231C9.51402 5.65178 9.51985 5.65272 9.5252 5.655L11.8819 7.01554C12.2429 7.2241 12.5371 7.53119 12.7299 7.90087C12.9228 8.27056 13.0063 8.68752 12.9707 9.10295C12.9351 9.51839 12.7819 9.91509 12.5291 10.2466C12.2762 10.5781 11.9341 10.8307 11.5428 10.9749C11.5428 10.9546 11.5428 10.919 11.5428 10.8943V8.20137C11.5434 8.13423 11.5261 8.06814 11.4926 8.0099C11.4592 7.95165 11.4109 7.90336 11.3527 7.86994ZM12.3333 6.394C12.316 6.38337 12.2858 6.36514 12.2641 6.3527L9.93303 5.00621C9.87493 4.97232 9.80887 4.95444 9.74158 4.95444C9.67432 4.95444 9.60824 4.97232 9.55014 5.00621L6.70418 6.64951V5.51167C6.70386 5.50585 6.70497 5.50005 6.70743 5.49479C6.70988 5.48952 6.7136 5.48492 6.71826 5.48144L9.0747 4.12203C9.4357 3.91387 9.84853 3.81281 10.2649 3.83068C10.6812 3.84856 11.0838 3.98462 11.4257 4.22296C11.7675 4.46129 12.0344 4.79204 12.1951 5.17652C12.3559 5.56099 12.4038 5.98327 12.3333 6.394ZM6.16851 8.42203L5.18299 7.85311C5.17784 7.85053 5.17336 7.84673 5.17002 7.84202C5.16668 7.8373 5.16455 7.83183 5.16385 7.82609V5.10452C5.16411 4.6877 5.28311 4.27956 5.5069 3.9279C5.73071 3.57623 6.05006 3.29559 6.42756 3.11883C6.80507 2.94206 7.22509 2.87649 7.63851 2.92977C8.05195 2.98306 8.44163 3.153 8.76197 3.41971C8.74421 3.42941 8.71327 3.44649 8.69272 3.45895L6.36168 4.80542C6.30317 4.83867 6.25462 4.8869 6.22093 4.94516C6.18727 5.0034 6.16974 5.06958 6.17012 5.13683L6.16851 8.42203ZM6.70371 7.26803L7.97126 6.53595L9.23878 7.26757V8.73127L7.97126 9.46292L6.70371 8.73127V7.26803Z"/></svg>'},S="team@northlight.ai";function T(e){const t=JSON.stringify(e.config).replace(/</g,"\\u003c");return`<!doctype html>
149
+ `,e1={arrow:'<path d="M7 7h10v10"/><path d="M7 17 17 7"/>',copy:'<rect width="14" height="14" x="8" y="8" rx="2" ry="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/>',clock:'<circle cx="12" cy="12" r="10"/><path d="M12 6v6l4 2"/>',warn:'<path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3"/><path d="M12 9v4"/><path d="M12 17h.01"/>',alert:'<circle cx="12" cy="12" r="10"/><path d="M12 8v4"/><path d="M12 16h.01"/>',check:'<path d="M20 6 9 18l-5-5"/>'};function d(e,t=""){return`<svg class="ic${t}" viewBox="0 0 24 24" aria-hidden="true" focusable="false">${e1[e]}</svg>`}o(d,"icon");const t1='<svg viewBox="-77.5 12 931 931" aria-hidden="true" focusable="false"><path fill="currentColor" d="M234 294m0 0h2l-1 5-6 16-5 15-6 25-4 23-2 22-1 5v47l5 38 5 26 6 22 10 24 8 16 9 14 14 19 13 16 11 13 9 11 11 12 7 8 13 16 11 14 14 19 12 19 12 23 7 17 6 23 3 14 3-1 5-15 20-84 6-24 6-21 10-33 10-25 8-16 8-15 8-12 9-12 8-10 9-10 7-8 6-7 20-20h2l2-4 17-17 7-8 10-13 14-21 8-16 8-18 5-15 2-7 2 1 6 36 2 18v41l-4 28-5 19-7 19-10 21-8 13-10 15-13 17-11 13-12 14-9 10-7 8-9 11h-2l-2 4-9 11-14 19-8 12-15 25-11 21-12 26-9 23-5 12-13 38-12 39-5 18-5 17h-2l-9-29-9-27-14-38-13-29-8-16-11-18-10-13-7-9-25-25-3-2v-2l-3-1v-2l-4-2-10-9-8-7-14-12-20-18-13-13-9-11-12-16-12-20-12-25-7-19-6-23-4-24-1-11-1-3v-39l3-23 6-27 7-23 5-11 11-23 9-16 10-14 8-11 9-11 10-11zM430 22m0 0h2v2h2l7 8 10 11 9 11 12 16 9 15 8 16 6 15 5 19 2 11 1 12v18l-1 16-5 24-5 16-7 15-9 17-7 11-10 15-10 13-9 11-13 14-7 8-11 12-7 8-13 16-11 15-13 20-10 18-8 16-7 18-5 15-4 18-2 14-1 27 2 24 3 17 5 23 8 30 12 36 9 28 3 8 4 12v2l-4-2-68-102-13-22-11-23-9-24-7-26-4-23-2-16v-31l3-25 6-27 7-21 7-15 8-16 14-21 11-14 26-30 12-13 8-10h2l2-4 10-11 7-9 14-19 7-10 13-24 7-19 4-15 3-14 3-22 2-24v-20l-2-31zM615 384m0 0 2 1 6 36 2 18v41l-4 28-5 19-7 19-10 21-8 13-10 15-13 17-11 13-12 14-9 10-7 8-9 11h-2l-2 4-9 11-14 19-8 12-15 25-11 21-2 5h-3l-2 2h-13l-6-5-11-6 1-9h-2l2-14-2 3 1-8 9-36 6-21 10-33 10-25 8-16 8-15 8-12 9-12 8-10 9-10 7-8 6-7 20-20h2l2-4 17-17 7-8 10-13 14-21 8-16 8-18 5-15zM557 254m0 0 2 1 4 16 2 16v34l-2 18-5 20-8 24-14 28-10 16-11 16-13 15-12 14-11 13-11 14-14 19-12 20-8 16-7 19-6 20-4 20-4 35-3 41-3 52-4 28-1 3h-2l-8-42-10-52-7-33-7-43v-54l4-24 5-17 8-20 10-19 7-10 10-13 9-11 19-19 8-7 16-15 8-7 9-9 8-7 11-11 1-2h2l2-4 11-13 10-14 11-17 9-19 8-21zM185 615m0 0 4 5 6 10 9 12 2 1 3 5 5-2 1-1h8l5 5 2 3 7 3 6 3 4 5 8 6 5 3v2h2v2h6l4 3 6 1 1 8 10 3 4 2 9 2 5 6 6 1h6l8 8 7 1 9 7h5l1-4-4-6-10-13-7-9-1-3h-2l-7-9v-3l7 6 7 9 11 14 14 19 12 19 12 23 7 17 6 23 3 14 3-1 5-15 10-42 5-22h2l1-4 1 4-1 8h-2l3 4-1 8 11 6 5 4h13l4-3-1 6-8 17-9 23-5 12-13 38-12 39-5 18-5 17h-2l-9-29-9-27-14-38-13-29-8-16-11-18-10-13-7-9-25-25-3-2v-2l-3-1v-2l-4-2-10-9-8-7-14-12-20-18-13-13-9-11-12-16-9-15zM369 553m0 0h1l1 43 2 3 3 4-1 6-1 1v7l1 2 1 15 7 1 5-2 5 1v-2l3-1 4 1 1-2h-3l1-3 6-2 2 11-1 8-3 12h2v2l3-1 2-12h-2l1-4 1-1 3-21 4-21h1v10l-4 30-3 34-4 69-4 28-1 3h-2l-8-42-10-52-7-33-6-37zM430 22m0 0h2v2h2l7 8 10 11 9 11 4 5 1 5 2 4 1 7 2 2-1 3-5-1h-7l-8-2-5 1v7l-1 1h-5l-2-8-1-2-1-15h-2l-2-31zM417 598m0 0h1v10l-4 30-3 34-4 69-4 28-1 3h-2l-7-37-1-16h8l2 1v-2h2l1-2 2-35v-13l-2-3-3-5-1-8 1-9-1-4-5-2v-2l-3-1v-2l3-1 4 1 1-2h-3l1-3 6-2 2 11-1 8-3 12h2v2l3-1 2-12h-2l1-4 1-1 3-21zM417 598m0 0h1v10l-4 30-3 34-1 17h-2v15l-1 12h-1v-18l1-17v-13l-2-3-3-5-1-8 1-9-1-4-5-2v-2l-3-1v-2l3-1 4 1 1-2h-3l1-3 6-2 2 11-1 8-3 12h2v2l3-1 2-12h-2l1-4 1-1 3-21zM310 619m0 0 4 2 4 6 5 8 7 9 3 5 2-1 2 1 2 10 6-1 2 1v2h-5l3 7 9 13 6 9 3 1v-2l-4-14h3l5 16 3 8 4 12v2l-4-2-60-90zM255 597m0 0 5 3 12 16 9 11 11 13 9 11 11 12 4 5-1 3-7-7-4-1-7-4v-2l-4-2-4-4 4 1 3-1v-3l-5-2-3-5v-2h-2l-6-8v-2l-3-1-1-2-8-1 1-2-2-8-3-4v-2h-2l-4-6-3-4zM425 181m0 0 7 1 1 3 12 2 2 3 3 1v-2h3l1 3-6 2-1 3h-2v2h-2l-1 7-5 1-2-5 2-3h3l1-5-3 1-3 3-1-4-5-2v-5h-6l-3-3zM369 553m0 0h1l1 43 2 3 3 4-1 6-1 1v7l1 2 1 15 2 1h-2l3 13 2 10v5l-3-4-5-25-4-26zM340 614m0 0 1 2h2l6 20 6 18 3 15-2-1-5-15-2-4v-5h-6l-3-2-9-2 2-3v2l5-4h4 2l-1-5-3-12zM296 649m0 0 5 2 11 12 4 5-1 3-7-7-4-1-7-4v-2l-4-2-4-4 4 1 3-1zM403 625m0 0h2l2 11-1 8-2 7-2 1v-9l-1-4-5-2v-2l-3-1v-2l3-1 4 1 1-2h-3l1-3zM417 598m0 0h1v10l-4 30-2 24h-1l-1-17h-2l1-4 1-1 3-21zM163 561m0 0 2 3 5 16 2 6 2 1 3 9 2 4 4-1 1-2 1 3h-2l-2 5 3 6-1 2-3-3-11-24-4-11-2-10zM439 685m0 0 1 2h9l3 4v6l7 2 3 7-4-1-6-4-5-4v-7h-9l-2-2zM369 553m0 0h1l1 43 2 3 3 4-1 6-1 1-1 7-2-2v-7h-2zM434 687m0 0h1v6l-3 9-7 29-4 5 1-8 9-36zM317 672m0 0 6 4 9 11 11 14 6 8v2l-4-2-10-13-7-9-1-3h-2l-7-9zM276 622m0 0 5 5 11 13 7 8-1 2-7-4-3-5v-2h-2l-6-8v-2l-3-1-2-4zM310 619m0 0 4 2 4 6 5 8 7 9-1 4-4-5-8-11-7-11zM416 172m0 0 2 1-1 7h-2v5l4-1-1 3-5 2-3-1v-7l4-8zM381 664m0 0 2 4 6 27v5l-1-2h-2l-5-24zM443 655m0 0 1 4-7 25-1 2h-2l1-7 6-22h2zM163 561m0 0 2 3 5 16 2 6 2 1v5l-2 1-7-18-2-10zM490 702m0 0 1 3-10 15-3 5-4 3v-5l5-5 7-11zM387 698m0 0 1 2h2l3 16v14h-1l-5-26zM426 139m0 0 1 3-1 5-7 22-2-1 2-9 5-18h2zM466 739m0 0h2l-1 6-8 15-3 1 2-7 7-12zM411 636m0 0h2v12l-1 14h-1l-1-17h-2l1-4zM349 645m0 0h3l3 9 3 15-2-1-5-15-2-4zM335 694m0 0 5 3 9 12v2l-4-2-10-13zM386 633m0 0 7 1-3 2-4 1-2 4h-4l-2-6h5zM547 287m0 0 3 2-3 7-1 5h-2l-1 4-2-1 1-5zM557 254m0 0 2 1 3 13-4-1 1-2h-2l-1 3-1-3zM560 311m0 0 3 1-2 5-3 6-9-3v-1l9-1zM409 664m0 0h1v25h-1l-2-24zM340 614m0 0 1 2h2l4 16-4-2-3-12zM438 705m0 0 10 2 1 7-3-1-4-4h-5zM502 685m0 0 1 3-8 11-3 1 2-5zM422 191m0 0 4 1 3 4-2 4-5-3zM359 675m0 0h3l4 13-1 4-4-9zM225 599m0 0 5 2 12 6-3 1-9-4-6-3zM255 597m0 0 5 3 6 8-1 2-3-1-4-6-3-4zM414 180m0 0h1v5l4-1-1 3-5 2-3-1 1-5zM341 665m0 0 3 1 6 9-1 4-8-12zM370 608m0 0h1l1 9 3 1-2 10h-1l-2-12zM439 671m0 0 1 2-4 13h-2l1-7 3-7zM341 658m0 0 6 1v2h-5l-1 5-3-3 1-4zM373 625m0 0h2l1 9 2 1h-2l-1 5h-1l-1-6zM185 615m0 0 4 5 5 8-1 3-4-5-4-7zM434 687m0 0h1v6l-3 9-2 3 1-13zM385 686m0 0h2l2 9v5l-1-2h-2l-1-5zM390 711m0 0h2l1 8v11h-1l-2-10zM355 657m0 0 2 3 4 12v3l-3-1-2-10zM413 624m0 0h1v14l-1-2h-2l1-11zM494 120m0 0h2l2 6v10l-2-3-2-9zM163 561m0 0 2 3 4 13-1 3v-2h-2l-3-13zM489 106m0 0h2l4 10-2 4-4-11zM230 609m0 0 5 1 4 5 3 2-6-1-3-3v-2l-3-1zM392 660m0 0h2v2h2l5 5 2 1-1 4-10-10zM254 615m0 0 8 1 1 1v5l-2-1v-2l-6-2zM190 587m0 0 6 1 2-1 4 2 1 3-13-2zM417 598m0 0h1v10l-1 5-2-1 1-9zM273 545m0 0 2 3 3 8v3h-2l-3-8z"/></svg>',n1={claude:'<svg viewBox="0 0 48 48" aria-hidden="true" focusable="false"><rect width="48" height="48" fill="#F3E9D7"/><path transform="translate(24 24) scale(.13) translate(-124 -124)" fill="#D97757" d="M52.4285 162.873L98.7844 136.879L99.5485 134.602L98.7844 133.334H96.4921L88.7237 132.862L62.2346 132.153L39.3113 131.207L17.0249 130.026L11.4214 128.844L6.2 121.873L6.7094 118.447L11.4214 115.257L18.171 115.847L33.0711 116.911L55.485 118.447L71.6586 119.392L95.728 121.873H99.5485L100.058 120.337L98.7844 119.392L97.7656 118.447L74.5877 102.732L49.4995 86.1905L36.3823 76.62L29.3779 71.7757L25.8121 67.2858L24.2839 57.3608L30.6515 50.2716L39.3113 50.8623L41.4763 51.4531L50.2636 58.1879L68.9842 72.7209L93.4357 90.6804L97.0015 93.6343L98.4374 92.6652L98.6571 91.9801L97.0015 89.2625L83.757 65.2772L69.621 40.8192L63.2534 30.6579L61.5978 24.632C60.9565 22.1032 60.579 20.0111 60.579 17.4246L67.8381 7.49965L71.9133 6.19995L81.7193 7.49965L85.7946 11.0443L91.9074 24.9865L101.714 46.8451L116.996 76.62L121.453 85.4816L123.873 93.6343L124.764 96.1155H126.292V94.6976L127.566 77.9197L129.858 57.3608L132.15 30.8942L132.915 23.4505L136.608 14.4708L143.994 9.62643L149.725 12.344L154.437 19.0788L153.8 23.4505L150.998 41.6463L145.522 70.1215L141.957 89.2625H143.994L146.414 86.7813L156.093 74.0206L172.266 53.698L179.398 45.6635L187.803 36.802L193.152 32.5484H203.34L210.726 43.6549L207.415 55.1159L196.972 68.3492L188.312 79.5739L175.896 96.2095L168.191 109.585L168.882 110.689L170.738 110.53L198.755 104.504L213.91 101.787L231.994 98.7149L240.144 102.496L241.036 106.395L237.852 114.311L218.495 119.037L195.826 123.645L162.07 131.592L161.696 131.893L162.137 132.547L177.36 133.925L183.855 134.279H199.774L229.447 136.524L237.215 141.605L241.8 147.867L241.036 152.711L229.065 158.737L213.019 154.956L175.45 145.977L162.587 142.787H160.805V143.85L171.502 154.366L191.242 172.089L215.82 195.011L217.094 200.682L213.91 205.172L210.599 204.699L188.949 188.394L180.544 181.069L161.696 165.118H160.422V166.772L164.752 173.152L187.803 207.771L188.949 218.405L187.294 221.832L181.308 223.959L174.813 222.777L161.187 203.754L147.305 182.486L136.098 163.345L134.745 164.2L128.075 235.42L125.019 239.082L117.887 241.8L111.902 237.31L108.718 229.984L111.902 215.452L115.722 196.547L118.779 181.541L121.58 162.873L123.291 156.636L123.14 156.219L121.773 156.449L107.699 175.752L86.304 204.699L69.3663 222.777L65.291 224.431L58.2867 220.768L58.9235 214.27L62.8713 208.48L86.304 178.705L100.44 160.155L109.551 149.507L109.462 147.967L108.959 147.924L46.6977 188.512L35.6182 189.93L30.7788 185.44L31.4156 178.115L33.7079 175.752L52.4285 162.873Z"/></svg>',chatgpt:'<svg viewBox="0 0 48 48" aria-hidden="true" focusable="false"><rect width="48" height="48" fill="#0D0D0D"/><path transform="translate(24 24) scale(2.35) translate(-7.98 -8)" fill="#FFF" d="M12.9851 6.93777C13.1163 6.54364 13.1618 6.12607 13.1186 5.71295C13.0754 5.29983 12.9444 4.90072 12.7344 4.54231C12.4232 4.00021 11.9478 3.57101 11.3768 3.31664C10.8058 3.06227 10.1687 2.99589 9.55751 3.12706C9.28184 2.81639 8.943 2.56818 8.56362 2.39905C8.18425 2.22993 7.77314 2.14379 7.3578 2.1464C6.73292 2.1449 6.1237 2.34187 5.61797 2.70892C5.11225 3.07598 4.73616 3.59415 4.54391 4.18873C4.13684 4.27206 3.75225 4.44139 3.41591 4.68539C3.07957 4.92938 2.79924 5.24241 2.59368 5.60352C2.27994 6.14413 2.14602 6.77039 2.21123 7.39205C2.27644 8.01367 2.5374 8.59851 2.95649 9.06224C2.82527 9.45637 2.77975 9.87394 2.82297 10.2871C2.8662 10.7002 2.99718 11.0993 3.20713 11.4577C3.51841 11.9998 3.99385 12.4289 4.56484 12.6833C5.13584 12.9377 5.77289 13.0041 6.38407 12.8729C6.65975 13.1836 6.99862 13.4318 7.37796 13.601C7.75734 13.7701 8.16844 13.8562 8.58379 13.8536C9.20899 13.8552 9.81853 13.6582 10.3244 13.2909C10.8304 12.9236 11.2065 12.4051 11.3986 11.8101C11.8057 11.7268 12.1903 11.5575 12.5266 11.3135C12.8629 11.0695 13.1433 10.7564 13.3488 10.3953C13.6622 9.85477 13.7958 9.22866 13.7304 8.60726C13.6651 7.98587 13.4041 7.40129 12.9851 6.93777ZM8.58472 13.0883C8.0715 13.089 7.57441 12.9093 7.18031 12.5805C7.19808 12.5708 7.22925 12.5537 7.24956 12.5413L9.58061 11.1948C9.63911 11.1615 9.6877 11.1133 9.72136 11.055C9.75505 10.9967 9.77258 10.9305 9.77217 10.8632V7.57684L10.7575 8.14576C10.7626 8.14834 10.7671 8.15214 10.7704 8.15685C10.7738 8.16157 10.7759 8.16704 10.7766 8.17275V10.8943C10.7759 11.4756 10.5448 12.0329 10.1339 12.4441C9.72308 12.8554 9.16599 13.087 8.58472 13.0883ZM3.87091 11.075C3.61385 10.6309 3.5212 10.1105 3.60918 9.60485C3.62649 9.61524 3.65673 9.6337 3.67842 9.64617L6.00947 10.9926C6.06756 11.0266 6.13365 11.0445 6.20094 11.0445C6.2682 11.0445 6.33428 11.0266 6.39238 10.9926L9.23834 9.34936V10.4872C9.23867 10.493 9.23755 10.4988 9.23509 10.5041C9.23264 10.5094 9.22892 10.5139 9.22427 10.5174L6.86782 11.878C6.36379 12.1683 5.76516 12.2467 5.20333 12.0962C4.64148 11.9457 4.1623 11.5784 3.87091 11.075ZM3.25768 5.98617C3.51363 5.54141 3.91789 5.2009 4.39966 5.02421C4.39966 5.04429 4.39851 5.07985 4.39851 5.10452V7.79747C4.3981 7.86473 4.41561 7.93087 4.44924 7.98915C4.48287 8.04739 4.5314 8.09563 4.58984 8.1289L7.4358 9.77197L6.45054 10.3409C6.44568 10.3441 6.44009 10.346 6.43429 10.3465C6.4285 10.3471 6.42265 10.3462 6.41729 10.3439L4.06062 8.98216C3.55747 8.69077 3.19039 8.21176 3.03987 7.65013C2.88935 7.08853 2.96768 6.49014 3.25768 5.98617ZM11.3527 7.86994L8.50669 6.22667L9.49198 5.65799C9.49684 5.6548 9.50243 5.65283 9.50823 5.65231C9.51402 5.65178 9.51985 5.65272 9.5252 5.655L11.8819 7.01554C12.2429 7.2241 12.5371 7.53119 12.7299 7.90087C12.9228 8.27056 13.0063 8.68752 12.9707 9.10295C12.9351 9.51839 12.7819 9.91509 12.5291 10.2466C12.2762 10.5781 11.9341 10.8307 11.5428 10.9749C11.5428 10.9546 11.5428 10.919 11.5428 10.8943V8.20137C11.5434 8.13423 11.5261 8.06814 11.4926 8.0099C11.4592 7.95165 11.4109 7.90336 11.3527 7.86994ZM12.3333 6.394C12.316 6.38337 12.2858 6.36514 12.2641 6.3527L9.93303 5.00621C9.87493 4.97232 9.80887 4.95444 9.74158 4.95444C9.67432 4.95444 9.60824 4.97232 9.55014 5.00621L6.70418 6.64951V5.51167C6.70386 5.50585 6.70497 5.50005 6.70743 5.49479C6.70988 5.48952 6.7136 5.48492 6.71826 5.48144L9.0747 4.12203C9.4357 3.91387 9.84853 3.81281 10.2649 3.83068C10.6812 3.84856 11.0838 3.98462 11.4257 4.22296C11.7675 4.46129 12.0344 4.79204 12.1951 5.17652C12.3559 5.56099 12.4038 5.98327 12.3333 6.394ZM6.16851 8.42203L5.18299 7.85311C5.17784 7.85053 5.17336 7.84673 5.17002 7.84202C5.16668 7.8373 5.16455 7.83183 5.16385 7.82609V5.10452C5.16411 4.6877 5.28311 4.27956 5.5069 3.9279C5.73071 3.57623 6.05006 3.29559 6.42756 3.11883C6.80507 2.94206 7.22509 2.87649 7.63851 2.92977C8.05195 2.98306 8.44163 3.153 8.76197 3.41971C8.74421 3.42941 8.71327 3.44649 8.69272 3.45895L6.36168 4.80542C6.30317 4.83867 6.25462 4.8869 6.22093 4.94516C6.18727 5.0034 6.16974 5.06958 6.17012 5.13683L6.16851 8.42203ZM6.70371 7.26803L7.97126 6.53595L9.23878 7.26757V8.73127L7.97126 9.46292L6.70371 8.73127V7.26803Z"/></svg>'},A="team@northlight.ai";function E(e){const t=JSON.stringify(e.config).replace(/</g,"\\u003c");return`<!doctype html>
150
150
  <html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
151
151
  <meta name="color-scheme" content="light dark">
152
- <title>${v(e.title)}</title><style nonce="${e.nonce}">${W}</style></head>
152
+ <title>${v(e.title)}</title><style nonce="${e.nonce}">${K}</style></head>
153
153
  <body>
154
- <header class="top">${K}<span>Northlight</span></header>
154
+ <header class="top">${t1}<span>Northlight</span></header>
155
155
  <main><div class="col">${e.body}</div></main>
156
- <footer class="foot"><span>Need help? Email <a href="mailto:${S}">${S}</a></span></footer>
156
+ <footer class="foot"><span>Need help? Email <a href="mailto:${A}">${A}</a></span></footer>
157
157
  <script type="application/json" id="cfg">${t}<\/script>
158
- <script nonce="${e.nonce}">${X}<\/script>
159
- </body></html>`}o(T,"page");function A(e,t){return`<div class="head"><div class="logo">${Q[e]}</div><h1>${t}</h1></div>`}o(A,"header");function h(e,t,r="",n=""){return`<li${n}><span class="n"><span>${e}</span>${d("check")}</span><div class="body"><span class="title">${t}</span>${r}</div></li>`}o(h,"step");function e1(e,t,r,n){return T({nonce:t,title:"Sign in with Claude Code",body:`<div class="card">
160
- ${A("claude","Sign in with Claude Code")}
158
+ <script nonce="${e.nonce}">${Q}<\/script>
159
+ </body></html>`}o(E,"page");function P(e,t){return`<div class="head"><div class="logo">${n1[e]}</div><h1>${t}</h1></div>`}o(P,"header");function f(e,t,n="",r=""){return`<li${r}><span class="n"><span>${e}</span>${d("check")}</span><div class="body"><span class="title">${t}</span>${n}</div></li>`}o(f,"step");function r1(e,t,n,r){return E({nonce:t,title:"Sign in with Claude Code",body:`<div class="card">
160
+ ${P("claude","Sign in with Claude Code")}
161
161
  <ol class="steps">
162
- ${h(1,"Sign in at claude.ai",`<div><a class="btn" href="${v(e.url)}" target="_blank" rel="noopener noreferrer">Open claude.ai${d("arrow")}</a></div>`," data-pre")}
163
- ${h(2,"Copy the code it shows",""," data-pre")}
164
- ${h(3,"Paste it here",`<form id="paste" autocomplete="off">
162
+ ${f(1,"Sign in at claude.ai",`<div><a class="btn" href="${v(e.url)}" target="_blank" rel="noopener noreferrer">Open claude.ai${d("arrow")}</a></div>`," data-pre")}
163
+ ${f(2,"Copy the code it shows",""," data-pre")}
164
+ ${f(3,"Paste it here",`<form id="paste" autocomplete="off">
165
165
  <div class="field"><label for="code">Code from Claude</label>
166
166
  <input type="text" id="code" name="code" required spellcheck="false" autocapitalize="off" aria-describedby="error">
167
167
  <div id="error" class="err" role="alert">${d("alert")}<span id="error-text"></span></div></div>
168
168
  <button class="btn primary lg wide" type="submit">Continue</button>
169
169
  </form>`)}
170
170
  </ol>
171
- </div>`,config:{kind:"anthropic",base:`${f}/${encodeURIComponent(e.flow_id)}`,returnTo:r,handoff:n}})}o(e1,"anthropicPage");function t1(e,t){const r=Date.parse(e.expires_at)-t;return Math.max(0,Math.floor(Math.min(Number.isNaN(r)?$*1e3:r,$*1e3)/1e3))}o(t1,"codeSecondsLeft");function n1(e,t,r,n,a=Date.now()){const i=e.user_code??"";return T({nonce:t,title:"Sign in with Codex",body:`<div class="card">
172
- ${A("chatgpt","Sign in with Codex")}
171
+ </div>`,config:{kind:"anthropic",base:`${h}/${encodeURIComponent(e.flow_id)}`,returnTo:n,handoff:r}})}o(r1,"anthropicPage");function a1(e,t){const n=Date.parse(e.expires_at)-t;return Math.max(0,Math.floor(Math.min(Number.isNaN(n)?S*1e3:n,S*1e3)/1e3))}o(a1,"codeSecondsLeft");function i1(e,t,n,r,a=Date.now()){const i=e.user_code??"";return E({nonce:t,title:"Sign in with Codex",body:`<div class="card">
172
+ ${P("chatgpt","Sign in with Codex")}
173
173
  <ol class="steps" id="device">
174
- ${h(1,"Turn on device code sign-in in ChatGPT settings",`<div><a class="btn" href="${G}" target="_blank" rel="noopener noreferrer">Open settings${d("arrow")}</a></div>`)}
175
- ${h(2,"Open the OpenAI device page",`<div><a class="btn" id="device-link" href="${v(e.url)}" target="_blank" rel="noopener noreferrer">${v(e.url.replace(/^https:\/\//,""))}${d("arrow")}</a></div>`)}
176
- ${h(3,"Enter this code",`<div class="codebox"><span class="code" id="user-code">${v(i)}</span>
174
+ ${f(1,"Turn on device code sign-in in ChatGPT settings",`<div><a class="btn" href="${q}" target="_blank" rel="noopener noreferrer">Open settings${d("arrow")}</a></div>`)}
175
+ ${f(2,"Open the OpenAI device page",`<div><a class="btn" id="device-link" href="${v(e.url)}" target="_blank" rel="noopener noreferrer">${v(e.url.replace(/^https:\/\//,""))}${d("arrow")}</a></div>`)}
176
+ ${f(3,"Enter this code",`<div class="codebox"><span class="code" id="user-code">${v(i)}</span>
177
177
  <span class="badge" id="expired-badge" hidden>Expired</span>
178
178
  <button class="btn sm" type="button" id="copy">${d("copy")}<span id="copy-label">Copy</span></button></div>`)}
179
- ${h(4,"Approve the sign-in",`<span class="small">Make sure it's the account you want to use.</span>`)}
179
+ ${f(4,"Approve the sign-in",`<span class="small">Make sure it's the account you want to use.</span>`)}
180
180
  </ol>
181
181
  <div class="wait" id="waiting">
182
182
  <svg class="spin" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M21 12a9 9 0 1 1-9-9"/></svg>
@@ -186,4 +186,4 @@ ${h(4,"Approve the sign-in",`<span class="small">Make sure it's the account you
186
186
  <div class="alert" id="expired" role="alert" hidden>${d("warn")}
187
187
  <div class="text"><strong>The code expired before it was approved</strong>Codes last 15 minutes. Getting a new one starts the sign-in over.</div>
188
188
  <div class="act"><button class="btn primary sm" type="button" id="renew">Get a new code</button></div></div>
189
- </div>`,config:{kind:"openai",base:`${f}/${encodeURIComponent(e.flow_id)}`,returnTo:r,handoff:n,userCode:i,expiresAt:e.expires_at,remainingSeconds:t1(e,a)}})}o(n1,"openaiPage");async function r1(e,t,r,n){const a=y(r.searchParams,"handoff"),i=await _(n,a);if(z(i.jti))throw p();const l=y(r.searchParams,"return_to");let L;try{L=l===void 0?void 0:new URL(l).origin}catch{L=void 0}if(l===void 0||L!==new URL(n.issuer).origin)throw new s(400,"invalid_request","return_to must be an absolute URL on the directory origin","return_to");const u=y(r.searchParams,"vendor");if(u!=="anthropic"&&u!=="openai")throw new s(400,"invalid_request","vendor must be anthropic or openai","vendor");if(!R(i.jti,i.exp))throw p();let w;try{w=await D({provider:F(u),jti:i.jti})}catch(c){const M=c instanceof x?c.category:"runtime";m({level:"error",event:"vendor_signin.start_failed",error:c,fields:{vendor:u,...c instanceof x?c.logFields():{category:M}}}),t.writeHead(303,{Location:Z(l,"failed",M,c instanceof x?c.step:void 0),"Cache-Control":"no-store","Referrer-Policy":"no-referrer"}),t.end();return}const b=P(16).toString("base64"),j=u==="anthropic"?e1(w,b,l,a):n1(w,b,l,a);t.writeHead(200,{"Content-Type":"text/html; charset=utf-8","Cache-Control":"no-store","Referrer-Policy":"no-referrer","X-Content-Type-Options":"nosniff","Content-Security-Policy":`default-src 'none'; script-src 'nonce-${b}'; style-src 'nonce-${b}'; connect-src 'self'; form-action 'none'; base-uri 'none'; frame-ancestors 'none'`}),t.end(j)}o(r1,"startPage");function g(e,t,r){const{category:n,step:a,fields:i}=V(t);m({level:"warn",event:"vendor_signin.failed",fields:{flow_id:t,message:r,...i}}),C(e,200,{status:"failed",reason:n,...a===void 0?{}:{step:a}})}o(g,"sendFailed");async function E(e,t,r){let n;try{n=await _(t,J(e))}catch(i){throw m({level:"warn",event:"vendor_signin.handoff_rejected",error:i,fields:{flow_id:r}}),i}const a=k(r);if(!a){if(z(n.jti))return!1;throw m({level:"warn",event:"vendor_signin.unauthorized",fields:{flow_id:r,reason:"unknown flow, handoff never started one"}}),p()}if(a.jti===void 0||a.jti!==n.jti)throw m({level:"warn",event:"vendor_signin.unauthorized",fields:{flow_id:r,reason:"handoff did not start this flow"}}),p();return!0}o(E,"followUpFlow");async function a1(e,t,r,n){if(!await E(e,r,n)){g(t,n,"flow_gone");return}const a=await q(e);try{await H(n,a.input),C(t,200,{status:"connected"})}catch(i){const l=k(n);if(l&&l.status!=="pending"){g(t,n,l.message??l.status);return}throw i}}o(a1,"submitCode");async function i1(e,t,r,n){if(!await E(e,r,n)){g(t,n,"flow_gone");return}const a=new AbortController;t.once("close",()=>a.abort());const i=await B(n,U,a.signal);if(!i){g(t,n,"flow_gone");return}if(i.status==="failed"){g(t,n,i.message??"failed");return}C(t,200,{status:i.status})}o(i1,"waitFlow");async function p1(e,t,r,n){const a=e.method??"GET";if(r.pathname===f&&a==="GET"){await r1(e,t,r,n);return}const i=r.pathname.slice(f.length+1).split("/");let l="";try{l=i[0]?decodeURIComponent(i[0]):""}catch{throw new s(404,"not_found","unknown operation")}if(l&&i.length===1&&a==="POST"){await a1(e,t,n,l);return}if(l&&i.length===2&&i[1]==="wait"&&a==="GET"){await i1(e,t,n,l);return}throw new s(404,"not_found","unknown operation")}o(p1,"handleVendorSignIn");export{f as VENDOR_SIGNIN_PATH,e1 as anthropicPage,v as escapeHtml,p1 as handleVendorSignIn,m1 as isVendorSignInPath,n1 as openaiPage};
189
+ </div>`,config:{kind:"openai",base:`${h}/${encodeURIComponent(e.flow_id)}`,returnTo:n,handoff:r,userCode:i,expiresAt:e.expires_at,remainingSeconds:a1(e,a)}})}o(i1,"openaiPage");async function o1(e,t,n,r){const a=L(n.searchParams,"handoff"),i=await C(r,a);if(await $(i.jti))throw u();const l=L(n.searchParams,"return_to");let w;try{w=l===void 0?void 0:new URL(l).origin}catch{w=void 0}if(l===void 0||w!==new URL(r.issuer).origin)throw new s(400,"invalid_request","return_to must be an absolute URL on the directory origin","return_to");const m=L(n.searchParams,"vendor");if(m!=="anthropic"&&m!=="openai")throw new s(400,"invalid_request","vendor must be anthropic or openai","vendor");if(!await D(i.jti,i.exp))throw u();let x;try{x=await U({provider:G(m),jti:i.jti})}catch(c){const z=c instanceof y?c.category:"runtime";p({level:"error",event:"vendor_signin.start_failed",error:c,fields:{vendor:m,...c instanceof y?c.logFields():{category:z}}}),t.writeHead(303,{Location:X(l,"failed",z,c instanceof y?c.step:void 0),"Cache-Control":"no-store","Referrer-Policy":"no-referrer"}),t.end();return}const b=H(16).toString("base64"),N=m==="anthropic"?r1(x,b,l,a):i1(x,b,l,a);t.writeHead(200,{"Content-Type":"text/html; charset=utf-8","Cache-Control":"no-store","Referrer-Policy":"no-referrer","X-Content-Type-Options":"nosniff","Content-Security-Policy":`default-src 'none'; script-src 'nonce-${b}'; style-src 'nonce-${b}'; connect-src 'self'; form-action 'none'; base-uri 'none'; frame-ancestors 'none'`}),t.end(N)}o(o1,"startPage");function g(e,t,n){const{category:r,step:a,fields:i}=B(t);p({level:"warn",event:"vendor_signin.failed",fields:{flow_id:t,message:n,...i}}),M(e,200,{status:"failed",reason:r,...a===void 0?{}:{step:a}})}o(g,"sendFailed");async function j(e,t,n){let r;try{r=await C(t,T(e))}catch(i){throw p({level:"warn",event:"vendor_signin.handoff_rejected",error:i,fields:{flow_id:n}}),i}const a=await _(n);if(!a){if(await $(r.jti))return!1;throw p({level:"warn",event:"vendor_signin.unauthorized",fields:{flow_id:n,reason:"unknown flow, handoff never started one"}}),u()}if(a.jti===void 0||a.jti!==r.jti)throw p({level:"warn",event:"vendor_signin.unauthorized",fields:{flow_id:n,reason:"handoff did not start this flow"}}),u();return!0}o(j,"followUpFlow");async function l1(e,t,n,r){if(!await j(e,n,r)){g(t,r,"flow_gone");return}const a=await Y(e);try{await I(r,a.input),M(t,200,{status:"connected"})}catch(i){const l=await _(r);if(l&&l.status!=="pending"){g(t,r,l.message??l.status);return}throw i}}o(l1,"submitCode");async function s1(e,t,n,r){if(!await j(e,n,r)){g(t,r,"flow_gone");return}const a=new AbortController;t.once("close",()=>a.abort());const i=await J(r,W,a.signal);if(!i){g(t,r,"flow_gone");return}if(i.status==="failed"){g(t,r,i.message??"failed");return}M(t,200,{status:i.status})}o(s1,"waitFlow");async function L1(e,t,n,r){if(!k()){await O(e,t,n,r);return}const a=n.pathname===h&&(e.method??"GET")==="GET",{sub:i}=await C(r,a?L(n.searchParams,"handoff"):T(e));await F(i,()=>O(e,t,n,r))}o(L1,"handleVendorSignIn");async function O(e,t,n,r){const a=e.method??"GET";if(n.pathname===h&&a==="GET"){await o1(e,t,n,r);return}const i=n.pathname.slice(h.length+1).split("/");let l="";try{l=i[0]?decodeURIComponent(i[0]):""}catch{throw new s(404,"not_found","unknown operation")}if(l&&i.length===1&&a==="POST"){await l1(e,t,r,l);return}if(l&&i.length===2&&i[1]==="wait"&&a==="GET"){await s1(e,t,r,l);return}throw new s(404,"not_found","unknown operation")}o(O,"serveVendorSignIn");export{h as VENDOR_SIGNIN_PATH,r1 as anthropicPage,v as escapeHtml,L1 as handleVendorSignIn,b1 as isVendorSignInPath,i1 as openaiPage};
@@ -1,6 +1,20 @@
1
- export declare function hasAttachedBrokerViewers(nodeId: string): boolean;
2
- export declare function hasPresentedViewer(nodeId: string): boolean;
3
- export declare function attachViewer(nodeId: string, connection: object): void;
4
- /** Marks an attending connection as shown the conversation. Returns true the first time only. */
5
- export declare function presentViewer(nodeId: string, connection: object): boolean;
6
- export declare function detachViewer(nodeId: string, connection: object): void;
1
+ export declare const VIEWER_ROW_TTL_MS = 90000;
2
+ export declare const VIEWER_ROW_REFRESH_MS = 30000;
3
+ /** How long a viewer stays attending after its broker connection ended, for its redial to land. */
4
+ export declare const VIEWER_REDIAL_HOLD_MS = 60000;
5
+ /** This process's id on the rows it writes. */
6
+ export declare const API_PROCESS_ID: `${string}-${string}-${string}-${string}-${string}`;
7
+ /** Whether an unexpired attending row exists for the node. */
8
+ export declare function hasAttachedBrokerViewers(nodeId: string): Promise<boolean>;
9
+ /** Whether an unexpired attending row has been shown the conversation (the relay forwarded the broker's welcome). */
10
+ export declare function hasPresentedViewer(nodeId: string): Promise<boolean>;
11
+ /** The row id of an attached connection, for diagnostics and tests. */
12
+ export declare function viewerConnectionId(connection: object): string | undefined;
13
+ /** Insert the attending row for `connection` and keep it fresh until {@link detachViewer} or {@link holdViewerForRedial}. Repeating it is a no-op. */
14
+ export declare function attachViewer(nodeId: string, connection: object): Promise<void>;
15
+ /** Mark an attending connection as shown the conversation. Returns true the first time only. */
16
+ export declare function presentViewer(_nodeId: string, connection: object): Promise<boolean>;
17
+ /** A clean viewer close: delete the row. */
18
+ export declare function detachViewer(_nodeId: string, connection: object): Promise<void>;
19
+ /** The broker connection ended under an open viewer: stop refreshing and keep the row 60 s for the viewer's redial. */
20
+ export declare function holdViewerForRedial(_nodeId: string, connection: object): Promise<void>;
@@ -1 +1,2 @@
1
- var o=Object.defineProperty;var r=(e,n)=>o(e,"name",{value:n,configurable:!0});const i=new Map,s=new Map;function f(e){return(i.get(e)?.size??0)>0}r(f,"hasAttachedBrokerViewers");function u(e){return(s.get(e)?.size??0)>0}r(u,"hasPresentedViewer");function p(e,n){let t=i.get(e);t||(t=new Set,i.set(e,t)),t.add(n)}r(p,"attachViewer");function w(e,n){if(!i.get(e)?.has(n))return!1;let t=s.get(e);return t||(t=new Set,s.set(e,t)),t.has(n)?!1:(t.add(n),!0)}r(w,"presentViewer");function g(e,n){for(const t of[i,s]){const a=t.get(e);a&&(a.delete(n),a.size===0&&t.delete(e))}}r(g,"detachViewer");export{p as attachViewer,g as detachViewer,f as hasAttachedBrokerViewers,u as hasPresentedViewer,w as presentViewer};
1
+ var E=Object.defineProperty;var r=(e,t)=>E(e,"name",{value:t,configurable:!0});import{randomUUID as p}from"node:crypto";import{openDb as a}from"../../core/canvas/db.js";const _=9e4,u=3e4,f=6e4,I=p(),i=new WeakMap,o=r((e=0)=>new Date(Date.now()+e).toISOString(),"at");async function x(e){return await(await a()).prepare("SELECT 1 AS present FROM viewer_attachments WHERE node_id = ? AND attends = 1 AND expires_at > ? LIMIT 1").get(e,o())!==void 0}r(x,"hasAttachedBrokerViewers");async function T(e){return await(await a()).prepare("SELECT 1 AS present FROM viewer_attachments WHERE node_id = ? AND attends = 1 AND presented_at IS NOT NULL AND expires_at > ? LIMIT 1").get(e,o())!==void 0}r(T,"hasPresentedViewer");function A(e){return i.get(e)?.connectionId}r(A,"viewerConnectionId");async function L(e,t){if(i.has(t))return;const n=p(),s=setInterval(()=>{h(n).catch(()=>{})},u);s.unref();const w=(async()=>{const c=o();await(await a()).prepare(`INSERT INTO viewer_attachments (connection_id, node_id, api_process_id, attends, presented_at, opened_at, expires_at)
2
+ VALUES (?, ?, ?, 1, NULL, ?, ?)`).run(n,e,I,c,o(_))})();i.set(t,{connectionId:n,refresh:s,inserted:w.then(()=>!0,()=>!1)});try{await w}catch(c){throw i.get(t)?.connectionId===n&&d(t),c}}r(L,"attachViewer");async function h(e){await(await a()).prepare("UPDATE viewer_attachments SET expires_at = ? WHERE connection_id = ?").run(o(_),e)}r(h,"refreshViewer");async function l(e,t){const n=i.get(t);return n===void 0||!await n.inserted?!1:(await(await a()).prepare("UPDATE viewer_attachments SET presented_at = ? WHERE connection_id = ? AND presented_at IS NULL").run(o(),n.connectionId)).changes===1}r(l,"presentViewer");async function m(e,t){const n=d(t);n===void 0||!await n.inserted||await(await a()).prepare("DELETE FROM viewer_attachments WHERE connection_id = ?").run(n.connectionId)}r(m,"detachViewer");async function N(e,t){const n=d(t);n===void 0||!await n.inserted||await(await a()).prepare("UPDATE viewer_attachments SET expires_at = ? WHERE connection_id = ?").run(o(f),n.connectionId)}r(N,"holdViewerForRedial");function d(e){const t=i.get(e);if(t!==void 0)return clearInterval(t.refresh),i.delete(e),t}r(d,"release");export{I as API_PROCESS_ID,f as VIEWER_REDIAL_HOLD_MS,u as VIEWER_ROW_REFRESH_MS,_ as VIEWER_ROW_TTL_MS,L as attachViewer,m as detachViewer,x as hasAttachedBrokerViewers,T as hasPresentedViewer,N as holdViewerForRedial,l as presentViewer,A as viewerConnectionId};