@north-light/cli 0.3.529 → 0.3.531

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (509) hide show
  1. package/dist/api/dto/lifecycle.d.ts +3 -1
  2. package/dist/api/dto/messages.d.ts +5 -3
  3. package/dist/builtin-memory/crouter-plugin/bundles-and-memory.md +1 -1
  4. package/dist/builtin-memory/crouter-plugin/commands.md +1 -1
  5. package/dist/clients/attach/session/connection.js +1 -1
  6. package/dist/clients/attach/session/reconnect.js +1 -1
  7. package/dist/clients/attach/viewer.js +508 -508
  8. package/dist/commands/node/message.js +1 -1
  9. package/dist/commands/sys/join.js +1 -1
  10. package/dist/core/async-array.d.ts +7 -0
  11. package/dist/core/async-array.js +1 -0
  12. package/dist/core/audit.d.ts +1 -1
  13. package/dist/core/audit.js +2 -2
  14. package/dist/core/canvas/attention.d.ts +4 -4
  15. package/dist/core/canvas/attention.js +1 -1
  16. package/dist/core/canvas/boot.d.ts +4 -4
  17. package/dist/core/canvas/boot.js +1 -1
  18. package/dist/core/canvas/canvas.d.ts +59 -59
  19. package/dist/core/canvas/canvas.js +19 -19
  20. package/dist/core/canvas/context-strip.js +2 -2
  21. package/dist/core/canvas/crons.d.ts +27 -27
  22. package/dist/core/canvas/crons.js +11 -11
  23. package/dist/core/canvas/daemon-actions.d.ts +10 -10
  24. package/dist/core/canvas/daemon-actions.js +8 -8
  25. package/dist/core/canvas/daemon-owner.d.ts +3 -3
  26. package/dist/core/canvas/daemon-owner.js +2 -2
  27. package/dist/core/canvas/db.d.ts +19 -30
  28. package/dist/core/canvas/db.js +3 -2
  29. package/dist/core/canvas/deliveries.d.ts +16 -16
  30. package/dist/core/canvas/deliveries.js +24 -24
  31. package/dist/core/canvas/executions.d.ts +8 -8
  32. package/dist/core/canvas/executions.js +1 -1
  33. package/dist/core/canvas/focuses.d.ts +8 -8
  34. package/dist/core/canvas/focuses.js +1 -1
  35. package/dist/core/canvas/history.d.ts +3 -3
  36. package/dist/core/canvas/history.js +9 -9
  37. package/dist/core/canvas/install-id.d.ts +1 -1
  38. package/dist/core/canvas/install-id.js +1 -1
  39. package/dist/core/canvas/managed-worktree-sweep-candidates.d.ts +1 -1
  40. package/dist/core/canvas/managed-worktree-sweep-candidates.js +2 -2
  41. package/dist/core/canvas/memory-reads.d.ts +6 -6
  42. package/dist/core/canvas/memory-reads.js +1 -1
  43. package/dist/core/canvas/nav-model.d.ts +13 -13
  44. package/dist/core/canvas/nav-model.js +1 -1
  45. package/dist/core/canvas/node-agent-paths.d.ts +6 -6
  46. package/dist/core/canvas/node-agent-paths.js +1 -1
  47. package/dist/core/canvas/node-tokens.d.ts +7 -7
  48. package/dist/core/canvas/node-tokens.js +3 -3
  49. package/dist/core/canvas/outcome-actions.d.ts +5 -5
  50. package/dist/core/canvas/outcome-actions.js +3 -3
  51. package/dist/core/canvas/recovery.d.ts +26 -26
  52. package/dist/core/canvas/recovery.js +2 -2
  53. package/dist/core/canvas/render-source.d.ts +1 -1
  54. package/dist/core/canvas/render-source.js +1 -1
  55. package/dist/core/canvas/sessions.d.ts +10 -10
  56. package/dist/core/canvas/sessions.js +4 -4
  57. package/dist/core/canvas/source.js +1 -1
  58. package/dist/core/canvas/structured-requests.d.ts +15 -15
  59. package/dist/core/canvas/structured-requests.js +5 -5
  60. package/dist/core/canvas/tree.d.ts +9 -9
  61. package/dist/core/canvas/tree.js +5 -5
  62. package/dist/core/canvas/waits.d.ts +13 -13
  63. package/dist/core/canvas/waits.js +6 -6
  64. package/dist/core/canvas/worktrees.d.ts +15 -15
  65. package/dist/core/canvas/worktrees.js +1 -1
  66. package/dist/core/command-hooks/lifecycle-catalog.d.ts +4 -4
  67. package/dist/core/command-hooks/lifecycle-catalog.js +1 -1
  68. package/dist/core/command-hooks/transport/exec-lifecycle.js +1 -1
  69. package/dist/core/command-plugins/bundle.d.ts +1 -1
  70. package/dist/core/command-plugins/bundle.js +1 -1
  71. package/dist/core/conversation-store/file-store.d.ts +7 -7
  72. package/dist/core/conversation-store/file-store.js +9 -9
  73. package/dist/core/conversation-store/index.d.ts +16 -14
  74. package/dist/core/conversation-store/index.js +1 -1
  75. package/dist/core/conversation-store/listener.js +5 -5
  76. package/dist/core/conversation-store/patch.d.ts +3 -1
  77. package/dist/core/conversation-store/patch.js +1 -1
  78. package/dist/core/directory/join.d.ts +1 -1
  79. package/dist/core/feed/feed.js +3 -3
  80. package/dist/core/feed/inbox.d.ts +2 -2
  81. package/dist/core/feed/inbox.js +1 -1
  82. package/dist/core/feed/messages.d.ts +11 -12
  83. package/dist/core/feed/messages.js +5 -5
  84. package/dist/core/feed/reports.d.ts +4 -4
  85. package/dist/core/feed/reports.js +2 -2
  86. package/dist/core/grants/cover.d.ts +1 -1
  87. package/dist/core/grants/cover.js +1 -1
  88. package/dist/core/grants/local.d.ts +1 -1
  89. package/dist/core/grants/local.js +1 -1
  90. package/dist/core/grants/mirror.d.ts +19 -19
  91. package/dist/core/grants/mirror.js +2 -2
  92. package/dist/core/grants/on-sync.d.ts +1 -1
  93. package/dist/core/grants/on-sync.js +1 -1
  94. package/dist/core/grants/remove.js +1 -1
  95. package/dist/core/grants/sync.js +1 -1
  96. package/dist/core/graph/access.d.ts +17 -17
  97. package/dist/core/graph/access.js +3 -3
  98. package/dist/core/graph/custom.d.ts +16 -16
  99. package/dist/core/graph/custom.js +9 -9
  100. package/dist/core/graph/deletion.d.ts +3 -7
  101. package/dist/core/graph/deletion.js +4 -4
  102. package/dist/core/graph/documents.d.ts +24 -27
  103. package/dist/core/graph/documents.js +7 -7
  104. package/dist/core/graph/edges.d.ts +13 -13
  105. package/dist/core/graph/edges.js +1 -1
  106. package/dist/core/graph/events.d.ts +7 -9
  107. package/dist/core/graph/events.js +8 -8
  108. package/dist/core/graph/exposures.d.ts +6 -6
  109. package/dist/core/graph/exposures.js +4 -4
  110. package/dist/core/graph/jobs.d.ts +6 -8
  111. package/dist/core/graph/jobs.js +2 -2
  112. package/dist/core/graph/kinds/action.js +1 -1
  113. package/dist/core/graph/kinds/custom.js +2 -2
  114. package/dist/core/graph/kinds/document.d.ts +1 -0
  115. package/dist/core/graph/kinds/document.js +4 -4
  116. package/dist/core/graph/kinds/dto.d.ts +2 -2
  117. package/dist/core/graph/kinds/dto.js +1 -1
  118. package/dist/core/graph/kinds/job.js +2 -2
  119. package/dist/core/graph/kinds/kind.d.ts +6 -8
  120. package/dist/core/graph/kinds/kind.js +1 -1
  121. package/dist/core/graph/kinds/node.js +5 -5
  122. package/dist/core/graph/kinds/owner.js +2 -2
  123. package/dist/core/graph/kinds/registry.d.ts +6 -9
  124. package/dist/core/graph/kinds/registry.js +1 -1
  125. package/dist/core/graph/names.d.ts +6 -6
  126. package/dist/core/graph/names.js +3 -3
  127. package/dist/core/graph/object-waits.d.ts +4 -7
  128. package/dist/core/graph/object-waits.js +1 -1
  129. package/dist/core/graph/objects.d.ts +14 -14
  130. package/dist/core/graph/objects.js +9 -9
  131. package/dist/core/graph/package-docs.d.ts +2 -7
  132. package/dist/core/graph/package-docs.js +5 -5
  133. package/dist/core/graph/package-kinds.d.ts +2 -5
  134. package/dist/core/graph/package-kinds.js +1 -1
  135. package/dist/core/graph/package-reconcile.d.ts +2 -5
  136. package/dist/core/graph/package-reconcile.js +1 -1
  137. package/dist/core/graph/reader.d.ts +18 -18
  138. package/dist/core/graph/reader.js +3 -3
  139. package/dist/core/graph/receivers.d.ts +4 -4
  140. package/dist/core/graph/receivers.js +5 -5
  141. package/dist/core/graph/repo-sync/exchange.d.ts +3 -7
  142. package/dist/core/graph/repo-sync/exchange.js +2 -2
  143. package/dist/core/graph/repo-sync/repos.d.ts +7 -5
  144. package/dist/core/graph/repo-sync/repos.js +3 -3
  145. package/dist/core/graph/repo-sync/sync.d.ts +3 -6
  146. package/dist/core/graph/repo-sync/sync.js +2 -2
  147. package/dist/core/graph/rules.d.ts +5 -5
  148. package/dist/core/graph/rules.js +3 -3
  149. package/dist/core/graph/spaces/app.js +1 -1
  150. package/dist/core/graph/spaces/index.d.ts +4 -5
  151. package/dist/core/graph/spaces/index.js +1 -1
  152. package/dist/core/graph/spaces/own-memory.d.ts +4 -4
  153. package/dist/core/graph/spaces/own-memory.js +1 -1
  154. package/dist/core/graph/spaces/person.js +3 -3
  155. package/dist/core/graph/spaces/repo.d.ts +1 -1
  156. package/dist/core/graph/spaces/repo.js +1 -1
  157. package/dist/core/graph/watches.d.ts +15 -15
  158. package/dist/core/graph/watches.js +10 -10
  159. package/dist/core/human/feedback-companion.d.ts +2 -2
  160. package/dist/core/human/feedback-companion.js +1 -1
  161. package/dist/core/human/feedback.d.ts +3 -3
  162. package/dist/core/human/feedback.js +1 -1
  163. package/dist/core/human/requests.d.ts +34 -33
  164. package/dist/core/human/requests.js +20 -20
  165. package/dist/core/human/scan.d.ts +2 -2
  166. package/dist/core/human/scan.js +1 -1
  167. package/dist/core/human/tickets.d.ts +9 -9
  168. package/dist/core/human/tickets.js +1 -1
  169. package/dist/core/llm/app-rungs.d.ts +1 -1
  170. package/dist/core/llm/app-rungs.js +1 -1
  171. package/dist/core/llm/run.js +1 -1
  172. package/dist/core/peer/directory.d.ts +1 -1
  173. package/dist/core/peer/directory.js +1 -1
  174. package/dist/core/peer/envelope.d.ts +3 -3
  175. package/dist/core/peer/envelope.js +1 -1
  176. package/dist/core/peer/home.d.ts +7 -7
  177. package/dist/core/peer/home.js +2 -2
  178. package/dist/core/peer/ingest.d.ts +6 -6
  179. package/dist/core/peer/ingest.js +1 -1
  180. package/dist/core/peer/outbox-store.d.ts +14 -14
  181. package/dist/core/peer/outbox-store.js +5 -5
  182. package/dist/core/peer/receiver.d.ts +2 -2
  183. package/dist/core/peer/receiver.js +1 -1
  184. package/dist/core/peer/stubs.d.ts +10 -10
  185. package/dist/core/peer/stubs.js +1 -1
  186. package/dist/core/providers/approval.d.ts +2 -2
  187. package/dist/core/providers/approval.js +2 -2
  188. package/dist/core/providers/audit.d.ts +3 -3
  189. package/dist/core/providers/audit.js +2 -2
  190. package/dist/core/providers/bundles.js +2 -2
  191. package/dist/core/providers/call.d.ts +2 -2
  192. package/dist/core/providers/call.js +1 -1
  193. package/dist/core/providers/files.d.ts +1 -1
  194. package/dist/core/providers/files.js +1 -1
  195. package/dist/core/providers/mint.js +1 -1
  196. package/dist/core/providers/receipts.d.ts +1 -1
  197. package/dist/core/providers/receipts.js +2 -2
  198. package/dist/core/review/birth.js +1 -1
  199. package/dist/core/review/comments.d.ts +19 -19
  200. package/dist/core/review/comments.js +5 -5
  201. package/dist/core/review/companion.d.ts +1 -1
  202. package/dist/core/review/companion.js +1 -1
  203. package/dist/core/review/document.d.ts +3 -3
  204. package/dist/core/review/document.js +2 -2
  205. package/dist/core/review/fork.js +2 -2
  206. package/dist/core/review/realize.js +1 -1
  207. package/dist/core/review/remap.d.ts +2 -2
  208. package/dist/core/review/remap.js +4 -4
  209. package/dist/core/review/stage.d.ts +1 -1
  210. package/dist/core/review/stage.js +1 -1
  211. package/dist/core/review/store.d.ts +21 -21
  212. package/dist/core/review/store.js +1 -1
  213. package/dist/core/runs/activity.d.ts +1 -1
  214. package/dist/core/runs/activity.js +5 -5
  215. package/dist/core/runs/confinement.d.ts +7 -7
  216. package/dist/core/runs/confinement.js +2 -2
  217. package/dist/core/runs/events.d.ts +12 -12
  218. package/dist/core/runs/events.js +4 -4
  219. package/dist/core/runs/operations.d.ts +11 -11
  220. package/dist/core/runs/operations.js +5 -5
  221. package/dist/core/runs/questions.d.ts +10 -10
  222. package/dist/core/runs/questions.js +3 -3
  223. package/dist/core/runtime/auth-reload.js +1 -1
  224. package/dist/core/runtime/bearings.d.ts +5 -5
  225. package/dist/core/runtime/bearings.js +6 -6
  226. package/dist/core/runtime/broker-inventory.js +1 -1
  227. package/dist/core/runtime/broker-request.js +1 -1
  228. package/dist/core/runtime/broker.js +1 -1
  229. package/dist/core/runtime/close.d.ts +3 -3
  230. package/dist/core/runtime/close.js +1 -1
  231. package/dist/core/runtime/deliver-live.js +1 -1
  232. package/dist/core/runtime/fleet.d.ts +2 -2
  233. package/dist/core/runtime/host.d.ts +3 -3
  234. package/dist/core/runtime/host.js +3 -3
  235. package/dist/core/runtime/kickoff.d.ts +12 -12
  236. package/dist/core/runtime/kickoff.js +17 -17
  237. package/dist/core/runtime/launch-target.d.ts +1 -1
  238. package/dist/core/runtime/launch-target.js +1 -1
  239. package/dist/core/runtime/ledger.d.ts +3 -3
  240. package/dist/core/runtime/ledger.js +3 -3
  241. package/dist/core/runtime/lifecycle.d.ts +1 -1
  242. package/dist/core/runtime/lifecycle.js +2 -2
  243. package/dist/core/runtime/memory-admission.js +1 -1
  244. package/dist/core/runtime/model-swap.d.ts +2 -2
  245. package/dist/core/runtime/model-swap.js +1 -1
  246. package/dist/core/runtime/node-read.d.ts +1 -1
  247. package/dist/core/runtime/node-read.js +2 -2
  248. package/dist/core/runtime/nodes.d.ts +6 -6
  249. package/dist/core/runtime/nodes.js +1 -1
  250. package/dist/core/runtime/outcome-document.d.ts +1 -1
  251. package/dist/core/runtime/outcome-document.js +1 -1
  252. package/dist/core/runtime/persona.d.ts +3 -3
  253. package/dist/core/runtime/persona.js +2 -2
  254. package/dist/core/runtime/placement.d.ts +11 -11
  255. package/dist/core/runtime/placement.js +1 -1
  256. package/dist/core/runtime/promote.d.ts +3 -3
  257. package/dist/core/runtime/promote.js +1 -1
  258. package/dist/core/runtime/recycle.js +1 -1
  259. package/dist/core/runtime/reopen.d.ts +21 -10
  260. package/dist/core/runtime/reopen.js +1 -1
  261. package/dist/core/runtime/reset.d.ts +4 -4
  262. package/dist/core/runtime/reset.js +1 -1
  263. package/dist/core/runtime/revive-all.d.ts +2 -2
  264. package/dist/core/runtime/revive-all.js +1 -1
  265. package/dist/core/runtime/revive.d.ts +4 -4
  266. package/dist/core/runtime/revive.js +2 -2
  267. package/dist/core/runtime/roadmap.d.ts +6 -6
  268. package/dist/core/runtime/roadmap.js +5 -5
  269. package/dist/core/runtime/session-branch.d.ts +1 -1
  270. package/dist/core/runtime/session-branch.js +1 -1
  271. package/dist/core/runtime/session-list-cache.js +1 -1
  272. package/dist/core/runtime/situational-live.js +1 -1
  273. package/dist/core/runtime/spawn.d.ts +2 -2
  274. package/dist/core/runtime/spawn.js +2 -2
  275. package/dist/core/runtime/stop-guard.d.ts +2 -2
  276. package/dist/core/runtime/stop-guard.js +3 -3
  277. package/dist/core/runtime/warm-pool.d.ts +2 -2
  278. package/dist/core/runtime/warm-pool.js +1 -1
  279. package/dist/core/spaces/mounts.d.ts +2 -2
  280. package/dist/core/spaces/mounts.js +1 -1
  281. package/dist/core/spaces/permissions.d.ts +1 -1
  282. package/dist/core/spaces/permissions.js +1 -1
  283. package/dist/core/spaces/process.d.ts +1 -1
  284. package/dist/core/spaces/process.js +1 -1
  285. package/dist/core/spaces/space.js +1 -1
  286. package/dist/core/spaces/stop.d.ts +3 -3
  287. package/dist/core/spaces/stop.js +2 -2
  288. package/dist/core/spaces/users.d.ts +6 -6
  289. package/dist/core/spaces/users.js +1 -1
  290. package/dist/core/storage/attachments.d.ts +2 -2
  291. package/dist/core/storage/attachments.js +1 -1
  292. package/dist/core/storage/shares.d.ts +2 -2
  293. package/dist/core/storage/shares.js +1 -1
  294. package/dist/core/storage/tables.d.ts +21 -21
  295. package/dist/core/storage/tables.js +3 -3
  296. package/dist/core/substrate/delivery/corpus.d.ts +5 -8
  297. package/dist/core/substrate/delivery/corpus.js +3 -3
  298. package/dist/core/substrate/delivery/deliver.d.ts +10 -15
  299. package/dist/core/substrate/delivery/deliver.js +3 -3
  300. package/dist/core/substrate/delivery/plan.d.ts +2 -12
  301. package/dist/core/substrate/delivery/plan.js +3 -3
  302. package/dist/core/substrate/delivery/render-boot.d.ts +4 -4
  303. package/dist/core/substrate/delivery/render-boot.js +18 -18
  304. package/dist/core/substrate/delivery/render-event.d.ts +7 -14
  305. package/dist/core/substrate/delivery/render-event.js +4 -4
  306. package/dist/core/substrate/subject.d.ts +2 -2
  307. package/dist/core/substrate/subject.js +1 -1
  308. package/dist/core/usage/ledger.d.ts +6 -6
  309. package/dist/core/usage/ledger.js +4 -4
  310. package/dist/core/worktree-close.js +4 -4
  311. package/dist/core/worktree-mutation-async.js +7 -7
  312. package/dist/core/worktree-quarantine.js +1 -1
  313. package/dist/core/worktree-sweep.d.ts +1 -1
  314. package/dist/core/worktree-sweep.js +6 -6
  315. package/dist/core/worktree.d.ts +5 -5
  316. package/dist/core/worktree.js +13 -13
  317. package/dist/daemon/analytics/compute.d.ts +2 -2
  318. package/dist/daemon/analytics/compute.js +1 -1
  319. package/dist/daemon/api/app-listener.d.ts +4 -4
  320. package/dist/daemon/api/app-listener.js +13 -13
  321. package/dist/daemon/api/bridge.js +5 -5
  322. package/dist/daemon/api/document-listener.js +6 -6
  323. package/dist/daemon/api/handlers/analytics.js +1 -1
  324. package/dist/daemon/api/handlers/attach.js +1 -1
  325. package/dist/daemon/api/handlers/bash-jobs.js +1 -1
  326. package/dist/daemon/api/handlers/bash.js +1 -1
  327. package/dist/daemon/api/handlers/broker-ops.d.ts +1 -1
  328. package/dist/daemon/api/handlers/broker-ops.js +1 -1
  329. package/dist/daemon/api/handlers/broker-recovery.d.ts +1 -1
  330. package/dist/daemon/api/handlers/broker-recovery.js +1 -1
  331. package/dist/daemon/api/handlers/broker-signals.d.ts +2 -2
  332. package/dist/daemon/api/handlers/broker-signals.js +2 -2
  333. package/dist/daemon/api/handlers/canvas.d.ts +1 -1
  334. package/dist/daemon/api/handlers/canvas.js +4 -4
  335. package/dist/daemon/api/handlers/chat-inventory.js +1 -1
  336. package/dist/daemon/api/handlers/crons.js +1 -1
  337. package/dist/daemon/api/handlers/custom-objects.d.ts +4 -4
  338. package/dist/daemon/api/handlers/custom-objects.js +3 -3
  339. package/dist/daemon/api/handlers/delivery-retry.js +1 -1
  340. package/dist/daemon/api/handlers/delivery.js +1 -1
  341. package/dist/daemon/api/handlers/docs.d.ts +4 -4
  342. package/dist/daemon/api/handlers/docs.js +1 -1
  343. package/dist/daemon/api/handlers/feedback-comments.js +3 -3
  344. package/dist/daemon/api/handlers/files.js +1 -1
  345. package/dist/daemon/api/handlers/focus.js +1 -1
  346. package/dist/daemon/api/handlers/health.js +3 -3
  347. package/dist/daemon/api/handlers/hook-exec.js +1 -1
  348. package/dist/daemon/api/handlers/human-requests.js +1 -1
  349. package/dist/daemon/api/handlers/inbox-page.d.ts +1 -1
  350. package/dist/daemon/api/handlers/inbox-page.js +1 -1
  351. package/dist/daemon/api/handlers/inbox.d.ts +1 -1
  352. package/dist/daemon/api/handlers/inbox.js +1 -1
  353. package/dist/daemon/api/handlers/llm.d.ts +1 -1
  354. package/dist/daemon/api/handlers/llm.js +3 -3
  355. package/dist/daemon/api/handlers/memory-reads.js +1 -1
  356. package/dist/daemon/api/handlers/memory.d.ts +5 -5
  357. package/dist/daemon/api/handlers/memory.js +5 -5
  358. package/dist/daemon/api/handlers/messages.js +2 -2
  359. package/dist/daemon/api/handlers/node-events.d.ts +2 -2
  360. package/dist/daemon/api/handlers/node-events.js +3 -3
  361. package/dist/daemon/api/handlers/node-outcomes.js +1 -1
  362. package/dist/daemon/api/handlers/node-records.js +2 -2
  363. package/dist/daemon/api/handlers/nodes.d.ts +1 -1
  364. package/dist/daemon/api/handlers/nodes.js +1 -1
  365. package/dist/daemon/api/handlers/objects.js +3 -3
  366. package/dist/daemon/api/handlers/package-docs.js +1 -1
  367. package/dist/daemon/api/handlers/plugin-app-token.d.ts +1 -1
  368. package/dist/daemon/api/handlers/plugin-app-token.js +1 -1
  369. package/dist/daemon/api/handlers/profiles.d.ts +3 -3
  370. package/dist/daemon/api/handlers/profiles.js +1 -1
  371. package/dist/daemon/api/handlers/providers.d.ts +1 -1
  372. package/dist/daemon/api/handlers/providers.js +1 -1
  373. package/dist/daemon/api/handlers/questions.js +1 -1
  374. package/dist/daemon/api/handlers/reports.d.ts +1 -1
  375. package/dist/daemon/api/handlers/reports.js +5 -5
  376. package/dist/daemon/api/handlers/review-comments.js +1 -1
  377. package/dist/daemon/api/handlers/reviews.js +1 -1
  378. package/dist/daemon/api/handlers/runs.js +1 -1
  379. package/dist/daemon/api/handlers/structured-requests.js +1 -1
  380. package/dist/daemon/api/handlers/subscriptions.js +1 -1
  381. package/dist/daemon/api/handlers/transfer.js +1 -1
  382. package/dist/daemon/api/map.d.ts +3 -3
  383. package/dist/daemon/api/map.js +1 -1
  384. package/dist/daemon/api/principal.d.ts +1 -1
  385. package/dist/daemon/api/principal.js +1 -1
  386. package/dist/daemon/api/reader.d.ts +5 -5
  387. package/dist/daemon/api/reader.js +1 -1
  388. package/dist/daemon/api/router.d.ts +5 -5
  389. package/dist/daemon/api/router.js +1 -1
  390. package/dist/daemon/api/server.js +1 -1
  391. package/dist/daemon/broker-signals/bus.d.ts +1 -1
  392. package/dist/daemon/broker-signals/bus.js +1 -1
  393. package/dist/daemon/companion-retire.js +1 -1
  394. package/dist/daemon/cron/armed-context.d.ts +2 -2
  395. package/dist/daemon/cron/armed-context.js +1 -1
  396. package/dist/daemon/cron/authority.d.ts +2 -2
  397. package/dist/daemon/cron/authority.js +1 -1
  398. package/dist/daemon/cron/disposition.js +1 -1
  399. package/dist/daemon/cron/ended.d.ts +1 -1
  400. package/dist/daemon/cron/ended.js +2 -2
  401. package/dist/daemon/cron/escalation.js +3 -3
  402. package/dist/daemon/cron/folders.d.ts +1 -1
  403. package/dist/daemon/cron/folders.js +1 -1
  404. package/dist/daemon/cron/held.d.ts +1 -1
  405. package/dist/daemon/cron/held.js +1 -1
  406. package/dist/daemon/cron/lease-recovery.d.ts +1 -1
  407. package/dist/daemon/cron/lease-recovery.js +1 -1
  408. package/dist/daemon/cron/passes.d.ts +2 -2
  409. package/dist/daemon/cron/passes.js +1 -1
  410. package/dist/daemon/cron/run-socket.d.ts +1 -1
  411. package/dist/daemon/cron/run-socket.js +1 -1
  412. package/dist/daemon/cron/settle.js +1 -1
  413. package/dist/daemon/cron/sinks.d.ts +1 -1
  414. package/dist/daemon/cron/sinks.js +2 -2
  415. package/dist/daemon/cron-run.d.ts +12 -3
  416. package/dist/daemon/cron-run.js +2 -2
  417. package/dist/daemon/crtrd.js +6 -6
  418. package/dist/daemon/delivery/run-delivery.js +1 -1
  419. package/dist/daemon/due-sources.d.ts +3 -3
  420. package/dist/daemon/due-sources.js +1 -1
  421. package/dist/daemon/due.d.ts +3 -3
  422. package/dist/daemon/due.js +7 -7
  423. package/dist/daemon/fleet.d.ts +2 -2
  424. package/dist/daemon/fleet.js +11 -11
  425. package/dist/daemon/human/finish.js +3 -3
  426. package/dist/daemon/human/settle.d.ts +1 -1
  427. package/dist/daemon/human/settle.js +1 -1
  428. package/dist/daemon/human/sweep.js +1 -1
  429. package/dist/daemon/joined-owner.d.ts +3 -3
  430. package/dist/daemon/joined-owner.js +1 -1
  431. package/dist/daemon/messaging/node-message.js +1 -1
  432. package/dist/daemon/park-activity.d.ts +2 -2
  433. package/dist/daemon/park-activity.js +1 -1
  434. package/dist/daemon/peer/authority.js +1 -1
  435. package/dist/daemon/peer/forward.d.ts +6 -6
  436. package/dist/daemon/peer/forward.js +1 -1
  437. package/dist/daemon/peer/handlers.js +1 -1
  438. package/dist/daemon/peer/ingress.d.ts +4 -4
  439. package/dist/daemon/peer/ingress.js +1 -1
  440. package/dist/daemon/peer/outbox.d.ts +2 -2
  441. package/dist/daemon/peer/outbox.js +1 -1
  442. package/dist/daemon/peer/relay-service.js +1 -1
  443. package/dist/daemon/plugin-objects/read-leaf.d.ts +2 -2
  444. package/dist/daemon/plugin-objects/read-leaf.js +2 -2
  445. package/dist/daemon/profile-delete.js +1 -1
  446. package/dist/daemon/readiness.d.ts +2 -2
  447. package/dist/daemon/readiness.js +1 -1
  448. package/dist/daemon/reconcilers/action-lane.d.ts +1 -1
  449. package/dist/daemon/reconcilers/action-lane.js +1 -1
  450. package/dist/daemon/reconcilers/bash-deadline.js +2 -2
  451. package/dist/daemon/reconcilers/broker-supervision.d.ts +1 -1
  452. package/dist/daemon/reconcilers/broker-supervision.js +4 -4
  453. package/dist/daemon/reconcilers/controller-death.d.ts +1 -1
  454. package/dist/daemon/reconcilers/controller-death.js +1 -1
  455. package/dist/daemon/reconcilers/cron-lane.d.ts +1 -1
  456. package/dist/daemon/reconcilers/cron-lane.js +1 -1
  457. package/dist/daemon/reconcilers/delivery-lane.d.ts +1 -1
  458. package/dist/daemon/reconcilers/delivery-lane.js +2 -2
  459. package/dist/daemon/reconcilers/fault-retry-backstop.d.ts +3 -3
  460. package/dist/daemon/reconcilers/fault-retry-backstop.js +1 -1
  461. package/dist/daemon/reconcilers/grove-instance-sweep.d.ts +2 -2
  462. package/dist/daemon/reconcilers/grove-instance-sweep.js +1 -1
  463. package/dist/daemon/reconcilers/live-obligation.d.ts +6 -6
  464. package/dist/daemon/reconcilers/live-obligation.js +1 -1
  465. package/dist/daemon/reconcilers/managed-worktree-sweep.js +1 -1
  466. package/dist/daemon/reconcilers/node-deadline.d.ts +1 -1
  467. package/dist/daemon/reconcilers/node-deadline.js +1 -1
  468. package/dist/daemon/reconcilers/node-lifecycle/freeze-lane.js +1 -1
  469. package/dist/daemon/reconcilers/node-lifecycle/respawn-policy.d.ts +3 -3
  470. package/dist/daemon/reconcilers/node-lifecycle/respawn-policy.js +1 -1
  471. package/dist/daemon/reconcilers/node-lifecycle/terminating.js +1 -1
  472. package/dist/daemon/reconcilers/node-lifecycle/tick.js +1 -1
  473. package/dist/daemon/reconcilers/node-lifecycle/wants-execution.d.ts +1 -1
  474. package/dist/daemon/reconcilers/node-lifecycle/wants-execution.js +1 -1
  475. package/dist/daemon/reconcilers/pending-review-submit.d.ts +1 -1
  476. package/dist/daemon/reconcilers/pending-review-submit.js +1 -1
  477. package/dist/daemon/reconcilers/storage-due-work.js +1 -1
  478. package/dist/daemon/reconcilers/storage-maintenance.d.ts +1 -1
  479. package/dist/daemon/reconcilers/storage-maintenance.js +2 -2
  480. package/dist/daemon/reconcilers/structured-request-lane.d.ts +1 -1
  481. package/dist/daemon/reconcilers/structured-request-lane.js +1 -1
  482. package/dist/daemon/review/comment-notify.js +2 -2
  483. package/dist/daemon/review/companion.d.ts +3 -3
  484. package/dist/daemon/review/companion.js +1 -1
  485. package/dist/daemon/review/finish.js +1 -1
  486. package/dist/daemon/review/sweep.js +1 -1
  487. package/dist/daemon/run-notices.d.ts +4 -4
  488. package/dist/daemon/run-notices.js +1 -1
  489. package/dist/daemon/runs/append-section.d.ts +2 -2
  490. package/dist/daemon/runs/append-section.js +2 -2
  491. package/dist/daemon/runs/observer.d.ts +2 -2
  492. package/dist/daemon/runs/observer.js +2 -2
  493. package/dist/daemon/structured-requests/boot.d.ts +1 -1
  494. package/dist/daemon/structured-requests/boot.js +1 -1
  495. package/dist/daemon/structured-requests/effects.js +1 -1
  496. package/dist/daemon/structured-requests/sidecar.d.ts +1 -1
  497. package/dist/daemon/structured-requests/sidecar.js +1 -1
  498. package/dist/launcher/run.js +1 -1
  499. package/dist/migrations/004-canvas-documents/apply.d.ts +3 -3
  500. package/dist/migrations/004-canvas-documents/apply.js +1 -1
  501. package/dist/migrations/004-canvas-documents/index.d.ts +2 -2
  502. package/dist/migrations/004-canvas-documents/index.js +2 -2
  503. package/dist/migrations/activation.js +2 -2
  504. package/docs/plugin/bundles-and-memory.md +1 -1
  505. package/docs/plugin/commands.md +1 -1
  506. package/docs/public-api.md +11 -0
  507. package/package.json +4 -3
  508. package/packages/crouter-identity/package.json +1 -1
  509. package/runtime.lock.json +12 -12
@@ -1,10 +1,10 @@
1
- var ie=Object.defineProperty;var a=(e,t)=>ie(e,"name",{value:t,configurable:!0});import{prepared as l}from"../sqlite-statements.js";import{randomUUID as se}from"node:crypto";import{CrtrError as O,notFound as N,usage as w}from"../errors.js";import{ExitCode as D}from"../../types.js";import{canChange as j,canRead as P,missingMemoryScope as ae,missingMemoryScopeUnder as ue,ownerChain as ce}from"./access.js";import{bodyOf as le,get as me,put as B}from"./bodies.js";import{dropUnresolved as we,linksOf as de,recordActedOn as R,setLinks as K,setUnresolved as pe,unresolvedLinksCouldName as fe}from"./edges.js";import{publish as x}from"./events.js";import{resolveName as he}from"./names.js";import{createObject as Ee,getById as _e,getByRowid as p}from"./objects.js";import{liveLookups as ye,readerForNode as ve,readerForObject as Ne}from"./reader.js";import{replaceRules as G,setRulesOwner as Re}from"./rules.js";import{recordWatch as $}from"./watches.js";function y(e){return e.class==="node"?e.node:e.class==="app"?e.app:e.class==="object"?e.object:e.person}a(y,"actorOf");let ge=0;function E(e,t){const n=`graph_doc_${++ge}`;e.exec(`SAVEPOINT ${n}`);try{const r=t();return e.exec(`RELEASE ${n}`),r}catch(r){throw e.exec(`ROLLBACK TO ${n}`),e.exec(`RELEASE ${n}`),r}}a(E,"atomic");function Se(e,t){return new O("conflict",e,D.GENERAL,t)}a(Se,"conflict");function _(e){if(e.type!=="document")throw w(`${e.type} ${e.id} is not a document`)}a(_,"assertDocument");function V(e,t){const n=ce(e,t);return(n.length?n[n.length-1]:t).type}a(V,"spaceType");function I(e,t,n){if(n!=="public"&&V(e,t)==="repo")throw w(`a repo owns only public documents; ${t.name} cannot own a ${n} one`,{rule:"repo-public-only",next:"Write it as public, or give it another owner (your own documents can carry `if: {repo: <handle>}`)."})}a(I,"assertPublicInRepo");function H(e,t,n,r){if(n.trim()===""||n!==n.trim())throw w(`invalid document name ${JSON.stringify(n)}`);const o=l(e,"SELECT id FROM objects WHERE (type = 'document' OR instr(type, '.') > 0) AND owner = ? AND name = ? AND deleted_at IS NULL AND home_machine IS NULL").get(t.rowid,n);if(o&&o.id!==r?.id)throw Se(`${t.name} already has a document named ${n}`,{name:n,holder:o.id})}a(H,"assertNameFree");function C(e,t,n){if(!P(e,t,n))throw N(`no document ${n.id}`)}a(C,"readable");function Y(e){return new O("scope_missing",`missing scope ${e}`,D.GENERAL,{scope:e})}a(Y,"scopeMissing");function T(e,t,n){C(e,t,n);const r=ae(e,t,n,"rw");if(r!==null)throw Y(r);if(!j(e,t,n))throw new O("forbidden",`you cannot change ${n.name}`,D.GENERAL,{id:n.id})}a(T,"changeable");function X(e,t){const n=l(e,`SELECT p.rev_id FROM revision_parents rp JOIN revisions p ON p.rowid = rp.parent
2
- WHERE rp.child = ? ORDER BY p.rev_id`).all(t.rowid);return{rowid:t.rowid,rev_id:t.rev_id,number:t.number,body_hash:t.body_hash,author:t.author===null?null:p(e,t.author)?.id??null,rationale:t.rationale,verbatim:t.verbatim===1,created_at:t.created_at,parents:n.map(r=>r.rev_id)}}a(X,"toRevision");function U(e,t){return l(e,`SELECT * FROM revisions r WHERE r.document = ?
3
- AND NOT EXISTS (SELECT 1 FROM revision_parents p WHERE p.parent = r.rowid) ORDER BY r.number DESC, r.rev_id`).all(t.rowid).map(r=>X(e,r))}a(U,"heads");function Oe(e){return e.map(t=>t.rev_id).sort().join(",")}a(Oe,"headsKeyOf");function k(e,t){const n=l(e,"SELECT * FROM documents WHERE object = ?").get(t.rowid);if(!n)throw N(`no document record for ${t.id}`);return{summary:n.summary,heads_key:n.heads_key,revision:n.revision,why_it_exists:n.why_it_exists,unlisted:n.unlisted===1,lint_ignore:n.lint_ignore_json===null?null:JSON.parse(n.lint_ignore_json),extensions:n.extensions_json===null?null:JSON.parse(n.extensions_json),source_path:n.source_path}}a(k,"documentRecord");function L(e,t,n){const r=l(e,`INSERT INTO revisions (document, rev_id, number, body_hash, author, rationale, verbatim, created_at)
4
- VALUES (?, ?, ?, ?, ?, ?, ?, ?) RETURNING *`).get(t.rowid,n.rev_id??se(),n.number,n.body_hash,n.author?.rowid??null,n.rationale,n.verbatim?1:0,n.created_at??new Date().toISOString()),o=l(e,"INSERT INTO revision_parents (child, parent) VALUES (?, ?)");for(const i of n.parents)o.run(r.rowid,i);return r}a(L,"insertRevision");function De(e){const t=new Set;for(const n of e.matchAll(/\[\[([^[\]\n]+?)\]\]/g))t.add(n[1].trim());return[...t]}a(De,"linksIn");function q(e,t,n){const r=[],o=[];for(const i of n){const s=he(e,t,i);"object"in s?r.push({written_as:i,dst:s.object}):"deleted"in s?r.push({written_as:i,dst:s.deleted}):"remote"in s||o.push(i)}return{links:r,unresolved:o}}a(q,"resolveLinks");function z(e,t,n,r){const{links:o,unresolved:i}=q(e,t,De(r));return te(e,K(e,n,o)),pe(e,n,i),i}a(z,"setRevisionLinks");function W(e,t,n){const r=new Map;for(const{src:o,name:i}of fe(e,t.name,t.id))r.set(o,[...r.get(o)??[],i]);for(const[o,i]of r){const s=p(e,o),u=s?.owner==null?null:p(e,s.owner);if(!s||s.deleted_at||s.home_machine!==null||!u||u.deleted_at)continue;const c=u.type==="node"?ve(e,u.id,n??(()=>[]),ye(e),!0):Ne(e,s,n),m=q(e,c,i).links.filter(d=>d.dst.rowid===t.rowid);m.length!==0&&(K(e,s,[...de(e,s),...m]),we(e,s,m.map(d=>d.written_as)))}}a(W,"linkNewlyNamed");function xe(e,t,n){return t.type==="node"?t.id:l(e,`SELECT 1 FROM objects o JOIN objects d ON d.owner = o.rowid
1
+ var oe=Object.defineProperty;var s=(e,n)=>oe(e,"name",{value:n,configurable:!0});import{randomUUID as se}from"node:crypto";import{CrtrError as O,notFound as v,usage as p}from"../errors.js";import{ExitCode as D}from"../../types.js";import{canChange as L,canRead as P,missingMemoryScope as we,missingMemoryScopeUnder as ue,ownerChain as ce}from"./access.js";import{bodyOf as pe,get as le,put as B}from"./bodies.js";import{dropUnresolved as me,linksOf as de,recordActedOn as N,setLinks as G,setUnresolved as fe,unresolvedLinksCouldName as ye}from"./edges.js";import{publish as k}from"./events.js";import{resolveName as he}from"./names.js";import{createObject as Ee,getById as _e,getByRowid as m}from"./objects.js";import{liveLookups as ve,readerForNode as Ne,readerForObject as Re}from"./reader.js";import{replaceRules as K,setRulesOwner as ge}from"./rules.js";import{recordWatch as I}from"./watches.js";import{withCanvasWrite as y}from"../canvas/db.js";import{filterAsync as Y,forEachAsync as Se,mapAsync as R}from"../async-array.js";function E(e){return e.class==="node"?e.node:e.class==="app"?e.app:e.class==="object"?e.object:e.person}s(E,"actorOf");function Oe(e,n){return new O("conflict",e,D.GENERAL,n)}s(Oe,"conflict");function h(e){if(e.type!=="document")throw p(`${e.type} ${e.id} is not a document`)}s(h,"assertDocument");async function V(e,n){const t=await ce(e,n);return(t.length?t[t.length-1]:n).type}s(V,"spaceType");async function $(e,n,t){if(t!=="public"&&await V(e,n)==="repo")throw p(`a repo owns only public documents; ${n.name} cannot own a ${t} one`,{rule:"repo-public-only",next:"Write it as public, or give it another owner (your own documents can carry `if: {repo: <handle>}`)."})}s($,"assertPublicInRepo");async function H(e,n,t,a){if(t.trim()===""||t!==t.trim())throw p(`invalid document name ${JSON.stringify(t)}`);const i=await e.prepare("SELECT id FROM objects WHERE (type = 'document' OR instr(type, '.') > 0) AND owner = ? AND name = ? AND deleted_at IS NULL AND home_machine IS NULL").get(n.rowid,t);if(i&&i.id!==a?.id)throw Oe(`${n.name} already has a document named ${t}`,{name:t,holder:i.id})}s(H,"assertNameFree");async function U(e,n,t){if(!await P(e,n,t))throw v(`no document ${t.id}`)}s(U,"readable");function X(e){return new O("scope_missing",`missing scope ${e}`,D.GENERAL,{scope:e})}s(X,"scopeMissing");async function x(e,n,t){await U(e,n,t);const a=await we(e,n,t,"rw");if(a!==null)throw X(a);if(!await L(e,n,t))throw new O("forbidden",`you cannot change ${t.name}`,D.GENERAL,{id:t.id})}s(x,"changeable");async function q(e,n){const t=await e.prepare(`SELECT p.rev_id FROM revision_parents rp JOIN revisions p ON p.rowid = rp.parent
2
+ WHERE rp.child = ? ORDER BY p.rev_id`).all(n.rowid);return{rowid:n.rowid,rev_id:n.rev_id,number:n.number,body_hash:n.body_hash,author:n.author===null?null:(await m(e,n.author))?.id??null,rationale:n.rationale,verbatim:n.verbatim===1,created_at:n.created_at,parents:t.map(a=>a.rev_id)}}s(q,"toRevision");async function C(e,n){const t=await e.prepare(`SELECT * FROM revisions r WHERE r.document = ?
3
+ AND NOT EXISTS (SELECT 1 FROM revision_parents p WHERE p.parent = r.rowid) ORDER BY r.number DESC, r.rev_id`).all(n.rowid);return await R(t,async a=>await q(e,a))}s(C,"heads");function De(e){return e.map(n=>n.rev_id).sort().join(",")}s(De,"headsKeyOf");async function T(e,n){const t=await e.prepare("SELECT * FROM documents WHERE object = ?").get(n.rowid);if(!t)throw v(`no document record for ${n.id}`);return{summary:t.summary,heads_key:t.heads_key,revision:t.revision,why_it_exists:t.why_it_exists,unlisted:t.unlisted===1,lint_ignore:t.lint_ignore_json===null?null:JSON.parse(t.lint_ignore_json),extensions:t.extensions_json===null?null:JSON.parse(t.extensions_json),source_path:t.source_path}}s(T,"documentRecord");async function j(e,n,t){const a=await e.prepare(`INSERT INTO revisions (document, rev_id, number, body_hash, author, rationale, verbatim, created_at)
4
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?) RETURNING *`).get(n.rowid,t.rev_id??se(),t.number,t.body_hash,t.author?.rowid??null,t.rationale,t.verbatim?1:0,t.created_at??new Date().toISOString()),i=e.prepare("INSERT INTO revision_parents (child, parent) VALUES (?, ?)");for(const r of t.parents)await i.run(a.rowid,r);return a}s(j,"insertRevision");function ke(e){const n=new Set;for(const t of e.matchAll(/\[\[([^[\]\n]+?)\]\]/g))n.add(t[1].trim());return[...n]}s(ke,"linksIn");async function z(e,n,t){const a=[],i=[];for(const r of t){const o=await he(e,n,r);"object"in o?a.push({written_as:r,dst:o.object}):"deleted"in o?a.push({written_as:r,dst:o.deleted}):"remote"in o||i.push(r)}return{links:a,unresolved:i}}s(z,"resolveLinks");async function Q(e,n,t,a){const{links:i,unresolved:r}=await z(e,n,ke(a));return await ae(e,await G(e,t,i)),await fe(e,t,r),r}s(Q,"setRevisionLinks");async function W(e,n,t){const a=new Map;for(const{src:i,name:r}of await ye(e,n.name,n.id))a.set(i,[...a.get(i)??[],r]);for(const[i,r]of a){const o=await m(e,i),w=o?.owner==null?null:await m(e,o.owner);if(!o||o.deleted_at||o.home_machine!==null||!w||w.deleted_at)continue;const u=w.type==="node"?await Ne(e,w.id,t??(async()=>[]),ve(e),!0):await Re(e,o,t),c=(await z(e,u,r)).links.filter(l=>l.dst.rowid===n.rowid);c.length!==0&&(await G(e,o,[...await de(e,o),...c]),await me(e,o,c.map(l=>l.written_as)))}}s(W,"linkNewlyNamed");async function xe(e,n,t){return n.type==="node"?n.id:await e.prepare(`SELECT 1 FROM objects o JOIN objects d ON d.owner = o.rowid
5
5
  WHERE o.name = ? AND o.type <> ? AND o.type IN ('person','app','repo','profile')
6
- AND d.type = 'document' AND d.name = ? AND d.deleted_at IS NULL LIMIT 1`).get(t.name,t.type,n)?`${t.type}:${t.name}`:t.name}a(xe,"ownerPrefix");function Q(e,t,n){const r=l(e,`SELECT e.written_as, o.* FROM edges e JOIN objects o ON o.rowid = e.dst
7
- WHERE e.type = 'links-to' AND e.src = ? AND e.written_as IS NOT NULL`).all(t.rowid);if(r.length===0)return n;const o=new Map;for(const i of r){if(i.deleted_at||i.written_as===i.id)continue;const s=!i.written_as.includes("/");if(s&&i.name===i.written_as)continue;const u=i.owner===null?null:p(e,i.owner),c=u?`${xe(e,u,i.name)}/${i.name}`:i.name,m=s&&i.owner===t.owner?i.name:c;m!==i.written_as&&o.set(i.written_as,m)}return o.size===0?n:n.replace(/\[\[([^[\]\n]+?)\]\]/g,(i,s)=>{const u=o.get(s.trim());return u===void 0?i:`[[${u}]]`})}a(Q,"withCurrentNames");function M(e,t,n){if(n.preview!==void 0){if(n.preview.trim()==="")throw w("a document needs a preview",{field:"preview"});l(e,"UPDATE objects SET preview = ? WHERE rowid = ?").run(n.preview,t.rowid)}n.privacy!==void 0&&(I(e,p(e,t.owner),n.privacy),l(e,"UPDATE objects SET privacy = ? WHERE rowid = ?").run(n.privacy,t.rowid));const r=a((i,s)=>e.prepare(`UPDATE documents SET ${i} = ? WHERE object = ?`).run(s,t.rowid),"set");n.summary!==void 0&&r("summary",n.summary),n.whyItExists!==void 0&&r("why_it_exists",n.whyItExists),n.unlisted!==void 0&&r("unlisted",n.unlisted?1:0),n.lintIgnore!==void 0&&r("lint_ignore_json",n.lintIgnore===null?null:JSON.stringify(n.lintIgnore)),n.extensions!==void 0&&r("extensions_json",n.extensions===null?null:JSON.stringify(n.extensions));const o=p(e,t.rowid);return n.rules!==void 0&&G(e,o,n.rules),o}a(M,"applyDocumentFields");function Z(e,t,n){if(t.owner.deleted_at)throw w(`${t.owner.name} is deleted`);if(t.preview.trim()==="")throw w("a document needs a preview",{field:"preview"});I(e,t.owner,t.privacy),H(e,t.owner,t.name);const r=Ee(e,{...t.id?{id:t.id}:{},type:"document",kind:t.kind,owner:t.owner.rowid,privacy:t.privacy,name:t.name,preview:t.preview});l(e,"INSERT INTO documents (object, heads_key, revision) VALUES (?, '', 0)").run(r.rowid);const o=M(e,r,{...t,preview:void 0,privacy:void 0,rules:t.rules??[]});return W(e,o,n),o}a(Z,"createDocument");function F(e,t){const n=U(e,t),r=Oe(n),o=Math.max(0,...n.map(i=>i.number));return l(e,"UPDATE documents SET heads_key = ?, revision = ? WHERE object = ?").run(r,o,t.rowid),{heads_key:r,revision:o,headCount:n.length}}a(F,"setHeads");function Ke(e,t,n,r,o){const i=B(r);return E(e,()=>{const s=y(t),u=ue(e,t,n.owner,"rw");if(u!==null)throw Y(u);const c=Z(e,n,o),m=L(e,c,{number:1,body_hash:i,author:s,rationale:null,parents:[]}),{heads_key:d}=F(e,c);if(!j(e,t,c))throw N(`no owner ${n.owner.name} you can write to`);const f=z(e,t,c,r);return R(e,s,c),$(e,s,c,"write",{readHeadsKey:d}),x(e,{event:"created",object:c,actor:s,attrs:{revision:1},pointer:m.rev_id},o),{object:c,revision:1,unresolved:f}})}a(Ke,"writeDocument");function Ge(e,t,n){return l(e,"SELECT read_heads_key FROM watches WHERE watcher = ? AND object = ?").get(y(t).rowid,n.rowid)?.read_heads_key??null}a(Ge,"readBase");function Te(e,t){let n=e;for(const[r,{old:o,new:i}]of t.entries()){if(o==="")throw w(`block ${r+1}: a replacement needs non-empty old text`,{field:"replace"});const s=n.indexOf(o);if(s<0)throw w(`block ${r+1}: old text not found: ${JSON.stringify(o.slice(0,120))}`,{field:"replace",old:o});if(n.indexOf(o,s+1)>=0)throw w(`block ${r+1}: old text occurs more than once: ${JSON.stringify(o.slice(0,120))}`,{field:"replace",old:o});n=n.slice(0,s)+i+n.slice(s+o.length)}return n}a(Te,"applyReplacements");function Ve(e,t,n,r,o,i,s={},u){if(_(n),T(e,t,n),n.deleted_at)throw w(`${n.name} is deleted`);if(i===null)throw new O("read_first",`read ${n.name} before editing it`,D.GENERAL,{id:n.id});if(o.trim()==="")throw w("an edit needs a rationale",{field:"rationale"});const c=k(e,n);if(c.heads_key!==i)return{stale:{heads_key:c.heads_key,revision:c.revision}};const m=U(e,n);let d;if("body"in r)d=r.body;else{if(m.length!==1)throw w(`${n.name} has ${m.length} heads and needs a merge; pass the whole merged body`,{heads:m.length});d=Te(Q(e,n,me(m[0].body_hash)),r.replace)}const f=B(d);try{return E(e,()=>{const h=y(t),g=1+Math.max(0,...m.map(v=>v.number)),J=L(e,n,{number:g,body_hash:f,author:h,rationale:o,verbatim:r.verbatim===!0,parents:m.map(v=>v.rowid)}),A=J.rev_id,re=l(e,"UPDATE documents SET heads_key = ?, revision = ? WHERE object = ? AND heads_key = ?").run(A,g,n.rowid,i);if(Number(re.changes)===0){const v=k(e,n);throw new b(v.heads_key,v.revision)}const S=M(e,n,s),oe=z(e,t,S,d);return R(e,h,S),$(e,h,S,"write",{readHeadsKey:A}),x(e,{event:"edited",object:S,actor:h,pointer:J.rev_id,attrs:{revision:g,from_revision:c.revision,rationale:o}},u),{revision:g,heads_key:A,unresolved:oe}})}catch(h){if(h instanceof b)return{stale:{heads_key:h.heads_key,revision:h.revision}};throw h}}a(Ve,"editDocument");class b extends Error{static{a(this,"StaleEdit")}heads_key;revision;constructor(t,n){super("stale"),this.heads_key=t,this.revision=n}}function Ye(e,t,n,r){return _(n),t&&T(e,t,n),E(e,()=>{const o=M(e,n,r);return t&&R(e,y(t),o),o})}a(Ye,"setDocumentRecord");function ke(e,t,n,r){const o=y(t),{heads_key:i}=k(e,n);$(e,o,n,"read",{readHeadsKey:i}),x(e,{event:"read",object:n,actor:o,attrs:{}},r)}a(ke,"recordRead");function Xe(e,t,n,r){return _(n),C(e,t,n),E(e,()=>{const o=k(e,n),i=U(e,n).map(u=>({...u,body:Q(e,n,le(u.body_hash,o.source_path))})),s=l(e,"SELECT dst, written_as FROM edges WHERE type = 'links-to' AND src = ? ORDER BY written_as").all(n.rowid).map(u=>({written_as:u.written_as??"",object:p(e,u.dst)})).filter(u=>u.object&&P(e,t,u.object)).map(u=>({...u,deleted:u.object.deleted_at!==null}));return n.deleted_at||ke(e,t,n,r),{object:n,record:o,heads:i,needsMerge:i.length>1,links:s}})}a(Xe,"readDocument");function qe(e,t,n){return _(n),C(e,t,n),l(e,"SELECT * FROM revisions WHERE document = ? ORDER BY number DESC, created_at DESC, rowid DESC").all(n.rowid).map(o=>X(e,o))}a(qe,"history");function ze(e,t,n,r,o){if(_(n),n.deleted_at)throw w(`${n.name} is deleted`);return t&&T(e,t,n),E(e,()=>{const i=r.owner??p(e,n.owner),s=r.name??n.name;H(e,i,s,n),I(e,i,n.privacy),l(e,"UPDATE objects SET name = ?, owner = ? WHERE rowid = ?").run(s,i.rowid,n.rowid);const u=p(e,n.rowid);if(i.rowid!==n.owner&&(Re(e,u),t&&!j(e,t,u)))throw N(`no owner ${i.name} you can move documents to`);return t&&R(e,y(t),u),(s!==n.name||i.rowid!==n.owner)&&W(e,u,o),u})}a(ze,"moveDocument");function Qe(e,t,n,r,o){return _(n),n.deleted_at?n:(t&&T(e,t,n),E(e,()=>{const i=ee(e,t,n,r,o);return te(e,ne(e,n.rowid),r),i}))}a(Qe,"deleteDocument");function Ze(e,t,n,r){return _(t),t.deleted_at?E(e,()=>{H(e,p(e,t.owner),n,t),l(e,"UPDATE objects SET deleted_at = NULL, name = ? WHERE rowid = ?").run(n,t.rowid);const o=p(e,t.rowid);return W(e,o,r),o}):t}a(Ze,"restoreDocument");function ee(e,t,n,r,o){l(e,"UPDATE objects SET deleted_at = ? WHERE rowid = ?").run(o??new Date().toISOString(),n.rowid);const i=p(e,n.rowid),s=t?y(t):null;return s&&R(e,s,i),x(e,{event:"deleted",object:i,actor:s,attrs:{}},r),l(e,"DELETE FROM watches WHERE object = ?").run(n.rowid),G(e,i,[]),i}a(ee,"markDeleted");function ne(e,t){return l(e,"SELECT dst FROM edges WHERE type = 'links-to' AND src = ?").all(t).map(({dst:n})=>n)}a(ne,"linkTargets");function te(e,t,n){const r=l(e,`SELECT 1 FROM objects d JOIN objects w ON w.rowid = d.owner
6
+ AND d.type = 'document' AND d.name = ? AND d.deleted_at IS NULL LIMIT 1`).get(n.name,n.type,t)?`${n.type}:${n.name}`:n.name}s(xe,"ownerPrefix");async function Z(e,n,t){const a=await e.prepare(`SELECT e.written_as, o.* FROM edges e JOIN objects o ON o.rowid = e.dst
7
+ WHERE e.type = 'links-to' AND e.src = ? AND e.written_as IS NOT NULL`).all(n.rowid);if(a.length===0)return t;const i=new Map;for(const r of a){if(r.deleted_at||r.written_as===r.id)continue;const o=!r.written_as.includes("/");if(o&&r.name===r.written_as)continue;const w=r.owner===null?null:await m(e,r.owner),u=w?`${await xe(e,w,r.name)}/${r.name}`:r.name,c=o&&r.owner===n.owner?r.name:u;c!==r.written_as&&i.set(r.written_as,c)}return i.size===0?t:t.replace(/\[\[([^[\]\n]+?)\]\]/g,(r,o)=>{const w=i.get(o.trim());return w===void 0?r:`[[${w}]]`})}s(Z,"withCurrentNames");async function M(e,n,t){if(t.preview!==void 0){if(t.preview.trim()==="")throw p("a document needs a preview",{field:"preview"});await e.prepare("UPDATE objects SET preview = ? WHERE rowid = ?").run(t.preview,n.rowid)}t.privacy!==void 0&&(await $(e,await m(e,n.owner),t.privacy),await e.prepare("UPDATE objects SET privacy = ? WHERE rowid = ?").run(t.privacy,n.rowid));const a=s(async(r,o)=>await e.prepareUncached(`UPDATE documents SET ${r} = ? WHERE object = ?`).run(o,n.rowid),"set");t.summary!==void 0&&await a("summary",t.summary),t.whyItExists!==void 0&&await a("why_it_exists",t.whyItExists),t.unlisted!==void 0&&await a("unlisted",t.unlisted?1:0),t.lintIgnore!==void 0&&await a("lint_ignore_json",t.lintIgnore===null?null:JSON.stringify(t.lintIgnore)),t.extensions!==void 0&&await a("extensions_json",t.extensions===null?null:JSON.stringify(t.extensions));const i=await m(e,n.rowid);return t.rules!==void 0&&await K(e,i,t.rules),i}s(M,"applyDocumentFields");async function b(e,n,t){if(n.owner.deleted_at)throw p(`${n.owner.name} is deleted`);if(n.preview.trim()==="")throw p("a document needs a preview",{field:"preview"});await $(e,n.owner,n.privacy),await H(e,n.owner,n.name);const a=await Ee(e,{...n.id?{id:n.id}:{},type:"document",kind:n.kind,owner:n.owner.rowid,privacy:n.privacy,name:n.name,preview:n.preview});await e.prepare("INSERT INTO documents (object, heads_key, revision) VALUES (?, '', 0)").run(a.rowid);const i=await M(e,a,{...n,preview:void 0,privacy:void 0,rules:n.rules??[]});return await W(e,i,t),i}s(b,"createDocument");async function F(e,n){const t=await C(e,n),a=De(t),i=Math.max(0,...t.map(r=>r.number));return await e.prepare("UPDATE documents SET heads_key = ?, revision = ? WHERE object = ?").run(a,i,n.rowid),{heads_key:a,revision:i,headCount:t.length}}s(F,"setHeads");async function Ye(e,n,t,a,i){const r=B(a);return await y(async()=>{const o=E(n),w=await ue(e,n,t.owner,"rw");if(w!==null)throw X(w);const u=await b(e,t,i),c=await j(e,u,{number:1,body_hash:r,author:o,rationale:null,parents:[]}),{heads_key:l}=await F(e,u);if(!await L(e,n,u))throw v(`no owner ${t.owner.name} you can write to`);const d=await Q(e,n,u,a);return await N(e,o,u),await I(e,o,u,"write",{readHeadsKey:l}),await k(e,{event:"created",object:u,actor:o,attrs:{revision:1},pointer:c.rev_id},i),{object:u,revision:1,unresolved:d}},{savepoint:!0})}s(Ye,"writeDocument");async function Ve(e,n,t){return(await e.prepare("SELECT read_heads_key FROM watches WHERE watcher = ? AND object = ?").get(E(n).rowid,t.rowid))?.read_heads_key??null}s(Ve,"readBase");function Te(e,n){let t=e;for(const[a,{old:i,new:r}]of n.entries()){if(i==="")throw p(`block ${a+1}: a replacement needs non-empty old text`,{field:"replace"});const o=t.indexOf(i);if(o<0)throw p(`block ${a+1}: old text not found: ${JSON.stringify(i.slice(0,120))}`,{field:"replace",old:i});if(t.indexOf(i,o+1)>=0)throw p(`block ${a+1}: old text occurs more than once: ${JSON.stringify(i.slice(0,120))}`,{field:"replace",old:i});t=t.slice(0,o)+r+t.slice(o+i.length)}return t}s(Te,"applyReplacements");async function Xe(e,n,t,a,i,r,o={},w){if(h(t),await x(e,n,t),t.deleted_at)throw p(`${t.name} is deleted`);if(r===null)throw new O("read_first",`read ${t.name} before editing it`,D.GENERAL,{id:t.id});if(i.trim()==="")throw p("an edit needs a rationale",{field:"rationale"});const u=await T(e,t);if(u.heads_key!==r)return{stale:{heads_key:u.heads_key,revision:u.revision}};const c=await C(e,t);let l;if("body"in a)l=a.body;else{if(c.length!==1)throw p(`${t.name} has ${c.length} heads and needs a merge; pass the whole merged body`,{heads:c.length});l=Te(await Z(e,t,le(c[0].body_hash)),a.replace)}const d=B(l);try{return await y(async()=>{const f=E(n),g=1+Math.max(0,...c.map(_=>_.number)),J=await j(e,t,{number:g,body_hash:d,author:f,rationale:i,verbatim:a.verbatim===!0,parents:c.map(_=>_.rowid)}),A=J.rev_id,ie=await e.prepare("UPDATE documents SET heads_key = ?, revision = ? WHERE object = ? AND heads_key = ?").run(A,g,t.rowid,r);if(Number(ie.changes)===0){const _=await T(e,t);throw new ee(_.heads_key,_.revision)}const S=await M(e,t,o),re=await Q(e,n,S,l);return await N(e,f,S),await I(e,f,S,"write",{readHeadsKey:A}),await k(e,{event:"edited",object:S,actor:f,pointer:J.rev_id,attrs:{revision:g,from_revision:u.revision,rationale:i}},w),{revision:g,heads_key:A,unresolved:re}},{savepoint:!0})}catch(f){if(f instanceof ee)return{stale:{heads_key:f.heads_key,revision:f.revision}};throw f}}s(Xe,"editDocument");class ee extends Error{static{s(this,"StaleEdit")}heads_key;revision;constructor(n,t){super("stale"),this.heads_key=n,this.revision=t}}async function qe(e,n,t,a){return h(t),n&&await x(e,n,t),await y(async()=>{const i=await M(e,t,a);return n&&await N(e,E(n),i),i},{savepoint:!0})}s(qe,"setDocumentRecord");async function je(e,n,t,a){const i=E(n),{heads_key:r}=await T(e,t);await I(e,i,t,"read",{readHeadsKey:r}),await k(e,{event:"read",object:t,actor:i,attrs:{}},a)}s(je,"recordRead");async function ze(e,n,t,a){return h(t),await U(e,n,t),await y(async()=>{const i=await T(e,t),r=await R(await C(e,t),async w=>({...w,body:await Z(e,t,pe(w.body_hash,i.source_path))})),o=(await Y(await R(await e.prepare("SELECT dst, written_as FROM edges WHERE type = 'links-to' AND src = ? ORDER BY written_as").all(t.rowid),async w=>({written_as:w.written_as??"",object:await m(e,w.dst)})),async w=>w.object&&await P(e,n,w.object))).map(w=>({...w,deleted:w.object.deleted_at!==null}));return t.deleted_at||await je(e,n,t,a),{object:t,record:i,heads:r,needsMerge:r.length>1,links:o}},{savepoint:!0})}s(ze,"readDocument");async function Qe(e,n,t){h(t),await U(e,n,t);const a=await e.prepare("SELECT * FROM revisions WHERE document = ? ORDER BY number DESC, created_at DESC, rowid DESC").all(t.rowid);return await R(a,async i=>await q(e,i))}s(Qe,"history");async function Ze(e,n,t,a,i){if(h(t),t.deleted_at)throw p(`${t.name} is deleted`);return n&&await x(e,n,t),await y(async()=>{const r=a.owner??await m(e,t.owner),o=a.name??t.name;await H(e,r,o,t),await $(e,r,t.privacy),await e.prepare("UPDATE objects SET name = ?, owner = ? WHERE rowid = ?").run(o,r.rowid,t.rowid);const w=await m(e,t.rowid);if(r.rowid!==t.owner&&(await ge(e,w),n&&!await L(e,n,w)))throw v(`no owner ${r.name} you can move documents to`);return n&&await N(e,E(n),w),(o!==t.name||r.rowid!==t.owner)&&await W(e,w,i),w},{savepoint:!0})}s(Ze,"moveDocument");async function be(e,n,t,a,i){return h(t),t.deleted_at?t:(n&&await x(e,n,t),await y(async()=>{const r=await te(e,n,t,a,i);return await ae(e,await ne(e,t.rowid),a),r},{savepoint:!0}))}s(be,"deleteDocument");async function et(e,n,t,a){return h(n),n.deleted_at?await y(async()=>{await H(e,await m(e,n.owner),t,n),await e.prepare("UPDATE objects SET deleted_at = NULL, name = ? WHERE rowid = ?").run(t,n.rowid);const i=await m(e,n.rowid);return await W(e,i,a),i},{savepoint:!0}):n}s(et,"restoreDocument");async function te(e,n,t,a,i){await e.prepare("UPDATE objects SET deleted_at = ? WHERE rowid = ?").run(i??new Date().toISOString(),t.rowid);const r=await m(e,t.rowid),o=n?E(n):null;return o&&await N(e,o,r),await k(e,{event:"deleted",object:r,actor:o,attrs:{}},a),await e.prepare("DELETE FROM watches WHERE object = ?").run(t.rowid),await K(e,r,[]),r}s(te,"markDeleted");async function ne(e,n){return(await e.prepare("SELECT dst FROM edges WHERE type = 'links-to' AND src = ?").all(n)).map(({dst:t})=>t)}s(ne,"linkTargets");async function ae(e,n,t){const a=e.prepare(`SELECT 1 FROM objects d JOIN objects w ON w.rowid = d.owner
8
8
  WHERE d.rowid = ? AND d.type = 'document' AND d.deleted_at IS NULL AND w.deleted_at IS NOT NULL
9
9
  AND NOT EXISTS (SELECT 1 FROM edges e JOIN objects s ON s.rowid = e.src
10
- WHERE e.type = 'links-to' AND e.dst = d.rowid AND e.src != d.rowid AND s.deleted_at IS NULL)`),o=[...t];for(;o.length>0;){const i=o.pop();r.get(i)!==void 0&&(ee(e,null,p(e,i),n),o.push(...ne(e,i)))}}a(te,"collectUnlinked");function be(e,t,n){if(t.revisions.length===0)throw w(`import of ${t.name}: no revisions`);return E(e,()=>{const r=Z(e,t,n);l(e,"UPDATE objects SET created_at = ? WHERE rowid = ?").run(t.revisions[0].created_at,r.rowid);let o=null;return t.revisions.forEach((i,s)=>{o=L(e,r,{...i,number:s+1,parents:o===null?[]:[o]}).rowid}),F(e,r),p(e,r.rowid)})}a(be,"importDocument");function en(e,t,n){if(_(t),t.privacy!=="public"&&V(e,t)==="repo")throw w(`a repo owns only public documents; refusing revisions of ${t.name}`);return E(e,()=>{const r=l(e,"SELECT rowid, number, document FROM revisions WHERE rev_id = ?");let o=n.filter(u=>!r.get(u.rev_id));for(;o.length>0;){const u=[];for(const c of o){const m=c.parents.map(f=>r.get(f));if(m.some(f=>f===void 0)){u.push(c);continue}const d=m;if(d.some(f=>f.document!==t.rowid))throw w(`revision ${c.rev_id} names a parent of another document`);L(e,t,{...c,author:null,number:1+Math.max(0,...d.map(f=>f.number)),parents:d.map(f=>f.rowid)})}if(u.length===o.length)throw w(`revisions of ${t.name} name unknown parents: ${u.map(c=>c.rev_id).join(", ")}`);o=u}const{heads_key:i,headCount:s}=F(e,t);return{heads_key:i,headCount:s}})}a(en,"insertImportedRevisions");function nn(e,t){const n=_e(e,t);if(!n||n.type!=="document")throw N(`no document ${t}`);return n}a(nn,"documentById");export{y as actorOf,M as applyDocumentFields,Te as applyReplacements,te as collectUnlinked,Qe as deleteDocument,nn as documentById,k as documentRecord,Ve as editDocument,U as heads,qe as history,be as importDocument,en as insertImportedRevisions,De as linksIn,ze as moveDocument,Ge as readBase,Xe as readDocument,ke as recordRead,Ze as restoreDocument,Ye as setDocumentRecord,z as setRevisionLinks,Q as withCurrentNames,Ke as writeDocument};
10
+ WHERE e.type = 'links-to' AND e.dst = d.rowid AND e.src != d.rowid AND s.deleted_at IS NULL)`),i=[...n];for(;i.length>0;){const r=i.pop();await a.get(r)!==void 0&&(await te(e,null,await m(e,r),t),i.push(...await ne(e,r)))}}s(ae,"collectUnlinked");async function tt(e,n,t){if(n.revisions.length===0)throw p(`import of ${n.name}: no revisions`);return await y(async()=>{const a=await b(e,n,t);await e.prepare("UPDATE objects SET created_at = ? WHERE rowid = ?").run(n.revisions[0].created_at,a.rowid);let i=null;return await Se(n.revisions,async(r,o)=>{i=(await j(e,a,{...r,number:o+1,parents:i===null?[]:[i]})).rowid}),await F(e,a),await m(e,a.rowid)},{savepoint:!0})}s(tt,"importDocument");async function nt(e,n,t){if(h(n),n.privacy!=="public"&&await V(e,n)==="repo")throw p(`a repo owns only public documents; refusing revisions of ${n.name}`);return await y(async()=>{const a=e.prepare("SELECT rowid, number, document FROM revisions WHERE rev_id = ?");let i=await Y(t,async w=>!await a.get(w.rev_id));for(;i.length>0;){const w=[];for(const u of i){const c=await R(u.parents,async d=>await a.get(d));if(c.some(d=>d===void 0)){w.push(u);continue}const l=c;if(l.some(d=>d.document!==n.rowid))throw p(`revision ${u.rev_id} names a parent of another document`);await j(e,n,{...u,author:null,number:1+Math.max(0,...l.map(d=>d.number)),parents:l.map(d=>d.rowid)})}if(w.length===i.length)throw p(`revisions of ${n.name} name unknown parents: ${w.map(u=>u.rev_id).join(", ")}`);i=w}const{heads_key:r,headCount:o}=await F(e,n);return{heads_key:r,headCount:o}},{savepoint:!0})}s(nt,"insertImportedRevisions");async function at(e,n){const t=await _e(e,n);if(!t||t.type!=="document")throw v(`no document ${n}`);return t}s(at,"documentById");export{E as actorOf,M as applyDocumentFields,Te as applyReplacements,ae as collectUnlinked,be as deleteDocument,at as documentById,T as documentRecord,Xe as editDocument,C as heads,Qe as history,tt as importDocument,nt as insertImportedRevisions,ke as linksIn,Ze as moveDocument,Ve as readBase,ze as readDocument,je as recordRead,et as restoreDocument,qe as setDocumentRecord,Q as setRevisionLinks,Z as withCurrentNames,Ye as writeDocument};
@@ -1,6 +1,6 @@
1
1
  /** `acted-on` and `links-to` edges. An edge is visible only to a reader who may read both ends. */
2
- import type { DatabaseSync } from 'node:sqlite';
3
2
  import type { ObjectRow, Reader } from './types.js';
3
+ import type { CanvasDb } from '../canvas/db.js';
4
4
  export type EdgeType = 'acted-on' | 'links-to';
5
5
  export interface Edge {
6
6
  type: EdgeType;
@@ -10,32 +10,32 @@ export interface Edge {
10
10
  created_at: string;
11
11
  }
12
12
  /** One row per actor and object however many times the actor acts. */
13
- export declare function recordActedOn(db: DatabaseSync, actor: ObjectRow, object: ObjectRow): void;
13
+ export declare function recordActedOn(db: CanvasDb, actor: ObjectRow, object: ObjectRow): Promise<void>;
14
14
  /** Replace the document's `links-to` edges with the links of its current revision. Answers the
15
15
  * rowids it no longer links to, so the caller can collect a kept document that lost its last link. */
16
- export declare function setLinks(db: DatabaseSync, doc: ObjectRow, links: ReadonlyArray<{
16
+ export declare function setLinks(db: CanvasDb, doc: ObjectRow, links: ReadonlyArray<{
17
17
  written_as: string;
18
18
  dst: ObjectRow;
19
- }>): number[];
19
+ }>): Promise<number[]>;
20
20
  /** Replace the names the document's current revision links that resolved to nothing or to several objects.
21
21
  * Kept so that when a document with such a name comes into being, the link can gain its edge. */
22
- export declare function setUnresolved(db: DatabaseSync, doc: ObjectRow, names: readonly string[]): void;
22
+ export declare function setUnresolved(db: CanvasDb, doc: ObjectRow, names: readonly string[]): Promise<void>;
23
23
  /** Forget `names` among the document's remembered unresolved links: they have gained an edge. */
24
- export declare function dropUnresolved(db: DatabaseSync, doc: ObjectRow, names: Iterable<string>): void;
24
+ export declare function dropUnresolved(db: CanvasDb, doc: ObjectRow, names: Iterable<string>): Promise<void>;
25
25
  /** The unresolved links, as `{src, name}`, whose written name is the document's id or `name`, or ends in `/<name>`: every
26
26
  * link that could name a document called `name`, bare or qualified by its owner. */
27
- export declare function unresolvedLinksCouldName(db: DatabaseSync, name: string, id: string): Array<{
27
+ export declare function unresolvedLinksCouldName(db: CanvasDb, name: string, id: string): Promise<Array<{
28
28
  src: number;
29
29
  name: string;
30
- }>;
30
+ }>>;
31
31
  /** The document's current `links-to` edges as the links they were written from. */
32
- export declare function linksOf(db: DatabaseSync, doc: ObjectRow): Array<{
32
+ export declare function linksOf(db: CanvasDb, doc: ObjectRow): Promise<Array<{
33
33
  written_as: string;
34
34
  dst: ObjectRow;
35
- }>;
35
+ }>>;
36
36
  /** Documents whose body links to `object`. */
37
- export declare function backlinks(db: DatabaseSync, reader: Reader, object: ObjectRow): Edge[];
38
- export declare function edgesOf(db: DatabaseSync, reader: Reader, object: ObjectRow, opts?: {
37
+ export declare function backlinks(db: CanvasDb, reader: Reader, object: ObjectRow): Promise<Edge[]>;
38
+ export declare function edgesOf(db: CanvasDb, reader: Reader, object: ObjectRow, opts?: {
39
39
  type?: EdgeType;
40
40
  direction?: 'out' | 'in' | 'both';
41
- }): Edge[];
41
+ }): Promise<Edge[]>;
@@ -1 +1 @@
1
- var m=Object.defineProperty;var c=(t,e)=>m(t,"name",{value:e,configurable:!0});import{prepared as i}from"../sqlite-statements.js";import{canRead as O}from"./access.js";import{getByRowid as p}from"./objects.js";function L(t,e,n){i(t,"INSERT OR IGNORE INTO edges (type, src, dst, written_as, created_at) VALUES ('acted-on', ?, ?, NULL, ?)").run(e.rowid,n.rowid,new Date().toISOString())}c(L,"recordActedOn");function T(t,e,n){const s=i(t,"SELECT dst FROM edges WHERE type = 'links-to' AND src = ?").all(e.rowid).map(({dst:o})=>o);i(t,"DELETE FROM edges WHERE type = 'links-to' AND src = ?").run(e.rowid);const d=i(t,"INSERT OR IGNORE INTO edges (type, src, dst, written_as, created_at) VALUES ('links-to', ?, ?, ?, ?)"),u=new Date().toISOString();for(const o of n)d.run(e.rowid,o.dst.rowid,o.written_as,u);const a=new Set(n.map(o=>o.dst.rowid));return s.filter(o=>!a.has(o))}c(T,"setLinks");function D(t,e,n){i(t,"DELETE FROM unresolved_links WHERE src = ?").run(e.rowid);const s=i(t,"INSERT OR IGNORE INTO unresolved_links (src, name) VALUES (?, ?)");for(const d of n)s.run(e.rowid,d)}c(D,"setUnresolved");function g(t,e,n){const s=i(t,"DELETE FROM unresolved_links WHERE src = ? AND name = ?");for(const d of n)s.run(e.rowid,d)}c(g,"dropUnresolved");function I(t,e,n){return i(t,"SELECT src, name FROM unresolved_links WHERE name = ? OR name = ? OR substr(name, -length(?) - 1) = '/' || ? ORDER BY src, name").all(e,n,e,e)}c(I,"unresolvedLinksCouldName");function A(t,e){return i(t,"SELECT e.dst, e.written_as FROM edges e WHERE e.type = 'links-to' AND e.src = ? ORDER BY e.written_as").all(e.rowid).map(s=>({written_as:s.written_as??"",dst:p(t,s.dst)}))}c(A,"linksOf");function h(t,e,n){return S(t,e,n,{type:"links-to",direction:"in"})}c(h,"backlinks");function S(t,e,n,s={}){if(!O(t,e,n))return[];const d=s.direction??"both",u=s.type?[s.type]:["acted-on","links-to"],a=[];for(const r of u)d!=="in"&&a.push(...i(t,"SELECT * FROM edges WHERE type = ? AND src = ?").all(r,n.rowid)),d!=="out"&&a.push(...i(t,"SELECT * FROM edges WHERE type = ? AND dst = ?").all(r,n.rowid));const o=new Set,w=[];for(const r of a){const R=`${r.type}|${r.src}|${r.dst}`;if(o.has(R))continue;o.add(R);const E=r.src===n.rowid?n:p(t,r.src),l=r.dst===n.rowid?n:p(t,r.dst);if(!E||!l)continue;const f=E===n?l:E;f!==n&&!O(t,e,f)||w.push({type:r.type,src:E,dst:l,written_as:r.written_as,created_at:r.created_at})}return w}c(S,"edgesOf");export{h as backlinks,g as dropUnresolved,S as edgesOf,A as linksOf,L as recordActedOn,T as setLinks,D as setUnresolved,I as unresolvedLinksCouldName};
1
+ var y=Object.defineProperty;var i=(t,r)=>y(t,"name",{value:r,configurable:!0});import{canRead as f}from"./access.js";import{getByRowid as E}from"./objects.js";import{mapAsync as O}from"../async-array.js";async function L(t,r,e){await t.prepare("INSERT OR IGNORE INTO edges (type, src, dst, written_as, created_at) VALUES ('acted-on', ?, ?, NULL, ?)").run(r.rowid,e.rowid,new Date().toISOString())}i(L,"recordActedOn");async function T(t,r,e){const s=(await t.prepare("SELECT dst FROM edges WHERE type = 'links-to' AND src = ?").all(r.rowid)).map(({dst:a})=>a);await t.prepare("DELETE FROM edges WHERE type = 'links-to' AND src = ?").run(r.rowid);const o=t.prepare("INSERT OR IGNORE INTO edges (type, src, dst, written_as, created_at) VALUES ('links-to', ?, ?, ?, ?)"),w=new Date().toISOString();for(const a of e)await o.run(r.rowid,a.dst.rowid,a.written_as,w);const c=new Set(e.map(a=>a.dst.rowid));return s.filter(a=>!c.has(a))}i(T,"setLinks");async function D(t,r,e){await t.prepare("DELETE FROM unresolved_links WHERE src = ?").run(r.rowid);const s=t.prepare("INSERT OR IGNORE INTO unresolved_links (src, name) VALUES (?, ?)");for(const o of e)await s.run(r.rowid,o)}i(D,"setUnresolved");async function g(t,r,e){const s=t.prepare("DELETE FROM unresolved_links WHERE src = ? AND name = ?");for(const o of e)await s.run(r.rowid,o)}i(g,"dropUnresolved");async function A(t,r,e){return await t.prepare("SELECT src, name FROM unresolved_links WHERE name = ? OR name = ? OR substr(name, -length(?) - 1) = '/' || ? ORDER BY src, name").all(r,e,r,r)}i(A,"unresolvedLinksCouldName");async function I(t,r){const e=await t.prepare("SELECT e.dst, e.written_as FROM edges e WHERE e.type = 'links-to' AND e.src = ? ORDER BY e.written_as").all(r.rowid);return await O(e,async s=>({written_as:s.written_as??"",dst:await E(t,s.dst)}))}i(I,"linksOf");async function h(t,r,e){return await m(t,r,e,{type:"links-to",direction:"in"})}i(h,"backlinks");async function m(t,r,e,s={}){if(!await f(t,r,e))return[];const o=s.direction??"both",w=s.type?[s.type]:["acted-on","links-to"],c=[];for(const n of w)o!=="in"&&c.push(...await t.prepare("SELECT * FROM edges WHERE type = ? AND src = ?").all(n,e.rowid)),o!=="out"&&c.push(...await t.prepare("SELECT * FROM edges WHERE type = ? AND dst = ?").all(n,e.rowid));const a=new Set,u=[];for(const n of c){const l=`${n.type}|${n.src}|${n.dst}`;if(a.has(l))continue;a.add(l);const p=n.src===e.rowid?e:await E(t,n.src),d=n.dst===e.rowid?e:await E(t,n.dst);if(!p||!d)continue;const R=p===e?d:p;R!==e&&!await f(t,r,R)||u.push({type:n.type,src:p,dst:d,written_as:n.written_as,created_at:n.created_at})}return u}i(m,"edgesOf");export{h as backlinks,g as dropUnresolved,m as edgesOf,I as linksOf,L as recordActedOn,T as setLinks,D as setUnresolved,A as unresolvedLinksCouldName};
@@ -1,12 +1,10 @@
1
- /** The event catalog, subject matching, listening-config resolution and `publish`: the one
2
- * path by which an event on an object reaches its watchers' inboxes. */
3
- import type { DatabaseSync } from 'node:sqlite';
4
- export declare function subscribeDocumentEvents(id: string, callback: (event: 'edited' | 'deleted') => void): () => void;
1
+ export declare function subscribeDocumentEvents(id: string, callback: (event: 'edited' | 'deleted') => void): Promise<() => void>;
5
2
  import { type ReposFn } from './reader.js';
6
3
  import { type Subscription } from './watches.js';
7
4
  import { CrtrError } from '../errors.js';
8
5
  import type { EventSpec } from './kinds/kind.js';
9
6
  import { type CanvasEvent, type Level, type ListenConfig, type ListenDelivery, type ObjectRow } from './types.js';
7
+ import { type CanvasDb } from '../canvas/db.js';
10
8
  /** The level `ev` publishes at: the declared level when none is supplied; a supplied level
11
9
  * must equal it or be one of the event's declared `levels`. Throws `unknown_event` for an
12
10
  * event the object's kind does not declare, `invalid_level` for any other level. */
@@ -17,7 +15,7 @@ export declare function matchSubject(pattern: string, event: string): boolean;
17
15
  * strongest. Null when the level is below every threshold of every config. */
18
16
  export declare function resolveDelivery(configs: readonly ListenConfig[], level: Level): ListenDelivery | null;
19
17
  /** A subscription's own config, else the watcher's `objects.listen_json`, else the global default. */
20
- export declare function listenConfigFor(db: DatabaseSync, subscription: Pick<Subscription, 'config'>, watcher: ObjectRow): ListenConfig;
18
+ export declare function listenConfigFor(db: CanvasDb, subscription: Pick<Subscription, 'config'>, watcher: ObjectRow): Promise<ListenConfig>;
21
19
  /** Supersede (`spec.supersedes`): each destination's pending deliveries of the same
22
20
  * event on the same object are deleted. A receiver kind may fence its claimed delivery if
23
21
  * that in-flight execution is replaceable. The replacement carries `spec.merge(prior, ev)` —
@@ -26,10 +24,10 @@ export declare function listenConfigFor(db: DatabaseSync, subscription: Pick<Sub
26
24
  * each group shares one replacement message. Messages left with no delivery are deleted.
27
25
  * The core selects matches by delivery destination and the message's event and object.
28
26
  * An event that does not supersede is one group with its own attrs. */
29
- export declare function supersede<D>(db: DatabaseSync, ev: CanvasEvent, spec: EventSpec, destinations: readonly D[], idOf: (d: D) => string): Array<{
27
+ export declare function supersede<D>(db: CanvasDb, ev: CanvasEvent, spec: EventSpec, destinations: readonly D[], idOf: (d: D) => string): Promise<Array<{
30
28
  attrs: Record<string, unknown>;
31
29
  destinations: D[];
32
- }>;
30
+ }>>;
33
31
  /**
34
32
  * Validate the event against its object's kind (`resolveLevel`), then push it to every watcher of
35
33
  * the object itself whose subscriptions receive it — a watch on an owner hears that owner's own
@@ -44,8 +42,8 @@ export declare const HOP_LIMIT = 8;
44
42
  export declare class HopLimitError extends CrtrError {
45
43
  constructor(depth: number);
46
44
  }
47
- export declare function publish(db: DatabaseSync, input: CanvasEvent, reposFn?: ReposFn): {
45
+ export declare function publish(db: CanvasDb, input: CanvasEvent, reposFn?: ReposFn): Promise<{
48
46
  delivered: number;
49
47
  message_id: string | null;
50
48
  depth: number;
51
- };
49
+ }>;
@@ -1,11 +1,11 @@
1
- var x=Object.defineProperty;var l=(n,e)=>x(n,"name",{value:e,configurable:!0});import{prepared as h}from"../sqlite-statements.js";import{EventEmitter as $}from"node:events";const S=new $;S.setMaxListeners(0);function ue(n,e){const o=l(s=>e(s),"listener");return S.on(n,o),()=>S.off(n,o)}l(ue,"subscribeDocumentEvents");import{evalCondition as B}from"../predicate.js";import{finalizeNodeMail as J,insertMessage as K}from"../feed/messages.js";import{linkAuthorizes as U,ownerChain as G,readCheck as q}from"./access.js";import{getByRowid as z}from"./objects.js";import{appScopesNow as X,publishLookups as Y,readerForObject as P}from"./reader.js";import{configFromJson as C}from"./watches.js";import{CrtrError as L}from"../errors.js";import{ExitCode as M}from"../../types.js";import{eventSpec as V,kindOf as D}from"./kinds/registry.js";import{machineNameOf as k}from"../peer/names.js";import{settleObjectWaits as Q}from"../canvas/waits.js";import{RECEIVERS as F}from"./receivers.js";import{DEFAULT_LISTEN as W}from"./types.js";function Z(n,e){if(n.level===void 0||n.level===e.level||e.levels?.includes(n.level))return n.level??e.level;const o=[e.level,...e.levels??[]].filter((s,t,i)=>i.indexOf(s)===t).sort((s,t)=>s-t);throw new L("invalid_level",`${n.object.type} ${n.event} publishes at level ${o.join(", ")}, not ${n.level}`,M.USAGE,{kind:n.object.type,event:n.event,level:n.level,allowed:o})}l(Z,"resolveLevel");function ee(n,e){const o=n.split("."),s=e.split(".");for(let t=0;t<o.length;t++){if(o[t]===">")return t===o.length-1&&s.length>t;if(t>=s.length||o[t]!=="*"&&o[t]!==s[t])return!1}return o.length===s.length}l(ee,"matchSubject");const H={"next-turn":1,"after-turn":2,steer:3,interrupt:4};function te(n,e){let o=null;for(const s of n){let t=null;for(const i of s)i.threshold<=e&&(!t||i.threshold>t.threshold)&&(t=i);t&&(!o||H[t.delivery]>H[o])&&(o=t.delivery)}return o}l(te,"resolveDelivery");function ve(n,e,o){if(e.config)return e.config;const s=h(n,"SELECT listen_json FROM objects WHERE rowid = ?").get(o.rowid);return s?.listen_json?C(s.listen_json):W}l(ve,"listenConfigFor");function ne(n,e){return e.inboxKind??(n.level>=7?"urgent":"update")}l(ne,"inboxKind");function oe(n,e){return e.type==="node"?e.id:h(n,`SELECT 1 FROM objects WHERE type IN ('person','app','repo','profile')
2
- AND name = ? AND rowid != ? LIMIT 1`).get(e.name,e.rowid)?`${e.type}:${e.name}`:e.name}l(oe,"ownerHandleOf");function se(n,e,o){const s=e.object.owner===null?null:h(n,"SELECT * FROM objects WHERE rowid = ?").get(e.object.owner),t=s?.id??null,i=s?oe(n,s):null;return{event:e.event,level:e.level,object:{id:e.object.id,type:e.object.type,kind:e.object.kind,owner:t,owner_handle:i,name:e.object.name,...e.object.home_machine?{machine:k(e.object.home_machine),machine_id:e.object.home_machine}:{}},actor:e.actor?.id??null,...e.actor?.home_machine?{actor_machine:k(e.actor.home_machine),actor_machine_id:e.actor.home_machine}:{},attrs:o,...e.pointer===void 0?{}:{pointer:e.pointer}}}l(se,"pushFields");function ie(n,e,o,s){const t=se(n,e,s),i=e.messageBody!==void 0&&o.carriesBody===!0,f=i?typeof e.messageBody=="object"&&e.messageBody!==null&&!Array.isArray(e.messageBody)?{...e.messageBody,push:t}:{body:e.messageBody,push:t}:{push:t},d=i?e.messageBody:null,a=d?.bodyRef===void 0?null:d;return{kind:ne(e,o),label:a?.label??(typeof d?.label=="string"?d.label:e.object.type.includes(".")&&typeof e.messageBody?.summary=="string"?e.messageBody.summary.split(`
3
- `)[0]:`${e.event} ${e.object.type} ${e.object.name}`),...a?.bodyRef===void 0?{}:{bodyRef:a.bodyRef},...a?.disposition===void 0?{}:{disposition:a.disposition},senderNodeId:e.actor?.type==="node"?e.actor.id:null,senderName:e.actor===null||e.actor===void 0?null:e.actor.home_machine?`${e.actor.name} on ${k(e.actor.home_machine)}`:e.actor.name,bodyJson:f}}l(ie,"messageInput");function re(n,e,o,s,t){if(!o.supersedes)return[{attrs:e.attrs,destinations:[...s]}];const i=h(n,`SELECT d.delivery_id, d.message_id, d.state, m.body_json FROM deliveries d
1
+ var H=Object.defineProperty;var d=(n,e)=>H(n,"name",{value:e,configurable:!0});import{EventEmitter as x}from"node:events";const v=new x;v.setMaxListeners(0);async function pe(n,e){const o=d(i=>e(i),"listener");return v.on(n,o),()=>v.off(n,o)}d(pe,"subscribeDocumentEvents");import{evalCondition as $}from"../predicate.js";import{finalizeNodeMail as B,insertMessage as J}from"../feed/messages.js";import{linkAuthorizes as K,ownerChain as U,readCheck as G}from"./access.js";import{getByRowid as q}from"./objects.js";import{appScopesNow as z,publishLookups as X,readerForObject as Y}from"./reader.js";import{configFromJson as T}from"./watches.js";import{CrtrError as A}from"../errors.js";import{ExitCode as L}from"../../types.js";import{eventSpec as P,kindOf as k}from"./kinds/registry.js";import{machineNameOf as M}from"../peer/names.js";import{settleObjectWaits as V}from"../canvas/waits.js";import{RECEIVERS as D}from"./receivers.js";import{DEFAULT_LISTEN as F}from"./types.js";import{afterCommit as Q}from"../canvas/db.js";function Z(n,e){if(n.level===void 0||n.level===e.level||e.levels?.includes(n.level))return n.level??e.level;const o=[e.level,...e.levels??[]].filter((i,t,s)=>s.indexOf(i)===t).sort((i,t)=>i-t);throw new A("invalid_level",`${n.object.type} ${n.event} publishes at level ${o.join(", ")}, not ${n.level}`,L.USAGE,{kind:n.object.type,event:n.event,level:n.level,allowed:o})}d(Z,"resolveLevel");function ee(n,e){const o=n.split("."),i=e.split(".");for(let t=0;t<o.length;t++){if(o[t]===">")return t===o.length-1&&i.length>t;if(t>=i.length||o[t]!=="*"&&o[t]!==i[t])return!1}return o.length===i.length}d(ee,"matchSubject");const W={"next-turn":1,"after-turn":2,steer:3,interrupt:4};function te(n,e){let o=null;for(const i of n){let t=null;for(const s of i)s.threshold<=e&&(!t||s.threshold>t.threshold)&&(t=s);t&&(!o||W[t.delivery]>W[o])&&(o=t.delivery)}return o}d(te,"resolveDelivery");async function ve(n,e,o){if(e.config)return e.config;const i=await n.prepare("SELECT listen_json FROM objects WHERE rowid = ?").get(o.rowid);return i?.listen_json?T(i.listen_json):F}d(ve,"listenConfigFor");function ne(n,e){return e.inboxKind??(n.level>=7?"urgent":"update")}d(ne,"inboxKind");async function oe(n,e){return e.type==="node"?e.id:await n.prepare(`SELECT 1 FROM objects WHERE type IN ('person','app','repo','profile')
2
+ AND name = ? AND rowid != ? LIMIT 1`).get(e.name,e.rowid)?`${e.type}:${e.name}`:e.name}d(oe,"ownerHandleOf");async function ie(n,e,o){const i=e.object.owner===null?null:await n.prepare("SELECT * FROM objects WHERE rowid = ?").get(e.object.owner),t=i?.id??null,s=i?await oe(n,i):null;return{event:e.event,level:e.level,object:{id:e.object.id,type:e.object.type,kind:e.object.kind,owner:t,owner_handle:s,name:e.object.name,...e.object.home_machine?{machine:M(e.object.home_machine),machine_id:e.object.home_machine}:{}},actor:e.actor?.id??null,...e.actor?.home_machine?{actor_machine:M(e.actor.home_machine),actor_machine_id:e.actor.home_machine}:{},attrs:o,...e.pointer===void 0?{}:{pointer:e.pointer}}}d(ie,"pushFields");async function se(n,e,o,i){const t=await ie(n,e,i),s=e.messageBody!==void 0&&o.carriesBody===!0,f=s?typeof e.messageBody=="object"&&e.messageBody!==null&&!Array.isArray(e.messageBody)?{...e.messageBody,push:t}:{body:e.messageBody,push:t}:{push:t},c=s?e.messageBody:null,l=c?.bodyRef===void 0?null:c;return{kind:ne(e,o),label:l?.label??(typeof c?.label=="string"?c.label:e.object.type.includes(".")&&typeof e.messageBody?.summary=="string"?e.messageBody.summary.split(`
3
+ `)[0]:`${e.event} ${e.object.type} ${e.object.name}`),...l?.bodyRef===void 0?{}:{bodyRef:l.bodyRef},...l?.disposition===void 0?{}:{disposition:l.disposition},senderNodeId:e.actor?.type==="node"?e.actor.id:null,senderName:e.actor===null||e.actor===void 0?null:e.actor.home_machine?`${e.actor.name} on ${M(e.actor.home_machine)}`:e.actor.name,bodyJson:f}}d(se,"messageInput");async function re(n,e,o,i,t){if(!o.supersedes)return[{attrs:e.attrs,destinations:[...i]}];const s=n.prepare(`SELECT d.delivery_id, d.message_id, d.state, m.body_json FROM deliveries d
4
4
  JOIN messages m ON m.message_id = d.message_id
5
5
  WHERE d.destination_id = ? AND d.state IN ('pending', 'handed_off')
6
6
  AND d.canceled_at IS NULL AND m.event = ? AND m.object_id = ?
7
- ORDER BY m.seq`),f=h(n,"DELETE FROM deliveries WHERE delivery_id = ?"),d=h(n,"SELECT * FROM objects WHERE id = ?"),a=new Map,_=new Set;for(const m of s){const w=t(m),O=d.get(w),I=O===void 0?void 0:D(n,O.type),j=i.all(w,e.event,e.object.id),b=new Set;for(const c of j)c.state==="handed_off"?I?.supersedeClaimed?.(n,c.delivery_id)&&b.add(c.delivery_id):(f.run(c.delivery_id),_.add(c.message_id));const y=j.filter(c=>c.state==="pending"||b.has(c.delivery_id)).at(-1),R=y?.message_id??null,r=a.get(R)??{prior:y?.body_json?JSON.parse(y.body_json).push?.attrs??null:null,destinations:[]};r.destinations.push(m),a.set(R,r)}const N=h(n,"DELETE FROM messages WHERE message_id = ? AND NOT EXISTS (SELECT 1 FROM deliveries WHERE message_id = ?)");for(const m of _)N.run(m,m);return[...a.values()].map(m=>({attrs:o.merge?o.merge(m.prior,e):e.attrs,destinations:m.destinations}))}l(re,"supersede");function ce(n,e,o,s,t){const i=z(n,s);if(i===null||i.type!=="app")return!1;const f=h(n,"SELECT 1 FROM peer_stubs WHERE object = ?").get(e.rowid)!==void 0,d=f?null:X(n,i,t);return(f||d!==null)&&U(n,i,d,e,o)}l(ce,"linkDelivers");const T=8;class de extends L{static{l(this,"HopLimitError")}constructor(e){super("hop_limit",`event depth ${e} exceeds ${T}`,M.GENERAL,{depth:e,limit:T})}}function Se(n,e,o=()=>[]){const s=V(n,e.object.type,e.event),t={...e,level:Z(e,s)};t.object.type==="document"&&(t.event==="edited"||t.event==="deleted")&&queueMicrotask(()=>S.emit(t.object.id,t.event));const i=e.cause??null,f=i===null?null:h(n,`SELECT depth FROM messages WHERE message_id = ?
8
- UNION ALL SELECT depth FROM message_causes WHERE message_id = ? LIMIT 1`).get(i,i);if(i!==null&&f===void 0)throw new L("unknown_cause",`no message ${i}`,M.USAGE,{cause:i});const d=f===null?0:f.depth+1;if(d>T)throw new de(d);(s.endsWait===!0||t.event==="deleted")&&Q(n,t.object.id);const a=G(n,t.object),_=`w.watcher, o.id AS watcher_id, o.type AS watcher_type, o.reception, s.pattern, s.filter_json,
9
- COALESCE(s.config_json, o.listen_json) AS config_json, w.link_app`,N=n.prepare(s.durable?`SELECT ${_} FROM watches w JOIN watch_subscriptions s ON s.watch = w.rowid
10
- JOIN objects o ON o.rowid = w.watcher WHERE w.object = ? AND w.watcher != ? AND o.reception >= 1`:`SELECT ${_} FROM objects o INDEXED BY objects_receiving CROSS JOIN watches w CROSS JOIN watch_subscriptions s
11
- WHERE o.reception = 2 AND w.watcher = o.rowid AND s.watch = w.rowid AND w.object = ? AND w.watcher != ?`).all(t.object.rowid,t.actor?.rowid??-1);if(N.length===0)return{delivered:0,message_id:null,depth:d};const m={event:t.event,level:t.level,id:t.object.id,type:t.object.type,kind:t.object.kind,actor:t.actor?.id??null,...t.attrs},w=new Map;for(const r of N){if(t.onlyWatchers!==void 0&&!t.onlyWatchers.includes(r.watcher_id)||!ee(r.pattern,t.event)||r.filter_json!==null&&!B(JSON.parse(r.filter_json),m))continue;const c=w.get(r.watcher)??{id:r.watcher_id,type:r.watcher_type,reception:r.reception,configs:[],linkApp:r.link_app};c.configs.push(r.config_json?C(r.config_json):W),w.set(r.watcher,c)}const O=(a.length?a[a.length-1]:t.object).type==="repo",I=l(()=>[],"noRepos"),j=q(n,t.object),b=Y(n),y=[];for(const r of w.values()){const c=h(n,"SELECT * FROM objects WHERE id = ?").get(r.id),u=D(n,c.type),v=u.receiverFor?u.receiverFor(n,c):u.receiver;if(v===void 0)continue;const g=te(r.configs,t.level);if(g===null)continue;const E=P(n,c,O?o:I,b);if(E.scopes===null&&(E.class==="node"||E.owner.type!=="person"))continue;const p=r.linkApp!==null&&!j(E)&&ce(n,t.object,c,r.linkApp,b);!p&&!j(E)||y.push({id:r.id,reception:r.reception,delivery:g,receiver:v,...p?{linked:p}:{}})}if(y.length===0)return{delivered:0,message_id:null,depth:d};let R=null;for(const r of re(n,t,s,y,c=>c.id)){const c=new Map;for(const p of r.destinations)c.set(p.receiver,[...c.get(p.receiver)??[],p]);const u=ie(n,t,s,r.attrs),v=[...c].map(([p,A])=>F[p].bodyOwner(A)).find(p=>p!==null)??null,g=J({...u,urgency:"normal"},v),E=K(n,{operationId:g.operationId,createdAt:g.createdAt,senderNodeId:u.senderNodeId,senderName:u.senderName,kind:u.kind,label:u.label,bodyRef:g.bodyRef,bodyJson:g.bodyJson,disposition:u.disposition??null,event:{event:t.event,objectId:t.object.id,level:t.level,actorId:t.actor?.id??null},causeMessageId:i,depth:d});R??=E;for(const[p,A]of c)F[p].enqueue(n,{messageId:E,event:t.event,level:t.level,senderNodeId:u.senderNodeId,elevatesTier:s.elevatesTier===!0,...t.idempotencyKey===void 0?{}:{idempotencyKey:t.idempotencyKey}},A)}return{delivered:y.length,message_id:R,depth:d}}l(Se,"publish");export{T as HOP_LIMIT,de as HopLimitError,ve as listenConfigFor,ee as matchSubject,Se as publish,te as resolveDelivery,Z as resolveLevel,ue as subscribeDocumentEvents,re as supersede};
7
+ ORDER BY m.seq`),f=n.prepare("DELETE FROM deliveries WHERE delivery_id = ?"),c=n.prepare("SELECT * FROM objects WHERE id = ?"),l=new Map,g=new Set;for(const m of i){const E=t(m),N=await c.get(E),S=N===void 0?void 0:await k(n,N.type),_=await s.all(E,e.event,e.object.id),j=new Set;for(const a of _)a.state==="handed_off"?await S?.supersedeClaimed?.(n,a.delivery_id)&&j.add(a.delivery_id):(await f.run(a.delivery_id),g.add(a.message_id));const w=_.filter(a=>a.state==="pending"||j.has(a.delivery_id)).at(-1),b=w?.message_id??null,r=l.get(b)??{prior:w?.body_json?JSON.parse(w.body_json).push?.attrs??null:null,destinations:[]};r.destinations.push(m),l.set(b,r)}const R=n.prepare("DELETE FROM messages WHERE message_id = ? AND NOT EXISTS (SELECT 1 FROM deliveries WHERE message_id = ?)");for(const m of g)await R.run(m,m);return[...l.values()].map(m=>({attrs:o.merge?o.merge(m.prior,e):e.attrs,destinations:m.destinations}))}d(re,"supersede");async function ae(n,e,o,i,t){const s=await q(n,i);if(s===null||s.type!=="app")return!1;const f=await n.prepare("SELECT 1 FROM peer_stubs WHERE object = ?").get(e.rowid)!==void 0,c=f?null:await z(n,s,t);return(f||c!==null)&&await K(n,s,c,e,o)}d(ae,"linkDelivers");const C=8;class ce extends A{static{d(this,"HopLimitError")}constructor(e){super("hop_limit",`event depth ${e} exceeds ${C}`,L.GENERAL,{depth:e,limit:C})}}async function Se(n,e,o=async()=>[]){const i=await P(n,e.object.type,e.event),t={...e,level:Z(e,i)};t.object.type==="document"&&(t.event==="edited"||t.event==="deleted")&&Q(()=>v.emit(t.object.id,t.event));const s=e.cause??null,f=s===null?null:await n.prepare(`SELECT depth FROM messages WHERE message_id = ?
8
+ UNION ALL SELECT depth FROM message_causes WHERE message_id = ? LIMIT 1`).get(s,s);if(s!==null&&f===void 0)throw new A("unknown_cause",`no message ${s}`,L.USAGE,{cause:s});const c=f===null?0:f.depth+1;if(c>C)throw new ce(c);(i.endsWait===!0||t.event==="deleted")&&await V(n,t.object.id);const l=await U(n,t.object),g=`w.watcher, o.id AS watcher_id, o.type AS watcher_type, o.reception, s.pattern, s.filter_json,
9
+ COALESCE(s.config_json, o.listen_json) AS config_json, w.link_app`,R=await n.prepareUncached(i.durable?`SELECT ${g} FROM watches w JOIN watch_subscriptions s ON s.watch = w.rowid
10
+ JOIN objects o ON o.rowid = w.watcher WHERE w.object = ? AND w.watcher != ? AND o.reception >= 1`:`SELECT ${g} FROM objects o INDEXED BY objects_receiving CROSS JOIN watches w CROSS JOIN watch_subscriptions s
11
+ WHERE o.reception = 2 AND w.watcher = o.rowid AND s.watch = w.rowid AND w.object = ? AND w.watcher != ?`).all(t.object.rowid,t.actor?.rowid??-1);if(R.length===0)return{delivered:0,message_id:null,depth:c};const m={event:t.event,level:t.level,id:t.object.id,type:t.object.type,kind:t.object.kind,actor:t.actor?.id??null,...t.attrs},E=new Map;for(const r of R){if(t.onlyWatchers!==void 0&&!t.onlyWatchers.includes(r.watcher_id)||!ee(r.pattern,t.event)||r.filter_json!==null&&!$(JSON.parse(r.filter_json),m))continue;const a=E.get(r.watcher)??{id:r.watcher_id,type:r.watcher_type,reception:r.reception,configs:[],linkApp:r.link_app};a.configs.push(r.config_json?T(r.config_json):F),E.set(r.watcher,a)}const N=(l.length?l[l.length-1]:t.object).type==="repo",S=d(async()=>[],"noRepos"),_=await G(n,t.object),j=X(n),w=[];for(const r of E.values()){const a=await n.prepare("SELECT * FROM objects WHERE id = ?").get(r.id),u=await k(n,a.type),O=u.receiverFor?await u.receiverFor(n,a):u.receiver;if(O===void 0)continue;const h=te(r.configs,t.level);if(h===null)continue;const y=await Y(n,a,N?o:S,j);if(y.scopes===null&&(y.class==="node"||y.owner.type!=="person"))continue;const p=r.linkApp!==null&&!await _(y)&&await ae(n,t.object,a,r.linkApp,j);!p&&!await _(y)||w.push({id:r.id,reception:r.reception,delivery:h,receiver:O,...p?{linked:p}:{}})}if(w.length===0)return{delivered:0,message_id:null,depth:c};let b=null;for(const r of await re(n,t,i,w,a=>a.id)){const a=new Map;for(const p of r.destinations)a.set(p.receiver,[...a.get(p.receiver)??[],p]);const u=await se(n,t,i,r.attrs),O=[...a].map(([p,I])=>D[p].bodyOwner(I)).find(p=>p!==null)??null,h=B({...u,urgency:"normal"},O),y=await J(n,{operationId:h.operationId,createdAt:h.createdAt,senderNodeId:u.senderNodeId,senderName:u.senderName,kind:u.kind,label:u.label,bodyRef:h.bodyRef,bodyJson:h.bodyJson,disposition:u.disposition??null,event:{event:t.event,objectId:t.object.id,level:t.level,actorId:t.actor?.id??null},causeMessageId:s,depth:c});b??=y;for(const[p,I]of a)await D[p].enqueue(n,{messageId:y,event:t.event,level:t.level,senderNodeId:u.senderNodeId,elevatesTier:i.elevatesTier===!0,...t.idempotencyKey===void 0?{}:{idempotencyKey:t.idempotencyKey}},I)}return{delivered:w.length,message_id:b,depth:c}}d(Se,"publish");export{C as HOP_LIMIT,ce as HopLimitError,ve as listenConfigFor,ee as matchSubject,Se as publish,te as resolveDelivery,Z as resolveLevel,pe as subscribeDocumentEvents,re as supersede};
@@ -2,8 +2,8 @@
2
2
  * channel (`system` = rebuilt system prompt, `transcript` = conversation), in
3
3
  * `exposures` and `context_sessions`. Rows cascade with the node. Callers
4
4
  * load, mutate in memory, and `saveLedger` inside their own transaction. */
5
- import type { DatabaseSync } from 'node:sqlite';
6
5
  import type { RuleSpec } from './types.js';
6
+ import type { CanvasDb } from '../canvas/db.js';
7
7
  export type ExposureLevel = RuleSpec['deliver'];
8
8
  export type Channel = 'system' | 'transcript';
9
9
  export interface Held {
@@ -28,16 +28,16 @@ export interface Exposed {
28
28
  headsKey: string | null;
29
29
  contentHash: string | null;
30
30
  }
31
- export declare function loadLedger(db: DatabaseSync, node: number): Ledger;
31
+ export declare function loadLedger(db: CanvasDb, node: number): Promise<Ledger>;
32
32
  /** Write what changed since `loadLedger` (a ledger never loaded is written whole). */
33
- export declare function saveLedger(db: DatabaseSync, ledger: Ledger): void;
33
+ export declare function saveLedger(db: CanvasDb, ledger: Ledger): Promise<void>;
34
34
  /** Whether the node has a ledger at all (a context session or any exposure). */
35
- export declare function hasLedger(db: DatabaseSync, node: number): boolean;
35
+ export declare function hasLedger(db: CanvasDb, node: number): Promise<boolean>;
36
36
  /** End the node's context session: nothing is held any more. */
37
- export declare function clearLedger(db: DatabaseSync, node: number): void;
37
+ export declare function clearLedger(db: CanvasDb, node: number): Promise<void>;
38
38
  /** Seed a fork with what the source's transcript holds; the fork builds its own
39
39
  * system prompt, so system rows and the preference snapshot are not copied. */
40
- export declare function forkLedger(db: DatabaseSync, source: number, fork: number): void;
40
+ export declare function forkLedger(db: CanvasDb, source: number, fork: number): Promise<void>;
41
41
  /** Held at `level` or above: this object, or any held object with the same body
42
42
  * (content hash). The object itself counts at content level only for the same revision. */
43
43
  export declare function heldAtOrAbove(ledger: Ledger, exposed: Exposed, level: ExposureLevel, channel?: Channel): boolean;
@@ -1,4 +1,4 @@
1
- var O=Object.defineProperty;var i=(n,e)=>O(n,"name",{value:e,configurable:!0});import{prepared as a}from"../sqlite-statements.js";const f={name:1,preview:2,content:3},b=["system","transcript"],l=new WeakMap;function _(n){return{node:n.node,preferenceSnapshot:n.preferenceSnapshot,objects:new Map([...n.objects].map(([e,t])=>[e,{...t}])),listed:new Map([...n.listed].map(([e,t])=>[e,{...t}]))}}i(_,"cloneLedger");function S(n){return{node:n,preferenceSnapshot:null,objects:new Map,listed:new Map}}i(S,"emptyLedger");function T(n,e){const t=S(e),s=a(n,"SELECT preference_snapshot, listed_json FROM context_sessions WHERE node = ?").get(e);if(s!==void 0){t.preferenceSnapshot=s.preference_snapshot;for(const[o,r]of Object.entries(JSON.parse(s.listed_json)))t.listed.set(o,r)}const c=a(n,"SELECT object, channel, level, heads_key, content_hash FROM exposures WHERE node = ?").all(e);for(const o of c){const r=t.objects.get(o.object)??{headsKey:o.heads_key,contentHash:o.content_hash};r[o.channel]=o.level,t.objects.set(o.object,r)}return l.set(t,_(t)),t}i(T,"loadLedger");function x(n,e){const t=l.get(e)??S(e.node),s=JSON.stringify(Object.fromEntries(e.listed));(e.preferenceSnapshot!==t.preferenceSnapshot||s!==JSON.stringify(Object.fromEntries(t.listed)))&&a(n,`INSERT INTO context_sessions (node, preference_snapshot, listed_json) VALUES (?, ?, ?)
2
- ON CONFLICT(node) DO UPDATE SET preference_snapshot = excluded.preference_snapshot, listed_json = excluded.listed_json`).run(e.node,e.preferenceSnapshot,s);const c=a(n,`INSERT INTO exposures (node, object, channel, level, heads_key, content_hash) VALUES (?, ?, ?, ?, ?, ?)
3
- ON CONFLICT(node, object, channel) DO UPDATE SET level = excluded.level, heads_key = excluded.heads_key, content_hash = excluded.content_hash`),o=a(n,"DELETE FROM exposures WHERE node = ? AND object = ? AND channel = ?"),r=new Set([...t.objects.keys(),...e.objects.keys()]);for(const d of r){const u=e.objects.get(d),p=t.objects.get(d);for(const h of b){const E=u?.[h];E===void 0?p?.[h]!==void 0&&o.run(e.node,d,h):(E!==p?.[h]||u.headsKey!==p?.headsKey||u.contentHash!==p?.contentHash)&&c.run(e.node,d,h,E,u.headsKey,u.contentHash)}}l.set(e,_(e))}i(x,"saveLedger");function H(n,e){return a(n,"SELECT 1 FROM context_sessions WHERE node = ? UNION ALL SELECT 1 FROM exposures WHERE node = ? LIMIT 1").get(e,e)!==void 0}i(H,"hasLedger");function L(n,e){a(n,"DELETE FROM exposures WHERE node = ?").run(e),a(n,"DELETE FROM context_sessions WHERE node = ?").run(e)}i(L,"clearLedger");function R(n,e,t){L(n,t),a(n,`INSERT INTO exposures (node, object, channel, level, heads_key, content_hash)
4
- SELECT ?, object, channel, level, heads_key, content_hash FROM exposures WHERE node = ? AND channel = 'transcript'`).run(t,e);const s=a(n,"SELECT listed_json FROM context_sessions WHERE node = ?").get(e);if(s===void 0)return;const c={};for(const[o,r]of Object.entries(JSON.parse(s.listed_json)))r.transcript!==void 0&&(c[o]={transcript:r.transcript});a(n,"INSERT INTO context_sessions (node, preference_snapshot, listed_json) VALUES (?, NULL, ?)").run(t,JSON.stringify(c))}i(R,"forkLedger");function j(n,e){if(n===void 0)return 0;const t=i(s=>n[s]!==void 0?f[n[s]]:0,"of");return e!==void 0?t(e):Math.max(t("system"),t("transcript"))}i(j,"rankIn");function m(n,e,t,s){const c=f[t],o=n.objects.get(e.object);if(o!==void 0&&j(o,s)>=c&&(t!=="content"||o.headsKey===e.headsKey))return!0;if(e.contentHash===null)return!1;for(const r of n.objects.values())if(r.contentHash===e.contentHash&&j(r,s)>=c)return!0;return!1}i(m,"heldAtOrAbove");function M(n,e,t,s){const c=n.objects.get(t.object),o=c!==void 0&&c.headsKey===t.headsKey&&c.contentHash===t.contentHash,r=o?{...c}:{headsKey:t.headsKey,contentHash:t.contentHash},d=o?c[e]:void 0;r[e]=d!==void 0&&f[d]>=f[s]?d:s,n.objects.set(t.object,r)}i(M,"hold");function A(n,e,t,s){return j(n.listed.get(e),s)>=f[t]}i(A,"listedAtOrAbove");function v(n,e,t,s){const c=n.listed.get(t)??{},o=c[e];o!==void 0&&f[o]>=f[s]||n.listed.set(t,{...c,[e]:s})}i(v,"holdListing");function I(n,e){const t=n.objects.get(e);if(t!==void 0)for(const[s,c]of n.objects){if(s!==e&&(t.contentHash===null||c.contentHash!==t.contentHash))continue;const{transcript:o,...r}=c;r.system===void 0?n.objects.delete(s):n.objects.set(s,r)}}i(I,"demoteTranscript");function w(n,e){return n.preferenceSnapshot===null&&(n.preferenceSnapshot=e),n.preferenceSnapshot}i(w,"freezePreferences");function k(n){return[...n.objects.values()].some(e=>e.transcript!==void 0)||[...n.listed.values()].some(e=>e.transcript!==void 0)}i(k,"hasTranscript");export{L as clearLedger,I as demoteTranscript,R as forkLedger,w as freezePreferences,H as hasLedger,k as hasTranscript,m as heldAtOrAbove,M as hold,v as holdListing,A as listedAtOrAbove,T as loadLedger,x as saveLedger};
1
+ var y=Object.defineProperty;var a=(n,e)=>y(n,"name",{value:e,configurable:!0});const p={name:1,preview:2,content:3},S=["system","transcript"],E=new WeakMap;function j(n){return{node:n.node,preferenceSnapshot:n.preferenceSnapshot,objects:new Map([...n.objects].map(([e,t])=>[e,{...t}])),listed:new Map([...n.listed].map(([e,t])=>[e,{...t}]))}}a(j,"cloneLedger");function _(n){return{node:n,preferenceSnapshot:null,objects:new Map,listed:new Map}}a(_,"emptyLedger");async function L(n,e){const t=_(e),s=await n.prepare("SELECT preference_snapshot, listed_json FROM context_sessions WHERE node = ?").get(e);if(s!==void 0){t.preferenceSnapshot=s.preference_snapshot;for(const[o,c]of Object.entries(JSON.parse(s.listed_json)))t.listed.set(o,c)}const r=await n.prepare("SELECT object, channel, level, heads_key, content_hash FROM exposures WHERE node = ?").all(e);for(const o of r){const c=t.objects.get(o.object)??{headsKey:o.heads_key,contentHash:o.content_hash};c[o.channel]=o.level,t.objects.set(o.object,c)}return E.set(t,j(t)),t}a(L,"loadLedger");async function N(n,e){const t=E.get(e)??_(e.node),s=JSON.stringify(Object.fromEntries(e.listed));(e.preferenceSnapshot!==t.preferenceSnapshot||s!==JSON.stringify(Object.fromEntries(t.listed)))&&await n.prepare(`INSERT INTO context_sessions (node, preference_snapshot, listed_json) VALUES (?, ?, ?)
2
+ ON CONFLICT(node) DO UPDATE SET preference_snapshot = excluded.preference_snapshot, listed_json = excluded.listed_json`).run(e.node,e.preferenceSnapshot,s);const r=n.prepare(`INSERT INTO exposures (node, object, channel, level, heads_key, content_hash) VALUES (?, ?, ?, ?, ?, ?)
3
+ ON CONFLICT(node, object, channel) DO UPDATE SET level = excluded.level, heads_key = excluded.heads_key, content_hash = excluded.content_hash`),o=n.prepare("DELETE FROM exposures WHERE node = ? AND object = ? AND channel = ?"),c=new Set([...t.objects.keys(),...e.objects.keys()]);for(const i of c){const f=e.objects.get(i),u=t.objects.get(i);for(const d of S){const h=f?.[d];h===void 0?u?.[d]!==void 0&&await o.run(e.node,i,d):(h!==u?.[d]||f.headsKey!==u?.headsKey||f.contentHash!==u?.contentHash)&&await r.run(e.node,i,d,h,f.headsKey,f.contentHash)}}E.set(e,j(e))}a(N,"saveLedger");async function T(n,e){return await n.prepare("SELECT 1 FROM context_sessions WHERE node = ? UNION ALL SELECT 1 FROM exposures WHERE node = ? LIMIT 1").get(e,e)!==void 0}a(T,"hasLedger");async function O(n,e){await n.prepare("DELETE FROM exposures WHERE node = ?").run(e),await n.prepare("DELETE FROM context_sessions WHERE node = ?").run(e)}a(O,"clearLedger");async function w(n,e,t){await O(n,t),await n.prepare(`INSERT INTO exposures (node, object, channel, level, heads_key, content_hash)
4
+ SELECT ?, object, channel, level, heads_key, content_hash FROM exposures WHERE node = ? AND channel = 'transcript'`).run(t,e);const s=await n.prepare("SELECT listed_json FROM context_sessions WHERE node = ?").get(e);if(s===void 0)return;const r={};for(const[o,c]of Object.entries(JSON.parse(s.listed_json)))c.transcript!==void 0&&(r[o]={transcript:c.transcript});await n.prepare("INSERT INTO context_sessions (node, preference_snapshot, listed_json) VALUES (?, NULL, ?)").run(t,JSON.stringify(r))}a(w,"forkLedger");function l(n,e){if(n===void 0)return 0;const t=a(s=>n[s]!==void 0?p[n[s]]:0,"of");return e!==void 0?t(e):Math.max(t("system"),t("transcript"))}a(l,"rankIn");function x(n,e,t,s){const r=p[t],o=n.objects.get(e.object);if(o!==void 0&&l(o,s)>=r&&(t!=="content"||o.headsKey===e.headsKey))return!0;if(e.contentHash===null)return!1;for(const c of n.objects.values())if(c.contentHash===e.contentHash&&l(c,s)>=r)return!0;return!1}a(x,"heldAtOrAbove");function H(n,e,t,s){const r=n.objects.get(t.object),o=r!==void 0&&r.headsKey===t.headsKey&&r.contentHash===t.contentHash,c=o?{...r}:{headsKey:t.headsKey,contentHash:t.contentHash},i=o?r[e]:void 0;c[e]=i!==void 0&&p[i]>=p[s]?i:s,n.objects.set(t.object,c)}a(H,"hold");function R(n,e,t,s){return l(n.listed.get(e),s)>=p[t]}a(R,"listedAtOrAbove");function M(n,e,t,s){const r=n.listed.get(t)??{},o=r[e];o!==void 0&&p[o]>=p[s]||n.listed.set(t,{...r,[e]:s})}a(M,"holdListing");function m(n,e){const t=n.objects.get(e);if(t!==void 0)for(const[s,r]of n.objects){if(s!==e&&(t.contentHash===null||r.contentHash!==t.contentHash))continue;const{transcript:o,...c}=r;c.system===void 0?n.objects.delete(s):n.objects.set(s,c)}}a(m,"demoteTranscript");function A(n,e){return n.preferenceSnapshot===null&&(n.preferenceSnapshot=e),n.preferenceSnapshot}a(A,"freezePreferences");function v(n){return[...n.objects.values()].some(e=>e.transcript!==void 0)||[...n.listed.values()].some(e=>e.transcript!==void 0)}a(v,"hasTranscript");export{O as clearLedger,m as demoteTranscript,w as forkLedger,A as freezePreferences,T as hasLedger,v as hasTranscript,x as heldAtOrAbove,H as hold,M as holdListing,R as listedAtOrAbove,L as loadLedger,N as saveLedger};
@@ -1,7 +1,5 @@
1
- /** Jobs: a backgrounded bash command as an object the node that started it owns, with its
2
- * `jobs` row and the events of its start and end. Runs in the caller's transaction. */
3
- import type { DatabaseSync } from 'node:sqlite';
4
1
  import type { ObjectRow } from './types.js';
2
+ import type { CanvasDb } from '../canvas/db.js';
5
3
  export type JobStatus = 'running' | 'exited' | 'killed';
6
4
  export interface JobRow {
7
5
  object: number;
@@ -11,21 +9,21 @@ export interface JobRow {
11
9
  job_dir: string;
12
10
  log_path: string;
13
11
  }
14
- export declare function jobRow(db: DatabaseSync, job: ObjectRow): JobRow | null;
12
+ export declare function jobRow(db: CanvasDb, job: ObjectRow): Promise<JobRow | null>;
15
13
  /** Create the job object (`id` keeps the job id the runner already uses), its `running` row,
16
14
  * the node's acted-on edge and `job-start` watch, and publish `created`. */
17
- export declare function startJob(db: DatabaseSync, node: ObjectRow, spec: {
15
+ export declare function startJob(db: CanvasDb, node: ObjectRow, spec: {
18
16
  id?: string;
19
17
  command: string;
20
18
  jobDir: string;
21
19
  logPath: string;
22
- }): ObjectRow;
20
+ }): Promise<ObjectRow>;
23
21
  /** End a running job: `exited` with its exit code, or `killed` with the killer as actor (null
24
22
  * when the runtime killed it, e.g. at its deadline; `reason` then names why). The event carries
25
23
  * the exit code and log path, never output. A job already ended is left as is. */
26
- export declare function finishJob(db: DatabaseSync, job: ObjectRow, end: {
24
+ export declare function finishJob(db: CanvasDb, job: ObjectRow, end: {
27
25
  exitCode: number;
28
26
  } | {
29
27
  killedBy: ObjectRow | null;
30
28
  reason?: string;
31
- }): ObjectRow;
29
+ }): Promise<ObjectRow>;
@@ -1,2 +1,2 @@
1
- var w=Object.defineProperty;var n=(t,o)=>w(t,"name",{value:o,configurable:!0});import{prepared as a}from"../sqlite-statements.js";import{recordActedOn as u}from"./edges.js";import{publish as d}from"./events.js";import{createObject as h,getByRowid as E}from"./objects.js";import{recordWatch as b}from"./watches.js";function m(t){return t.split(`
2
- `,1)[0].trim()}n(m,"firstLine");function f(t,o){return`${m(t)} (${o})`}n(f,"previewOf");function j(t,o){return a(t,"SELECT * FROM jobs WHERE object = ?").get(o.rowid)??null}n(j,"jobRow");function v(t,o,r){if(o.type!=="node")throw new Error(`startJob: ${o.id} is a ${o.type}, not a node`);const i=h(t,{...r.id===void 0?{}:{id:r.id},type:"job",kind:"bash",owner:o.rowid,privacy:"public",name:m(r.command)||"bash",preview:f(r.command,"running")});return a(t,"INSERT INTO jobs (object, command, status, exit_code, job_dir, log_path) VALUES (?, ?, 'running', NULL, ?, ?)").run(i.rowid,r.command,r.jobDir,r.logPath),u(t,o,i),b(t,o,i,"job-start"),d(t,{event:"created",object:i,actor:o,attrs:{}}),i}n(v,"startJob");function S(t,o,r){const i=j(t,o);if(i===null)throw new Error(`finishJob: ${o.id} has no jobs row`);if(i.status!=="running")return o;const e="killedBy"in r,s=e?"killed":"exited",l=e?null:r.exitCode;a(t,"UPDATE jobs SET status = ?, exit_code = ? WHERE object = ?").run(s,l,o.rowid);const p=e?"killed":`exited ${l}`;a(t,"UPDATE objects SET preview = ? WHERE rowid = ?").run(f(i.command,p),o.rowid);const c=E(t,o.rowid);return e&&r.killedBy!==null&&u(t,r.killedBy,c),d(t,{event:s,object:c,actor:e?r.killedBy:null,attrs:e?{"log-path":i.log_path,...r.reason===void 0?{}:{reason:r.reason}}:{"exit-code":l,"log-path":i.log_path}}),c}n(S,"finishJob");export{S as finishJob,j as jobRow,v as startJob};
1
+ var m=Object.defineProperty;var e=(t,r)=>m(t,"name",{value:r,configurable:!0});import{recordActedOn as s}from"./edges.js";import{publish as u}from"./events.js";import{createObject as f,getByRowid as E}from"./objects.js";import{recordWatch as h}from"./watches.js";function w(t){return t.split(`
2
+ `,1)[0].trim()}e(w,"firstLine");function d(t,r){return`${w(t)} (${r})`}e(d,"previewOf");async function b(t,r){return await t.prepare("SELECT * FROM jobs WHERE object = ?").get(r.rowid)??null}e(b,"jobRow");async function R(t,r,i){if(r.type!=="node")throw new Error(`startJob: ${r.id} is a ${r.type}, not a node`);const o=await f(t,{...i.id===void 0?{}:{id:i.id},type:"job",kind:"bash",owner:r.rowid,privacy:"public",name:w(i.command)||"bash",preview:d(i.command,"running")});return await t.prepare("INSERT INTO jobs (object, command, status, exit_code, job_dir, log_path) VALUES (?, ?, 'running', NULL, ?, ?)").run(o.rowid,i.command,i.jobDir,i.logPath),await s(t,r,o),await h(t,r,o,"job-start"),await u(t,{event:"created",object:o,actor:r,attrs:{}}),o}e(R,"startJob");async function T(t,r,i){const o=await b(t,r);if(o===null)throw new Error(`finishJob: ${r.id} has no jobs row`);if(o.status!=="running")return r;const a="killedBy"in i,c=a?"killed":"exited",n=a?null:i.exitCode;await t.prepare("UPDATE jobs SET status = ?, exit_code = ? WHERE object = ?").run(c,n,r.rowid);const p=a?"killed":`exited ${n}`;await t.prepare("UPDATE objects SET preview = ? WHERE rowid = ?").run(d(o.command,p),r.rowid);const l=await E(t,r.rowid);return a&&i.killedBy!==null&&await s(t,i.killedBy,l),await u(t,{event:c,object:l,actor:a?i.killedBy:null,attrs:a?{"log-path":o.log_path,...i.reason===void 0?{}:{reason:i.reason}}:{"exit-code":n,"log-path":o.log_path}}),l}e(T,"finishJob");export{T as finishJob,b as jobRow,R as startJob};
@@ -1 +1 @@
1
- import{receiverForObject as o}from"../receivers.js";import{withBase as d}from"./kind.js";import{header as c}from"./render.js";import{objectDTO as n}from"./dto.js";const b={name:"action",addressable:"id",events:d({}),receiverFor:o,supersedeClaimed(r,t){const e=Date.now();return Number(r.prepare("UPDATE deliveries SET canceled_at = ?, updated_at = ? WHERE delivery_id = ? AND state = 'handed_off' AND canceled_at IS NULL").run(e,e,t).changes)===1},read(r,t,e){const a={object:n(r,e)};return{data:a,text:c("object",a.object)}}};export{b as actionKind};
1
+ import{receiverForObject as o}from"../receivers.js";import{withBase as c}from"./kind.js";import{header as d}from"./render.js";import{objectDTO as n}from"./dto.js";const b={name:"action",addressable:"id",events:c({}),receiverFor:o,async supersedeClaimed(r,t){const e=Date.now();return Number((await r.prepareUncached("UPDATE deliveries SET canceled_at = ?, updated_at = ? WHERE delivery_id = ? AND state = 'handed_off' AND canceled_at IS NULL").run(e,e,t)).changes)===1},async read(r,t,e){const a={object:await n(r,e)};return{data:a,text:d("object",a.object)}}};export{b as actionKind};
@@ -1,7 +1,7 @@
1
- var l=Object.defineProperty;var d=(s,c)=>l(s,"name",{value:c,configurable:!0});import{prepared as m}from"../../sqlite-statements.js";import{recordLiveRead as u}from"./kind.js";import{header as v}from"./render.js";import{objectDTO as j}from"./dto.js";import{receiverForObject as b}from"../receivers.js";function S(s,c){const a=Object.fromEntries(Object.entries(c).map(([t,{ends_wait:i,...o}])=>[`${s}.${t}`,{...o,carriesBody:!0,...i===void 0?{}:{endsWait:i}}]));return{name:s,events:{created:{level:4},read:{level:1},watched:{level:1},deleted:{level:5},configured:{level:1},...a},addressable:"name",receiverFor:b,read(t,i,o,p){u(t,i,o,p.reposFn);const e=m(t,"SELECT description, summary, state_json, published_at, receiver_json, dropped FROM custom_objects WHERE object = ?").get(o.rowid),n=e?.receiver_json==null?null:JSON.parse(e.receiver_json),r={object:j(t,o),description:e?.description??"",summary:e?.summary??null,state:e?.state_json==null?null:JSON.parse(e.state_json),published_at:e?.published_at??null,receiver:typeof n=="string"?n:n&&typeof n=="object"?Object.keys(n)[0]:null,dropped:e?.dropped??0};return{data:r,text:`${v("object",r.object)}
1
+ var l=Object.defineProperty;var c=(s,a)=>l(s,"name",{value:a,configurable:!0});import{recordLiveRead as u}from"./kind.js";import{header as m}from"./render.js";import{objectDTO as v}from"./dto.js";import{receiverForObject as j}from"../receivers.js";function $(s,a){const d=Object.fromEntries(Object.entries(a).map(([t,{ends_wait:i,...o}])=>[`${s}.${t}`,{...o,carriesBody:!0,...i===void 0?{}:{endsWait:i}}]));return{name:s,events:{created:{level:4},read:{level:1},watched:{level:1},deleted:{level:5},configured:{level:1},...d},addressable:"name",receiverFor:j,async read(t,i,o,p){await u(t,i,o,p.reposFn);const e=await t.prepare("SELECT description, summary, state_json, published_at, receiver_json, dropped FROM custom_objects WHERE object = ?").get(o.rowid),n=e?.receiver_json==null?null:JSON.parse(e.receiver_json),r={object:await v(t,o),description:e?.description??"",summary:e?.summary??null,state:e?.state_json==null?null:JSON.parse(e.state_json),published_at:e?.published_at??null,receiver:typeof n=="string"?n:n&&typeof n=="object"?Object.keys(n)[0]:null,dropped:e?.dropped??0};return{data:r,text:`${m("object",r.object)}
2
2
  Description: ${r.description}
3
3
  Summary: ${r.summary??""}
4
4
  State: ${JSON.stringify(r.state)}
5
5
  Published: ${r.published_at??"never"}
6
6
  Receiver: ${r.receiver??"none"}
7
- Dropped: ${r.dropped}`}}}}d(S,"customKind");export{S as customKind};
7
+ Dropped: ${r.dropped}`}}}}c($,"customKind");export{$ as customKind};
@@ -1,3 +1,4 @@
1
+ /** The document kind: markdown with revisions — its catalog (edits supersede and merge), its list fields and its render. */
1
2
  import type { DocFieldsDTO, ObjectDTO } from '../../../api/dto/objects.js';
2
3
  import { type ObjectKind } from './kind.js';
3
4
  export interface DocumentReadData {
@@ -1,5 +1,5 @@
1
- var y=Object.defineProperty;var m=(e,t)=>y(e,"name",{value:t,configurable:!0});import{prepared as _}from"../../sqlite-statements.js";import{recordMemoryReadsIn as v}from"../../canvas/memory-reads.js";import{deliveryDocOf as x,nodeSubject as S,ownerHandle as $}from"../../substrate/delivery/corpus.js";import{recordContentDelivery as D}from"../../substrate/delivery/deliver.js";import{renderExplicitRead as R}from"../../substrate/delivery/render-event.js";import{canRead as N}from"../access.js";import{documentRecord as j,readDocument as k}from"../documents.js";import{loadLedger as E,saveLedger as O}from"../exposures.js";import{getByRowid as A}from"../objects.js";import{rulesOf as h}from"../rules.js";import{objectDTO as d}from"./dto.js";import{withBase as L}from"./kind.js";import{attr as l,header as I,section as M}from"./render.js";function b(e,t,n){const r=`${n.name}/`;return _(e,`SELECT * FROM objects WHERE type = 'document' AND deleted_at IS NULL AND home_machine IS NULL AND owner IS ?
2
- AND substr(name, 1, ?) = ? ORDER BY name`).all(n.owner,r.length,r).filter(s=>!s.name.slice(r.length).includes("/")&&N(e,t,s)).map(s=>d(e,s))}m(b,"listingOf");function B(e,t,n){const r=t.class==="node",o=r?E(e,t.node.rowid):{node:0,preferenceSnapshot:null,objects:new Map,listed:new Map},s={db:e,reader:t,subject:r?S(e,t):null,ledger:o,channel:"transcript"},a=R(s,x(e,t,n));return r&&(D(e,t,a.delivered),O(e,o)),{attachments:a.attachments,linked:a.linked.map(u=>u.object)}}m(B,"explicitReadAttachments");function T(e,t,n){if(t.class!=="node"||n.kind!=="knowledge"&&n.kind!=="preference"||n.owner===null)return;const r=A(e,n.owner);r!==null&&v(e,t.node.id,[{name:n.name,scope:$(r),at:new Date().toISOString(),type:"read"}])}m(T,"recordExplicitMemoryRead");function W(e,t){const n=[];if(t.attachments&&n.push(t.attachments,""),n.push(I("object",e,l("privacy",e.privacy)+l("revision",t.revision))),n.push(`Preview: ${e.preview}`),t.summary&&n.push(`Summary: ${t.summary}`),t.fields!==void 0&&n.push(`<fields>
1
+ var _=Object.defineProperty;var m=(e,t)=>_(e,"name",{value:t,configurable:!0});import{recordMemoryReadsIn as v}from"../../canvas/memory-reads.js";import{deliveryDocOf as x,nodeSubject as $,ownerHandle as D}from"../../substrate/delivery/corpus.js";import{recordContentDelivery as R}from"../../substrate/delivery/deliver.js";import{renderExplicitRead as S}from"../../substrate/delivery/render-event.js";import{canRead as N}from"../access.js";import{documentRecord as j,readDocument as k}from"../documents.js";import{loadLedger as A,saveLedger as E}from"../exposures.js";import{getByRowid as O}from"../objects.js";import{rulesOf as h}from"../rules.js";import{objectDTO as d}from"./dto.js";import{withBase as L}from"./kind.js";import{attr as l,header as I,section as M}from"./render.js";import{filterAsync as b,mapAsync as p}from"../../async-array.js";async function B(e,t,n){const i=`${n.name}/`,s=await e.prepare(`SELECT * FROM objects WHERE type = 'document' AND deleted_at IS NULL AND home_machine IS NULL AND owner IS ?
2
+ AND substr(name, 1, ?) = ? ORDER BY name`).all(n.owner,i.length,i);return await p(await b(s,async r=>!r.name.slice(i.length).includes("/")&&await N(e,t,r)),async r=>await d(e,r))}m(B,"listingOf");async function T(e,t,n){const i=t.class==="node",s=i?await A(e,t.node.rowid):{node:0,preferenceSnapshot:null,objects:new Map,listed:new Map},r={db:e,reader:t,subject:i?await $(e,t):null,ledger:s,channel:"transcript"},o=await S(r,await x(e,t,n));return i&&(await R(e,t,o.delivered),await E(e,s)),{attachments:o.attachments,linked:o.linked.map(c=>c.object)}}m(T,"explicitReadAttachments");async function W(e,t,n){if(t.class!=="node"||n.kind!=="knowledge"&&n.kind!=="preference"||n.owner===null)return;const i=await O(e,n.owner);i!==null&&await v(e,t.node.id,[{name:n.name,scope:D(i),at:new Date().toISOString(),type:"read"}])}m(W,"recordExplicitMemoryRead");function C(e,t){const n=[];if(t.attachments&&n.push(t.attachments,""),n.push(I("object",e,l("privacy",e.privacy)+l("revision",t.revision))),n.push(`Preview: ${e.preview}`),t.summary&&n.push(`Summary: ${t.summary}`),t.fields!==void 0&&n.push(`<fields>
3
3
  ${JSON.stringify(t.fields,null,2)}
4
- </fields>`),t.needs_merge?(t.heads.forEach((r,o)=>{n.push(`<head${l("rev",r.rev_id)}${l("number",r.number)}${l("author",r.author_id)}>`,t.bodies[o]??"","</head>")}),n.push(`This document has ${t.heads.length} heads. Your next \`crtr doc edit\` writes the merged body and joins them into one revision.`)):n.push("",t.bodies[0]??""),t.listing&&t.listing.length>0){const r=t.listing.some(a=>a.owner?.id===e.owner?.id&&a.name.startsWith(`${e.name}/`)),o=t.listing.some(a=>a.owner?.id!==e.owner?.id||!a.name.startsWith(`${e.name}/`)),s=r&&o?`Names under ${e.name}/ and documents it links to`:r?`Names under ${e.name}/`:"Documents it links to";n.push("",...M(s,t.listing))}return n.join(`
5
- `)}m(W,"render");function C(e){const t=e.attrs.revision,n=e.attrs.from_revision??(typeof t=="number"?t-1:null),r=e.attrs.rationale;return{...e.attrs,from_revision:n,revision:t,authors:e.actor?[e.actor.id]:[],rationales:typeof r=="string"?[r]:[]}}m(C,"editAttrs");const H=m((e,t)=>{const n=C(t);if(e===null)return n;const r=e.authors??[];return{...n,from_revision:e.from_revision??null,authors:[...r,...n.authors.filter(o=>!r.includes(o))],rationales:[...e.rationales??[],...n.rationales]}},"mergeEdits"),te={name:"document",addressable:"name",events:L({edited:{level:8,supersedes:!0,merge:H},deleted:{level:8}}),listItem(e,t){return{summary:j(e,t).summary??null,rules:h(e,t).length}},read(e,t,n,r){const o=k(e,t,n,r.reposFn);T(e,t,n);const s=o.record,a=b(e,t,n),{attachments:u,linked:p}=B(e,t,n),g=new Set(a.map(i=>i.id)),f=[...a,...p.filter(i=>!g.has(i.id)).map(i=>d(e,i))],c={summary:s.summary??null,revision:s.revision,heads:o.heads.map(i=>({rev_id:i.rev_id,number:i.number,author_id:i.author,created_at:i.created_at})),bodies:o.heads.map(i=>i.body),needs_merge:o.needsMerge,...f.length>0?{listing:f}:{},...u===""?{}:{attachments:u}};return r.fields&&(c.fields={why_it_exists:s.why_it_exists??null,unlisted:s.unlisted,lint_ignore:s.lint_ignore??[],extensions:s.extensions??{},rules:h(e,n).map(({matchFrontmatter:i,...w})=>({...w,...i===void 0?{}:{match_frontmatter:i}}))}),{data:c,text:W(d(e,n),c)}}};export{te as documentKind};
4
+ </fields>`),t.needs_merge?(t.heads.forEach((i,s)=>{n.push(`<head${l("rev",i.rev_id)}${l("number",i.number)}${l("author",i.author_id)}>`,t.bodies[s]??"","</head>")}),n.push(`This document has ${t.heads.length} heads. Your next \`crtr doc edit\` writes the merged body and joins them into one revision.`)):n.push("",t.bodies[0]??""),t.listing&&t.listing.length>0){const i=t.listing.some(o=>o.owner?.id===e.owner?.id&&o.name.startsWith(`${e.name}/`)),s=t.listing.some(o=>o.owner?.id!==e.owner?.id||!o.name.startsWith(`${e.name}/`)),r=i&&s?`Names under ${e.name}/ and documents it links to`:i?`Names under ${e.name}/`:"Documents it links to";n.push("",...M(r,t.listing))}return n.join(`
5
+ `)}m(C,"render");function H(e){const t=e.attrs.revision,n=e.attrs.from_revision??(typeof t=="number"?t-1:null),i=e.attrs.rationale;return{...e.attrs,from_revision:n,revision:t,authors:e.actor?[e.actor.id]:[],rationales:typeof i=="string"?[i]:[]}}m(H,"editAttrs");const U=m((e,t)=>{const n=H(t);if(e===null)return n;const i=e.authors??[];return{...n,from_revision:e.from_revision??null,authors:[...i,...n.authors.filter(s=>!i.includes(s))],rationales:[...e.rationales??[],...n.rationales]}},"mergeEdits"),ne={name:"document",addressable:"name",events:L({edited:{level:8,supersedes:!0,merge:U},deleted:{level:8}}),async listItem(e,t){return{summary:(await j(e,t)).summary??null,rules:(await h(e,t)).length}},async read(e,t,n,i){const s=await k(e,t,n,i.reposFn);await W(e,t,n);const r=s.record,o=await B(e,t,n),{attachments:c,linked:w}=await T(e,t,n),y=new Set(o.map(a=>a.id)),f=[...o,...await p(w.filter(a=>!y.has(a.id)),async a=>await d(e,a))],u={summary:r.summary??null,revision:r.revision,heads:s.heads.map(a=>({rev_id:a.rev_id,number:a.number,author_id:a.author,created_at:a.created_at})),bodies:s.heads.map(a=>a.body),needs_merge:s.needsMerge,...f.length>0?{listing:f}:{},...c===""?{}:{attachments:c}};return i.fields&&(u.fields={why_it_exists:r.why_it_exists??null,unlisted:r.unlisted,lint_ignore:r.lint_ignore??[],extensions:r.extensions??{},rules:(await h(e,n)).map(({matchFrontmatter:a,...g})=>({...g,...a===void 0?{}:{match_frontmatter:a}}))}),{data:u,text:C(await d(e,n),u)}}};export{ne as documentKind};
@@ -1,5 +1,5 @@
1
1
  /** An object row as the `/v1/objects` wire shape. */
2
- import type { DatabaseSync } from 'node:sqlite';
3
2
  import type { ObjectDTO } from '../../../api/dto/objects.js';
4
3
  import type { ObjectRow } from '../types.js';
5
- export declare function objectDTO(db: DatabaseSync, o: ObjectRow): ObjectDTO;
4
+ import type { CanvasDb } from '../../canvas/db.js';
5
+ export declare function objectDTO(db: CanvasDb, o: ObjectRow): Promise<ObjectDTO>;
@@ -1 +1 @@
1
- var i=Object.defineProperty;var d=(n,e)=>i(n,"name",{value:e,configurable:!0});import{getByRowid as a}from"../objects.js";function c(n,e){const t=e.owner===null?null:a(n,e.owner),r=t?{id:t.id,type:t.type,handle:t.type==="node"?t.id:t.name}:null;return{id:e.id,type:e.type,kind:e.kind,owner:r,privacy:e.privacy,name:e.name,preview:e.preview??"",created_at:e.created_at,deleted_at:e.deleted_at}}d(c,"objectDTO");export{c as objectDTO};
1
+ var a=Object.defineProperty;var d=(n,e)=>a(n,"name",{value:e,configurable:!0});import{getByRowid as i}from"../objects.js";async function l(n,e){const t=e.owner===null?null:await i(n,e.owner),r=t?{id:t.id,type:t.type,handle:t.type==="node"?t.id:t.name}:null;return{id:e.id,type:e.type,kind:e.kind,owner:r,privacy:e.privacy,name:e.name,preview:e.preview??"",created_at:e.created_at,deleted_at:e.deleted_at}}d(l,"objectDTO");export{l as objectDTO};
@@ -1,2 +1,2 @@
1
- import{jobRow as m}from"../jobs.js";import{objectDTO as c}from"./dto.js";import{recordLiveRead as l,withBase as p}from"./kind.js";import{attr as a,header as h}from"./render.js";const f={name:"job",addressable:"id",events:p({exited:{level:7},killed:{level:7}}),read(r,s,e,d){const o=m(r,e);if(!o)throw new Error(`job object ${e.id} has no jobs row`);l(r,s,e,d.reposFn);const n=c(r,e),t={command:o.command,status:o.status,exit_code:o.exit_code,log_path:o.log_path},i=[h("object",n,a("status",t.status)+a("exit_code",t.exit_code)),`Command: ${t.command}`,`Log: ${t.log_path}`].join(`
2
- `);return{data:t,text:i}}};export{f as jobKind};
1
+ import{jobRow as c}from"../jobs.js";import{objectDTO as m}from"./dto.js";import{recordLiveRead as l,withBase as p}from"./kind.js";import{attr as r,header as w}from"./render.js";const f={name:"job",addressable:"id",events:p({exited:{level:7},killed:{level:7}}),async read(a,s,e,i){const o=await c(a,e);if(!o)throw new Error(`job object ${e.id} has no jobs row`);await l(a,s,e,i.reposFn);const n=await m(a,e),t={command:o.command,status:o.status,exit_code:o.exit_code,log_path:o.log_path},d=[w("object",n,r("status",t.status)+r("exit_code",t.exit_code)),`Command: ${t.command}`,`Log: ${t.log_path}`].join(`
2
+ `);return{data:t,text:d}}};export{f as jobKind};