@aphexcms/cms-core 9.6.0 → 9.8.0

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 (491) hide show
  1. package/dist/agent-chat-state.svelte.d.ts +38 -0
  2. package/dist/agent-chat-state.svelte.d.ts.map +1 -0
  3. package/dist/agent-chat-state.svelte.js +86 -0
  4. package/dist/ai/content-workspace-tools.d.ts +3 -0
  5. package/dist/ai/content-workspace-tools.d.ts.map +1 -0
  6. package/dist/ai/content-workspace-tools.js +50 -0
  7. package/dist/ai/default-system-prompt.d.ts +2 -0
  8. package/dist/ai/default-system-prompt.d.ts.map +1 -0
  9. package/dist/ai/default-system-prompt.js +15 -0
  10. package/dist/ai/index.d.ts +2 -0
  11. package/dist/ai/index.d.ts.map +1 -0
  12. package/dist/ai/index.js +4 -0
  13. package/dist/ai/interfaces/ai-provider.d.ts +67 -0
  14. package/dist/ai/interfaces/ai-provider.d.ts.map +1 -0
  15. package/dist/ai/interfaces/ai-provider.js +16 -0
  16. package/dist/ai/run-agent-turn.d.ts +29 -0
  17. package/dist/ai/run-agent-turn.d.ts.map +1 -0
  18. package/dist/ai/run-agent-turn.js +166 -0
  19. package/dist/api/agent-chat.d.ts +27 -0
  20. package/dist/api/agent-chat.d.ts.map +1 -0
  21. package/dist/api/agent-chat.js +64 -0
  22. package/dist/api/documents.d.ts +36 -3
  23. package/dist/api/documents.d.ts.map +1 -1
  24. package/dist/api/documents.js +24 -6
  25. package/dist/api/schemas/agent-chat.d.ts +45 -0
  26. package/dist/api/schemas/agent-chat.d.ts.map +1 -0
  27. package/dist/api/schemas/agent-chat.js +35 -0
  28. package/dist/api/schemas/agent-operations.d.ts +13 -0
  29. package/dist/api/schemas/agent-operations.d.ts.map +1 -0
  30. package/dist/api/schemas/agent-operations.js +15 -0
  31. package/dist/api/schemas/documents.d.ts +41 -0
  32. package/dist/api/schemas/documents.d.ts.map +1 -1
  33. package/dist/api/schemas/documents.js +38 -2
  34. package/dist/chunk-recovery.d.ts +33 -0
  35. package/dist/chunk-recovery.d.ts.map +1 -0
  36. package/dist/chunk-recovery.js +131 -0
  37. package/dist/client/index.d.ts +1 -0
  38. package/dist/client/index.d.ts.map +1 -1
  39. package/dist/client/index.js +1 -0
  40. package/dist/client/ui.d.ts +2 -0
  41. package/dist/client/ui.d.ts.map +1 -1
  42. package/dist/client/ui.js +3 -0
  43. package/dist/components/AdminApp.svelte +37 -3
  44. package/dist/components/AdminApp.svelte.d.ts.map +1 -1
  45. package/dist/components/admin/ActivityView.svelte +436 -0
  46. package/dist/components/admin/ActivityView.svelte.d.ts +4 -0
  47. package/dist/components/admin/ActivityView.svelte.d.ts.map +1 -0
  48. package/dist/components/admin/AgentChat.svelte +977 -0
  49. package/dist/components/admin/AgentChat.svelte.d.ts +17 -0
  50. package/dist/components/admin/AgentChat.svelte.d.ts.map +1 -0
  51. package/dist/components/admin/DocumentEditor.svelte +469 -70
  52. package/dist/components/admin/DocumentEditor.svelte.d.ts +6 -0
  53. package/dist/components/admin/DocumentEditor.svelte.d.ts.map +1 -1
  54. package/dist/components/admin/ObjectModal.svelte +4 -2
  55. package/dist/components/admin/ScheduleDialog.svelte +174 -0
  56. package/dist/components/admin/ScheduleDialog.svelte.d.ts +20 -0
  57. package/dist/components/admin/ScheduleDialog.svelte.d.ts.map +1 -0
  58. package/dist/components/admin/fields/ArrayField.svelte +4 -1
  59. package/dist/components/admin/fields/ReferenceField.svelte +12 -1
  60. package/dist/components/admin/fields/ReferenceField.svelte.d.ts.map +1 -1
  61. package/dist/components/index.d.ts +1 -0
  62. package/dist/components/index.d.ts.map +1 -1
  63. package/dist/components/index.js +1 -0
  64. package/dist/components/layout/OrganizationSwitcher.svelte +3 -3
  65. package/dist/components/layout/Sidebar.svelte +26 -2
  66. package/dist/components/layout/Sidebar.svelte.d.ts +1 -0
  67. package/dist/components/layout/Sidebar.svelte.d.ts.map +1 -1
  68. package/dist/components/layout/sidebar/NavUser.svelte +5 -5
  69. package/dist/db/interfaces/agent-change-sets.d.ts +17 -0
  70. package/dist/db/interfaces/agent-change-sets.d.ts.map +1 -0
  71. package/dist/db/interfaces/agent-change-sets.js +1 -0
  72. package/dist/db/interfaces/document.d.ts +25 -3
  73. package/dist/db/interfaces/document.d.ts.map +1 -1
  74. package/dist/db/interfaces/document.js +19 -1
  75. package/dist/db/interfaces/events.d.ts +55 -0
  76. package/dist/db/interfaces/events.d.ts.map +1 -0
  77. package/dist/db/interfaces/events.js +1 -0
  78. package/dist/db/interfaces/index.d.ts +13 -2
  79. package/dist/db/interfaces/index.d.ts.map +1 -1
  80. package/dist/db/interfaces/index.js +1 -1
  81. package/dist/db/interfaces/plugin-storage.d.ts +39 -0
  82. package/dist/db/interfaces/plugin-storage.d.ts.map +1 -0
  83. package/dist/db/interfaces/plugin-storage.js +1 -0
  84. package/dist/document-refresh.svelte.d.ts +2 -0
  85. package/dist/document-refresh.svelte.d.ts.map +1 -1
  86. package/dist/document-refresh.svelte.js +15 -0
  87. package/dist/document-workspace-registry.svelte.d.ts +15 -0
  88. package/dist/document-workspace-registry.svelte.d.ts.map +1 -0
  89. package/dist/document-workspace-registry.svelte.js +30 -0
  90. package/dist/events/catalog.d.ts +8 -0
  91. package/dist/events/catalog.d.ts.map +1 -0
  92. package/dist/events/catalog.js +11 -0
  93. package/dist/events/consumer.d.ts +79 -0
  94. package/dist/events/consumer.d.ts.map +1 -0
  95. package/dist/events/consumer.js +76 -0
  96. package/dist/events/define-event.d.ts +17 -0
  97. package/dist/events/define-event.d.ts.map +1 -0
  98. package/dist/events/define-event.js +7 -0
  99. package/dist/events/emit.d.ts +11 -0
  100. package/dist/events/emit.d.ts.map +1 -0
  101. package/dist/events/emit.js +20 -0
  102. package/dist/events/index.d.ts +4 -0
  103. package/dist/events/index.d.ts.map +1 -0
  104. package/dist/events/index.js +3 -0
  105. package/dist/field-validation/rule.d.ts.map +1 -1
  106. package/dist/field-validation/rule.js +15 -0
  107. package/dist/field-validation/utils.d.ts.map +1 -1
  108. package/dist/field-validation/utils.js +211 -29
  109. package/dist/forms/define-form.d.ts +25 -0
  110. package/dist/forms/define-form.d.ts.map +1 -0
  111. package/dist/forms/define-form.js +22 -0
  112. package/dist/forms/index.d.ts +4 -0
  113. package/dist/forms/index.d.ts.map +1 -0
  114. package/dist/forms/index.js +5 -0
  115. package/dist/forms/types.d.ts +49 -0
  116. package/dist/forms/types.d.ts.map +1 -0
  117. package/dist/forms/types.js +1 -0
  118. package/dist/forms/validate.d.ts +9 -0
  119. package/dist/forms/validate.d.ts.map +1 -0
  120. package/dist/forms/validate.js +18 -0
  121. package/dist/hooks.d.ts +2 -0
  122. package/dist/hooks.d.ts.map +1 -1
  123. package/dist/hooks.js +17 -0
  124. package/dist/index.d.ts +2 -0
  125. package/dist/index.d.ts.map +1 -1
  126. package/dist/index.js +6 -0
  127. package/dist/jobs/document-jobs.d.ts +27 -0
  128. package/dist/jobs/document-jobs.d.ts.map +1 -0
  129. package/dist/jobs/document-jobs.js +42 -0
  130. package/dist/jobs/embedded-runner.d.ts +25 -0
  131. package/dist/jobs/embedded-runner.d.ts.map +1 -0
  132. package/dist/jobs/embedded-runner.js +46 -0
  133. package/dist/jobs/index.d.ts +7 -0
  134. package/dist/jobs/index.d.ts.map +1 -0
  135. package/dist/jobs/index.js +8 -0
  136. package/dist/jobs/relay.d.ts +27 -0
  137. package/dist/jobs/relay.d.ts.map +1 -0
  138. package/dist/jobs/relay.js +60 -0
  139. package/dist/jobs/run-batch.d.ts +52 -0
  140. package/dist/jobs/run-batch.d.ts.map +1 -0
  141. package/dist/jobs/run-batch.js +61 -0
  142. package/dist/jobs/run-due-jobs.d.ts +30 -0
  143. package/dist/jobs/run-due-jobs.d.ts.map +1 -0
  144. package/dist/jobs/run-due-jobs.js +69 -0
  145. package/dist/jobs/types.d.ts +18 -0
  146. package/dist/jobs/types.d.ts.map +1 -0
  147. package/dist/jobs/types.js +1 -0
  148. package/dist/lib/agent-chat-state.svelte.d.ts +38 -0
  149. package/dist/lib/agent-chat-state.svelte.d.ts.map +1 -0
  150. package/dist/lib/agent-chat-state.svelte.js +87 -0
  151. package/dist/lib/agent-chat-state.svelte.js.map +1 -0
  152. package/dist/lib/ai/content-workspace-tools.d.ts +3 -0
  153. package/dist/lib/ai/content-workspace-tools.d.ts.map +1 -0
  154. package/dist/lib/ai/content-workspace-tools.js +51 -0
  155. package/dist/lib/ai/content-workspace-tools.js.map +1 -0
  156. package/dist/lib/ai/default-system-prompt.d.ts +2 -0
  157. package/dist/lib/ai/default-system-prompt.d.ts.map +1 -0
  158. package/dist/lib/ai/default-system-prompt.js +16 -0
  159. package/dist/lib/ai/default-system-prompt.js.map +1 -0
  160. package/dist/lib/ai/index.d.ts +2 -0
  161. package/dist/lib/ai/index.d.ts.map +1 -0
  162. package/dist/lib/ai/index.js +5 -0
  163. package/dist/lib/ai/index.js.map +1 -0
  164. package/dist/lib/ai/interfaces/ai-provider.d.ts +67 -0
  165. package/dist/lib/ai/interfaces/ai-provider.d.ts.map +1 -0
  166. package/dist/lib/ai/interfaces/ai-provider.js +17 -0
  167. package/dist/lib/ai/interfaces/ai-provider.js.map +1 -0
  168. package/dist/lib/ai/run-agent-turn.d.ts +29 -0
  169. package/dist/lib/ai/run-agent-turn.d.ts.map +1 -0
  170. package/dist/lib/ai/run-agent-turn.js +167 -0
  171. package/dist/lib/ai/run-agent-turn.js.map +1 -0
  172. package/dist/lib/api/agent-chat.d.ts +27 -0
  173. package/dist/lib/api/agent-chat.d.ts.map +1 -0
  174. package/dist/lib/api/agent-chat.js +65 -0
  175. package/dist/lib/api/agent-chat.js.map +1 -0
  176. package/dist/lib/api/documents.d.ts +36 -3
  177. package/dist/lib/api/documents.d.ts.map +1 -1
  178. package/dist/lib/api/documents.js +24 -6
  179. package/dist/lib/api/documents.js.map +1 -1
  180. package/dist/lib/api/schemas/agent-chat.d.ts +45 -0
  181. package/dist/lib/api/schemas/agent-chat.d.ts.map +1 -0
  182. package/dist/lib/api/schemas/agent-chat.js +36 -0
  183. package/dist/lib/api/schemas/agent-chat.js.map +1 -0
  184. package/dist/lib/api/schemas/agent-operations.d.ts +13 -0
  185. package/dist/lib/api/schemas/agent-operations.d.ts.map +1 -0
  186. package/dist/lib/api/schemas/agent-operations.js +16 -0
  187. package/dist/lib/api/schemas/agent-operations.js.map +1 -0
  188. package/dist/lib/api/schemas/documents.d.ts +41 -0
  189. package/dist/lib/api/schemas/documents.d.ts.map +1 -1
  190. package/dist/lib/api/schemas/documents.js +38 -2
  191. package/dist/lib/api/schemas/documents.js.map +1 -1
  192. package/dist/lib/chunk-recovery.d.ts +33 -0
  193. package/dist/lib/chunk-recovery.d.ts.map +1 -0
  194. package/dist/lib/chunk-recovery.js +132 -0
  195. package/dist/lib/chunk-recovery.js.map +1 -0
  196. package/dist/lib/client/index.d.ts +1 -0
  197. package/dist/lib/client/index.d.ts.map +1 -1
  198. package/dist/lib/client/index.js +1 -0
  199. package/dist/lib/client/index.js.map +1 -1
  200. package/dist/lib/client/ui.d.ts +2 -0
  201. package/dist/lib/client/ui.d.ts.map +1 -1
  202. package/dist/lib/client/ui.js +3 -0
  203. package/dist/lib/client/ui.js.map +1 -1
  204. package/dist/lib/components/index.d.ts +1 -0
  205. package/dist/lib/components/index.d.ts.map +1 -1
  206. package/dist/lib/components/index.js +1 -0
  207. package/dist/lib/components/index.js.map +1 -1
  208. package/dist/lib/db/interfaces/agent-change-sets.d.ts +17 -0
  209. package/dist/lib/db/interfaces/agent-change-sets.d.ts.map +1 -0
  210. package/dist/lib/db/interfaces/agent-change-sets.js +2 -0
  211. package/dist/lib/db/interfaces/agent-change-sets.js.map +1 -0
  212. package/dist/lib/db/interfaces/document.d.ts +25 -3
  213. package/dist/lib/db/interfaces/document.d.ts.map +1 -1
  214. package/dist/lib/db/interfaces/document.js +19 -1
  215. package/dist/lib/db/interfaces/document.js.map +1 -1
  216. package/dist/lib/db/interfaces/events.d.ts +55 -0
  217. package/dist/lib/db/interfaces/events.d.ts.map +1 -0
  218. package/dist/lib/db/interfaces/events.js +2 -0
  219. package/dist/lib/db/interfaces/events.js.map +1 -0
  220. package/dist/lib/db/interfaces/index.d.ts +13 -2
  221. package/dist/lib/db/interfaces/index.d.ts.map +1 -1
  222. package/dist/lib/db/interfaces/index.js +1 -1
  223. package/dist/lib/db/interfaces/index.js.map +1 -1
  224. package/dist/lib/db/interfaces/plugin-storage.d.ts +39 -0
  225. package/dist/lib/db/interfaces/plugin-storage.d.ts.map +1 -0
  226. package/dist/lib/db/interfaces/plugin-storage.js +2 -0
  227. package/dist/lib/db/interfaces/plugin-storage.js.map +1 -0
  228. package/dist/lib/document-refresh.svelte.d.ts +2 -0
  229. package/dist/lib/document-refresh.svelte.d.ts.map +1 -1
  230. package/dist/lib/document-refresh.svelte.js +15 -0
  231. package/dist/lib/document-refresh.svelte.js.map +1 -1
  232. package/dist/lib/document-workspace-registry.svelte.d.ts +15 -0
  233. package/dist/lib/document-workspace-registry.svelte.d.ts.map +1 -0
  234. package/dist/lib/document-workspace-registry.svelte.js +31 -0
  235. package/dist/lib/document-workspace-registry.svelte.js.map +1 -0
  236. package/dist/lib/events/catalog.d.ts +8 -0
  237. package/dist/lib/events/catalog.d.ts.map +1 -0
  238. package/dist/lib/events/catalog.js +12 -0
  239. package/dist/lib/events/catalog.js.map +1 -0
  240. package/dist/lib/events/consumer.d.ts +79 -0
  241. package/dist/lib/events/consumer.d.ts.map +1 -0
  242. package/dist/lib/events/consumer.js +77 -0
  243. package/dist/lib/events/consumer.js.map +1 -0
  244. package/dist/lib/events/define-event.d.ts +17 -0
  245. package/dist/lib/events/define-event.d.ts.map +1 -0
  246. package/dist/lib/events/define-event.js +8 -0
  247. package/dist/lib/events/define-event.js.map +1 -0
  248. package/dist/lib/events/emit.d.ts +11 -0
  249. package/dist/lib/events/emit.d.ts.map +1 -0
  250. package/dist/lib/events/emit.js +21 -0
  251. package/dist/lib/events/emit.js.map +1 -0
  252. package/dist/lib/events/index.d.ts +4 -0
  253. package/dist/lib/events/index.d.ts.map +1 -0
  254. package/dist/lib/events/index.js +4 -0
  255. package/dist/lib/events/index.js.map +1 -0
  256. package/dist/lib/field-validation/rule.d.ts.map +1 -1
  257. package/dist/lib/field-validation/rule.js +15 -0
  258. package/dist/lib/field-validation/rule.js.map +1 -1
  259. package/dist/lib/field-validation/utils.d.ts.map +1 -1
  260. package/dist/lib/field-validation/utils.js +211 -29
  261. package/dist/lib/field-validation/utils.js.map +1 -1
  262. package/dist/lib/forms/define-form.d.ts +25 -0
  263. package/dist/lib/forms/define-form.d.ts.map +1 -0
  264. package/dist/lib/forms/define-form.js +23 -0
  265. package/dist/lib/forms/define-form.js.map +1 -0
  266. package/dist/lib/forms/index.d.ts +4 -0
  267. package/dist/lib/forms/index.d.ts.map +1 -0
  268. package/dist/lib/forms/index.js +6 -0
  269. package/dist/lib/forms/index.js.map +1 -0
  270. package/dist/lib/forms/types.d.ts +49 -0
  271. package/dist/lib/forms/types.d.ts.map +1 -0
  272. package/dist/lib/forms/types.js +2 -0
  273. package/dist/lib/forms/types.js.map +1 -0
  274. package/dist/lib/forms/validate.d.ts +9 -0
  275. package/dist/lib/forms/validate.d.ts.map +1 -0
  276. package/dist/lib/forms/validate.js +19 -0
  277. package/dist/lib/forms/validate.js.map +1 -0
  278. package/dist/lib/hooks.d.ts +2 -0
  279. package/dist/lib/hooks.d.ts.map +1 -1
  280. package/dist/lib/hooks.js +17 -0
  281. package/dist/lib/hooks.js.map +1 -1
  282. package/dist/lib/index.d.ts +2 -0
  283. package/dist/lib/index.d.ts.map +1 -1
  284. package/dist/lib/index.js +6 -0
  285. package/dist/lib/index.js.map +1 -1
  286. package/dist/lib/jobs/document-jobs.d.ts +27 -0
  287. package/dist/lib/jobs/document-jobs.d.ts.map +1 -0
  288. package/dist/lib/jobs/document-jobs.js +43 -0
  289. package/dist/lib/jobs/document-jobs.js.map +1 -0
  290. package/dist/lib/jobs/embedded-runner.d.ts +25 -0
  291. package/dist/lib/jobs/embedded-runner.d.ts.map +1 -0
  292. package/dist/lib/jobs/embedded-runner.js +47 -0
  293. package/dist/lib/jobs/embedded-runner.js.map +1 -0
  294. package/dist/lib/jobs/index.d.ts +7 -0
  295. package/dist/lib/jobs/index.d.ts.map +1 -0
  296. package/dist/lib/jobs/index.js +9 -0
  297. package/dist/lib/jobs/index.js.map +1 -0
  298. package/dist/lib/jobs/relay.d.ts +27 -0
  299. package/dist/lib/jobs/relay.d.ts.map +1 -0
  300. package/dist/lib/jobs/relay.js +61 -0
  301. package/dist/lib/jobs/relay.js.map +1 -0
  302. package/dist/lib/jobs/run-batch.d.ts +52 -0
  303. package/dist/lib/jobs/run-batch.d.ts.map +1 -0
  304. package/dist/lib/jobs/run-batch.js +62 -0
  305. package/dist/lib/jobs/run-batch.js.map +1 -0
  306. package/dist/lib/jobs/run-due-jobs.d.ts +30 -0
  307. package/dist/lib/jobs/run-due-jobs.d.ts.map +1 -0
  308. package/dist/lib/jobs/run-due-jobs.js +70 -0
  309. package/dist/lib/jobs/run-due-jobs.js.map +1 -0
  310. package/dist/lib/jobs/types.d.ts +18 -0
  311. package/dist/lib/jobs/types.d.ts.map +1 -0
  312. package/dist/lib/jobs/types.js +2 -0
  313. package/dist/lib/jobs/types.js.map +1 -0
  314. package/dist/lib/local-api/collection-api.d.ts +49 -2
  315. package/dist/lib/local-api/collection-api.d.ts.map +1 -1
  316. package/dist/lib/local-api/collection-api.js +193 -27
  317. package/dist/lib/local-api/collection-api.js.map +1 -1
  318. package/dist/lib/mcp/tools.d.ts +39 -4
  319. package/dist/lib/mcp/tools.d.ts.map +1 -1
  320. package/dist/lib/mcp/tools.js +546 -362
  321. package/dist/lib/mcp/tools.js.map +1 -1
  322. package/dist/lib/plugins/resolver.d.ts +19 -1
  323. package/dist/lib/plugins/resolver.d.ts.map +1 -1
  324. package/dist/lib/plugins/resolver.js +17 -1
  325. package/dist/lib/plugins/resolver.js.map +1 -1
  326. package/dist/lib/plugins/types.d.ts +68 -2
  327. package/dist/lib/plugins/types.d.ts.map +1 -1
  328. package/dist/lib/plugins/types.js.map +1 -1
  329. package/dist/lib/preview/stega.d.ts +2 -2
  330. package/dist/lib/preview/stega.d.ts.map +1 -1
  331. package/dist/lib/preview/stega.js +52 -29
  332. package/dist/lib/preview/stega.js.map +1 -1
  333. package/dist/lib/schema-utils/validator.d.ts.map +1 -1
  334. package/dist/lib/schema-utils/validator.js +5 -2
  335. package/dist/lib/schema-utils/validator.js.map +1 -1
  336. package/dist/lib/server/api/index.d.ts.map +1 -1
  337. package/dist/lib/server/api/index.js +16 -0
  338. package/dist/lib/server/api/index.js.map +1 -1
  339. package/dist/lib/server/api/routes/agent-change-sets.d.ts +4 -0
  340. package/dist/lib/server/api/routes/agent-change-sets.d.ts.map +1 -0
  341. package/dist/lib/server/api/routes/agent-change-sets.js +132 -0
  342. package/dist/lib/server/api/routes/agent-change-sets.js.map +1 -0
  343. package/dist/lib/server/api/routes/agent-chat.d.ts +14 -0
  344. package/dist/lib/server/api/routes/agent-chat.d.ts.map +1 -0
  345. package/dist/lib/server/api/routes/agent-chat.js +224 -0
  346. package/dist/lib/server/api/routes/agent-chat.js.map +1 -0
  347. package/dist/lib/server/api/routes/document-versions.d.ts.map +1 -1
  348. package/dist/lib/server/api/routes/document-versions.js +16 -2
  349. package/dist/lib/server/api/routes/document-versions.js.map +1 -1
  350. package/dist/lib/server/api/routes/documents-by-id.d.ts.map +1 -1
  351. package/dist/lib/server/api/routes/documents-by-id.js +11 -1
  352. package/dist/lib/server/api/routes/documents-by-id.js.map +1 -1
  353. package/dist/lib/server/api/routes/documents-publish.d.ts.map +1 -1
  354. package/dist/lib/server/api/routes/documents-publish.js +145 -2
  355. package/dist/lib/server/api/routes/documents-publish.js.map +1 -1
  356. package/dist/lib/server/api/routes/jobs.d.ts +4 -0
  357. package/dist/lib/server/api/routes/jobs.d.ts.map +1 -0
  358. package/dist/lib/server/api/routes/jobs.js +95 -0
  359. package/dist/lib/server/api/routes/jobs.js.map +1 -0
  360. package/dist/lib/server/api/routes/resolve-created-by.d.ts +13 -0
  361. package/dist/lib/server/api/routes/resolve-created-by.d.ts.map +1 -0
  362. package/dist/lib/server/api/routes/resolve-created-by.js +31 -0
  363. package/dist/lib/server/api/routes/resolve-created-by.js.map +1 -0
  364. package/dist/lib/server/api/routes/workers-run.d.ts +4 -0
  365. package/dist/lib/server/api/routes/workers-run.d.ts.map +1 -0
  366. package/dist/lib/server/api/routes/workers-run.js +41 -0
  367. package/dist/lib/server/api/routes/workers-run.js.map +1 -0
  368. package/dist/lib/server/index.d.ts +2 -0
  369. package/dist/lib/server/index.d.ts.map +1 -1
  370. package/dist/lib/server/index.js +3 -0
  371. package/dist/lib/server/index.js.map +1 -1
  372. package/dist/lib/services/version-service.d.ts +19 -3
  373. package/dist/lib/services/version-service.d.ts.map +1 -1
  374. package/dist/lib/services/version-service.js +75 -69
  375. package/dist/lib/services/version-service.js.map +1 -1
  376. package/dist/lib/type-gen.d.ts.map +1 -1
  377. package/dist/lib/type-gen.js +11 -0
  378. package/dist/lib/type-gen.js.map +1 -1
  379. package/dist/lib/types/agent-change-sets.d.ts +70 -0
  380. package/dist/lib/types/agent-change-sets.d.ts.map +1 -0
  381. package/dist/lib/types/agent-change-sets.js +7 -0
  382. package/dist/lib/types/agent-change-sets.js.map +1 -0
  383. package/dist/lib/types/agent-stream.d.ts +60 -0
  384. package/dist/lib/types/agent-stream.d.ts.map +1 -0
  385. package/dist/lib/types/agent-stream.js +12 -0
  386. package/dist/lib/types/agent-stream.js.map +1 -0
  387. package/dist/lib/types/agent-tools.d.ts +65 -0
  388. package/dist/lib/types/agent-tools.d.ts.map +1 -0
  389. package/dist/lib/types/agent-tools.js +2 -0
  390. package/dist/lib/types/agent-tools.js.map +1 -0
  391. package/dist/lib/types/config.d.ts +62 -0
  392. package/dist/lib/types/config.d.ts.map +1 -1
  393. package/dist/lib/types/document-workspace.d.ts +53 -0
  394. package/dist/lib/types/document-workspace.d.ts.map +1 -0
  395. package/dist/lib/types/document-workspace.js +15 -0
  396. package/dist/lib/types/document-workspace.js.map +1 -0
  397. package/dist/lib/types/document.d.ts +5 -0
  398. package/dist/lib/types/document.d.ts.map +1 -1
  399. package/dist/lib/types/events.d.ts +134 -0
  400. package/dist/lib/types/events.d.ts.map +1 -0
  401. package/dist/lib/types/events.js +4 -0
  402. package/dist/lib/types/events.js.map +1 -0
  403. package/dist/lib/types/index.d.ts +3 -0
  404. package/dist/lib/types/index.d.ts.map +1 -1
  405. package/dist/lib/types/index.js +3 -0
  406. package/dist/lib/types/index.js.map +1 -1
  407. package/dist/lib/types/schemas.js +1 -1
  408. package/dist/lib/types/schemas.js.map +1 -1
  409. package/dist/lib/utils/fetch-remote-file.d.ts +11 -0
  410. package/dist/lib/utils/fetch-remote-file.d.ts.map +1 -0
  411. package/dist/lib/utils/fetch-remote-file.js +169 -0
  412. package/dist/lib/utils/fetch-remote-file.js.map +1 -0
  413. package/dist/lib/utils/index.d.ts +1 -1
  414. package/dist/lib/utils/index.d.ts.map +1 -1
  415. package/dist/lib/utils/index.js.map +1 -1
  416. package/dist/local-api/collection-api.d.ts +49 -2
  417. package/dist/local-api/collection-api.d.ts.map +1 -1
  418. package/dist/local-api/collection-api.js +193 -27
  419. package/dist/mcp/tools.d.ts +39 -4
  420. package/dist/mcp/tools.d.ts.map +1 -1
  421. package/dist/mcp/tools.js +546 -362
  422. package/dist/plugins/resolver.d.ts +19 -1
  423. package/dist/plugins/resolver.d.ts.map +1 -1
  424. package/dist/plugins/resolver.js +17 -1
  425. package/dist/plugins/types.d.ts +68 -2
  426. package/dist/plugins/types.d.ts.map +1 -1
  427. package/dist/preview/stega.d.ts +2 -2
  428. package/dist/preview/stega.d.ts.map +1 -1
  429. package/dist/preview/stega.js +52 -29
  430. package/dist/schema-utils/validator.d.ts.map +1 -1
  431. package/dist/schema-utils/validator.js +5 -2
  432. package/dist/server/api/index.d.ts.map +1 -1
  433. package/dist/server/api/index.js +16 -0
  434. package/dist/server/api/routes/agent-change-sets.d.ts +4 -0
  435. package/dist/server/api/routes/agent-change-sets.d.ts.map +1 -0
  436. package/dist/server/api/routes/agent-change-sets.js +131 -0
  437. package/dist/server/api/routes/agent-chat.d.ts +14 -0
  438. package/dist/server/api/routes/agent-chat.d.ts.map +1 -0
  439. package/dist/server/api/routes/agent-chat.js +223 -0
  440. package/dist/server/api/routes/document-versions.d.ts.map +1 -1
  441. package/dist/server/api/routes/document-versions.js +16 -2
  442. package/dist/server/api/routes/documents-by-id.d.ts.map +1 -1
  443. package/dist/server/api/routes/documents-by-id.js +11 -1
  444. package/dist/server/api/routes/documents-publish.d.ts.map +1 -1
  445. package/dist/server/api/routes/documents-publish.js +145 -2
  446. package/dist/server/api/routes/jobs.d.ts +4 -0
  447. package/dist/server/api/routes/jobs.d.ts.map +1 -0
  448. package/dist/server/api/routes/jobs.js +94 -0
  449. package/dist/server/api/routes/resolve-created-by.d.ts +13 -0
  450. package/dist/server/api/routes/resolve-created-by.d.ts.map +1 -0
  451. package/dist/server/api/routes/resolve-created-by.js +30 -0
  452. package/dist/server/api/routes/workers-run.d.ts +4 -0
  453. package/dist/server/api/routes/workers-run.d.ts.map +1 -0
  454. package/dist/server/api/routes/workers-run.js +40 -0
  455. package/dist/server/index.d.ts +2 -0
  456. package/dist/server/index.d.ts.map +1 -1
  457. package/dist/server/index.js +3 -0
  458. package/dist/services/version-service.d.ts +19 -3
  459. package/dist/services/version-service.d.ts.map +1 -1
  460. package/dist/services/version-service.js +75 -69
  461. package/dist/type-gen.d.ts.map +1 -1
  462. package/dist/type-gen.js +11 -0
  463. package/dist/types/agent-change-sets.d.ts +70 -0
  464. package/dist/types/agent-change-sets.d.ts.map +1 -0
  465. package/dist/types/agent-change-sets.js +6 -0
  466. package/dist/types/agent-stream.d.ts +60 -0
  467. package/dist/types/agent-stream.d.ts.map +1 -0
  468. package/dist/types/agent-stream.js +11 -0
  469. package/dist/types/agent-tools.d.ts +65 -0
  470. package/dist/types/agent-tools.d.ts.map +1 -0
  471. package/dist/types/agent-tools.js +1 -0
  472. package/dist/types/config.d.ts +62 -0
  473. package/dist/types/config.d.ts.map +1 -1
  474. package/dist/types/document-workspace.d.ts +53 -0
  475. package/dist/types/document-workspace.d.ts.map +1 -0
  476. package/dist/types/document-workspace.js +14 -0
  477. package/dist/types/document.d.ts +5 -0
  478. package/dist/types/document.d.ts.map +1 -1
  479. package/dist/types/events.d.ts +134 -0
  480. package/dist/types/events.d.ts.map +1 -0
  481. package/dist/types/events.js +3 -0
  482. package/dist/types/index.d.ts +3 -0
  483. package/dist/types/index.d.ts.map +1 -1
  484. package/dist/types/index.js +3 -0
  485. package/dist/types/schemas.js +1 -1
  486. package/dist/utils/fetch-remote-file.d.ts +11 -0
  487. package/dist/utils/fetch-remote-file.d.ts.map +1 -0
  488. package/dist/utils/fetch-remote-file.js +168 -0
  489. package/dist/utils/index.d.ts +1 -1
  490. package/dist/utils/index.d.ts.map +1 -1
  491. package/package.json +5 -1
@@ -0,0 +1,223 @@
1
+ import { Hono } from 'hono';
2
+ import { streamSSE } from 'hono/streaming';
3
+ import { z } from 'zod';
4
+ import { agentChatRequest } from '../../../api/schemas/agent-chat.js';
5
+ import { recordWorkspaceOperationRequest } from '../../../api/schemas/agent-operations.js';
6
+ import { authToContext } from '../../../local-api/auth-helpers.js';
7
+ import { resolveAgentTools } from '../../../mcp/tools.js';
8
+ import { runAgentTurn } from '../../../ai/run-agent-turn.js';
9
+ import { DEFAULT_AGENT_SYSTEM_PROMPT } from '../../../ai/default-system-prompt.js';
10
+ import { cmsLogger } from '../../../utils/logger.js';
11
+ const SUMMARY_MAX_LENGTH = 200;
12
+ // A mutating tool's `data` is `unknown` at this boundary (AgentToolResult.data) — every tool
13
+ // returns a different shape (list_collections -> {collections}, upload_asset -> {asset, ...},
14
+ // document tools -> {document, validation}), and this route dispatches by name against
15
+ // whatever's registered, including plugin-contributed tools it's never seen at compile time.
16
+ // There's no static type to give it, so the id is pulled out via a runtime-validated parse
17
+ // (the same idiom `run-agent-turn.ts` already uses for tool arguments) rather than an `as`
18
+ // cast asserting a shape without checking it.
19
+ const toolResultWithDocumentId = z.object({ document: z.object({ id: z.string() }) });
20
+ /** `create_document` has no `id` argument (nothing to reference before it exists) — its new
21
+ * id only shows up in the result. Falls back to that when the args don't have one, so a
22
+ * create is still attributable to a document instead of being silently dropped. */
23
+ function resolveDocumentId(args, data) {
24
+ if (typeof args.id === 'string')
25
+ return args.id;
26
+ const parsed = toolResultWithDocumentId.safeParse(data);
27
+ return parsed.success ? parsed.data.document.id : null;
28
+ }
29
+ /**
30
+ * Best-effort audit record for one mutating tool call — looks up the two most recent
31
+ * document-version rows to capture `versionBefore`/`versionAfter` (the version an undo would
32
+ * restore to, and the one this write produced), then records the operation. Never throws: a
33
+ * failure to record the audit trail must never break the actual tool call or the SSE stream.
34
+ * Exported for unit testing — not part of the route's own public surface.
35
+ */
36
+ export async function recordMutatingOperation(aphexCMS, context, changeSetId, toolName, args, success, error, data) {
37
+ const collection = typeof args.collection === 'string' ? args.collection : null;
38
+ // `resolveDocumentId` checks `args.id` first, so a failed update_document/publish_document
39
+ // (which does have `args.id`) is still attributable — it only falls through to parsing
40
+ // `data` for the rare case for `create_document`, whose result won't parse on failure anyway.
41
+ const documentId = resolveDocumentId(args, data);
42
+ if (!collection || !documentId)
43
+ return;
44
+ try {
45
+ const { databaseAdapter, localAPI } = aphexCMS;
46
+ const { versions } = await localAPI.versionService.listVersions(databaseAdapter, context.organizationId, documentId, { limit: 2 });
47
+ const [versionAfter, versionBefore] = versions;
48
+ await databaseAdapter.recordOperation({
49
+ changeSetId,
50
+ organizationId: context.organizationId,
51
+ collection,
52
+ documentId,
53
+ toolName,
54
+ arguments: args,
55
+ success,
56
+ error,
57
+ versionBefore: versionBefore?.versionNumber ?? null,
58
+ versionAfter: versionAfter?.versionNumber ?? null
59
+ });
60
+ }
61
+ catch (err) {
62
+ cmsLogger.error('[agent-chat] failed to record agent operation (continuing):', err);
63
+ }
64
+ }
65
+ export const agentChatRouter = new Hono();
66
+ /**
67
+ * POST /api/agent/chat — the in-admin agent's streaming chat endpoint (Milestone 2 item 5
68
+ * of references/content-copilot-phase-1-plan.md). Stateless per call: the browser sends
69
+ * the full running conversation each time (conversation persistence is a separate,
70
+ * not-yet-built piece — see the plan). Requires an authenticated session; individual tool
71
+ * calls are separately capability-gated by `resolveAgentTools`/each tool's own checks —
72
+ * this endpoint is a dumb transport over the same tool-execution service MCP uses, not an
73
+ * additional authorization layer.
74
+ *
75
+ * 404s (rather than 401) when no `aiProvider` is configured, so the route doesn't exist as
76
+ * a surface at all on an instance that hasn't opted in — same "don't advertise an unset
77
+ * feature" posture as `workers-run.ts`'s worker secret gate.
78
+ *
79
+ * Also records an audit/undo trail (`cms_agent_change_sets`/`cms_agent_operations`): a
80
+ * change-set row is created eagerly for every turn (so token usage is captured even for a
81
+ * pure Q&A turn with no mutations), and every mutating tool call gets an operation row. All
82
+ * of this recording is best-effort — see `recordMutatingOperation` above and the try/catch
83
+ * around change-set creation/completion below — a failure here must never break the chat.
84
+ */
85
+ agentChatRouter.post('/chat', async (c) => {
86
+ const { aphexCMS, auth } = c.var;
87
+ const { aiProvider, agentModel } = aphexCMS.config;
88
+ const { databaseAdapter } = aphexCMS;
89
+ if (!aiProvider)
90
+ return c.json({ success: false, error: 'Not found' }, 404);
91
+ if (!auth)
92
+ return c.json({ success: false, error: 'Unauthorized' }, 401);
93
+ if (!agentModel) {
94
+ return c.json({ success: false, error: 'Server misconfigured: no agentModel configured for aiProvider' }, 501);
95
+ }
96
+ const body = await c.req.json().catch(() => null);
97
+ const parsed = agentChatRequest.safeParse(body);
98
+ if (!parsed.success) {
99
+ return c.json({ success: false, error: 'Invalid request', issues: parsed.error.issues }, 400);
100
+ }
101
+ const context = authToContext(auth);
102
+ const tools = resolveAgentTools({ aphexCMS, context }, { documentContext: parsed.data.documentContext });
103
+ const toolsByName = new Map(tools.map((t) => [t.definition.name, t]));
104
+ const model = parsed.data.model ?? agentModel;
105
+ const abortController = new AbortController();
106
+ // A turn paused for a workspace tool resumes as a brand-new HTTP request (see
107
+ // `types/agent-stream.ts`) — the client echoes back the change-set id from the leg that
108
+ // paused so every leg of one logical turn records against the same row, instead of a
109
+ // fresh `cms_agent_change_sets` row per leg.
110
+ let changeSetId = parsed.data.changeSetId ?? null;
111
+ if (!changeSetId) {
112
+ try {
113
+ const firstUserMessage = parsed.data.messages.find((m) => m.role === 'user')?.content ?? '';
114
+ const changeSet = await databaseAdapter.createChangeSet({
115
+ organizationId: context.organizationId,
116
+ createdBy: context.user?.id ?? null,
117
+ summary: firstUserMessage.slice(0, SUMMARY_MAX_LENGTH) || null,
118
+ provider: aiProvider.name,
119
+ model
120
+ });
121
+ changeSetId = changeSet.id;
122
+ }
123
+ catch (err) {
124
+ cmsLogger.error('[agent-chat] failed to create change-set (continuing without one):', err);
125
+ }
126
+ }
127
+ return streamSSE(c, async (stream) => {
128
+ c.req.raw.signal.addEventListener('abort', () => abortController.abort());
129
+ let promptTokens = parsed.data.priorUsage?.promptTokens ?? 0;
130
+ let completionTokens = parsed.data.priorUsage?.completionTokens ?? 0;
131
+ let turnFailed = false;
132
+ let turnPaused = false;
133
+ // toolCall args aren't repeated on the matching toolResult event, so stash them here
134
+ // to correlate the two when it's time to record a mutating operation.
135
+ const argsByToolCallId = new Map();
136
+ try {
137
+ for await (const event of runAgentTurn({
138
+ aiProvider,
139
+ model,
140
+ messages: parsed.data.messages,
141
+ tools,
142
+ toolContext: { aphexCMS, context },
143
+ systemPrompt: aphexCMS.config.agentSystemPrompt ?? DEFAULT_AGENT_SYSTEM_PROMPT,
144
+ signal: abortController.signal
145
+ })) {
146
+ if (event.type === 'usage') {
147
+ promptTokens += event.promptTokens;
148
+ completionTokens += event.completionTokens;
149
+ }
150
+ else if (event.type === 'toolCall') {
151
+ argsByToolCallId.set(event.toolCallId, event.arguments);
152
+ }
153
+ else if (event.type === 'toolResult' && changeSetId) {
154
+ const tool = toolsByName.get(event.name);
155
+ const args = argsByToolCallId.get(event.toolCallId);
156
+ if (tool?.definition.mutates && args) {
157
+ await recordMutatingOperation(aphexCMS, context, changeSetId, event.name, args, event.success, event.error, event.data);
158
+ }
159
+ }
160
+ else if (event.type === 'error') {
161
+ turnFailed = true;
162
+ }
163
+ if (event.type === 'done') {
164
+ event.changeSetId = changeSetId;
165
+ if (event.finishReason === 'awaiting_workspace_tool')
166
+ turnPaused = true;
167
+ }
168
+ await stream.writeSSE({ data: JSON.stringify(event) });
169
+ }
170
+ }
171
+ catch (err) {
172
+ turnFailed = true;
173
+ cmsLogger.error('[agent-chat] turn failed:', err);
174
+ await stream.writeSSE({
175
+ data: JSON.stringify({
176
+ type: 'error',
177
+ message: err instanceof Error ? err.message : 'Unknown error'
178
+ })
179
+ });
180
+ }
181
+ finally {
182
+ // A paused leg isn't the end of the turn — the client resumes with the same
183
+ // changeSetId, and only the truly-terminal leg should mark the change-set complete.
184
+ if (changeSetId && !turnPaused) {
185
+ try {
186
+ await databaseAdapter.completeChangeSet(context.organizationId, changeSetId, {
187
+ status: turnFailed ? 'failed' : 'completed',
188
+ promptTokens,
189
+ completionTokens
190
+ });
191
+ }
192
+ catch (err) {
193
+ cmsLogger.error('[agent-chat] failed to complete change-set (continuing):', err);
194
+ }
195
+ }
196
+ }
197
+ });
198
+ });
199
+ /**
200
+ * POST /api/agent/operations — records an audit/undo row for a tool the *client* executed
201
+ * against a live `DocumentWorkspace` (the `content_patch_fields`/`content_save_draft` bridge
202
+ * tools — see `ai/content-workspace-tools.ts`). `agent-chat.ts`'s own `recordMutatingOperation`
203
+ * call above only sees tool results resolved server-side inside `runAgentTurn`'s loop, so a
204
+ * workspace tool's result — resolved client-side after a paused turn — needs this separate
205
+ * path to reach the same `cms_agent_change_sets`/`cms_agent_operations` tables. Same
206
+ * session-authenticated posture as `/chat`; not itself a mutation of document data (the
207
+ * client already made that call directly via the normal document API), purely bookkeeping.
208
+ */
209
+ agentChatRouter.post('/operations', async (c) => {
210
+ const { aphexCMS, auth } = c.var;
211
+ if (!aphexCMS.config.aiProvider)
212
+ return c.json({ success: false, error: 'Not found' }, 404);
213
+ if (!auth)
214
+ return c.json({ success: false, error: 'Unauthorized' }, 401);
215
+ const body = await c.req.json().catch(() => null);
216
+ const parsed = recordWorkspaceOperationRequest.safeParse(body);
217
+ if (!parsed.success) {
218
+ return c.json({ success: false, error: 'Invalid request', issues: parsed.error.issues }, 400);
219
+ }
220
+ const context = authToContext(auth);
221
+ await recordMutatingOperation(aphexCMS, context, parsed.data.changeSetId, parsed.data.toolName, { collection: parsed.data.collection, id: parsed.data.id, ...parsed.data.arguments }, parsed.data.success, parsed.data.error, parsed.data.data);
222
+ return c.json({ success: true });
223
+ });
@@ -1 +1 @@
1
- {"version":3,"file":"document-versions.d.ts","sourceRoot":"","sources":["../../../../src/lib/server/api/routes/document-versions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAM5B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEzC,eAAO,MAAM,sBAAsB,EAAE,IAAI,CAAC,QAAQ,CAiK/C,CAAC"}
1
+ {"version":3,"file":"document-versions.d.ts","sourceRoot":"","sources":["../../../../src/lib/server/api/routes/document-versions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAO5B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEzC,eAAO,MAAM,sBAAsB,EAAE,IAAI,CAAC,QAAQ,CAsL/C,CAAC"}
@@ -3,7 +3,8 @@ import { zValidator } from '@hono/zod-validator';
3
3
  import { authToContext } from '../../../local-api/auth-helpers.js';
4
4
  import { cmsLogger } from '../../../utils/logger.js';
5
5
  import { hasCapability } from '../../../types/capabilities.js';
6
- import { listVersionsQuery } from '../../../api/schemas/documents.js';
6
+ import { RevisionConflictError } from '../../../db/interfaces.js';
7
+ import { listVersionsQuery, restoreVersionRequest } from '../../../api/schemas/documents.js';
7
8
  export const documentVersionsRouter = new Hono()
8
9
  .get('/:id/versions', zValidator('query', listVersionsQuery, (result, c) => {
9
10
  if (!result.success) {
@@ -103,7 +104,12 @@ export const documentVersionsRouter = new Hono()
103
104
  if (isNaN(versionNumber)) {
104
105
  return c.json({ success: false, error: 'Version must be a number' }, 400);
105
106
  }
106
- const document = await localAPI.versionService.restoreVersion(databaseAdapter, context.organizationId, id, versionNumber, context.user?.id);
107
+ const body = await c.req.json().catch(() => ({}));
108
+ const parsed = restoreVersionRequest.safeParse(body);
109
+ if (!parsed.success) {
110
+ return c.json({ success: false, error: 'Invalid request', issues: parsed.error.issues }, 400);
111
+ }
112
+ const document = await localAPI.versionService.restoreVersion(databaseAdapter, context.organizationId, id, versionNumber, context.user?.id, parsed.data.expectedRevision);
107
113
  if (!document) {
108
114
  return c.json({ success: false, error: 'Version not found or restore failed' }, 404);
109
115
  }
@@ -115,6 +121,14 @@ export const documentVersionsRouter = new Hono()
115
121
  }
116
122
  catch (error) {
117
123
  cmsLogger.error('Failed to restore document version:', error);
124
+ if (error instanceof RevisionConflictError) {
125
+ return c.json({
126
+ success: false,
127
+ error: 'Conflict',
128
+ message: error.message,
129
+ currentRevision: error.currentRevision
130
+ }, 409);
131
+ }
118
132
  return c.json({ success: false, error: 'Failed to restore version' }, 500);
119
133
  }
120
134
  });
@@ -1 +1 @@
1
- {"version":3,"file":"documents-by-id.d.ts","sourceRoot":"","sources":["../../../../src/lib/server/api/routes/documents-by-id.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAO5B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEzC,eAAO,MAAM,mBAAmB,EAAE,IAAI,CAAC,QAAQ,CAqN5C,CAAC"}
1
+ {"version":3,"file":"documents-by-id.d.ts","sourceRoot":"","sources":["../../../../src/lib/server/api/routes/documents-by-id.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAQ5B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEzC,eAAO,MAAM,mBAAmB,EAAE,IAAI,CAAC,QAAQ,CAiO5C,CAAC"}
@@ -3,6 +3,7 @@ import { zValidator } from '@hono/zod-validator';
3
3
  import { authToContext } from '../../../local-api/auth-helpers.js';
4
4
  import { PermissionError } from '../../../local-api/permissions.js';
5
5
  import { SingletonOperationError } from '../../../local-api/collection-api.js';
6
+ import { RevisionConflictError } from '../../../db/interfaces.js';
6
7
  import { cmsLogger } from '../../../utils/logger.js';
7
8
  import { updateDocumentRequest } from '../../../api/schemas/documents.js';
8
9
  export const documentsByIdRouter = new Hono()
@@ -82,7 +83,8 @@ export const documentsByIdRouter = new Hono()
82
83
  }, 400);
83
84
  }
84
85
  const result = await collection.update(context, id, documentData, {
85
- publish: shouldPublish
86
+ publish: shouldPublish,
87
+ expectedRevision: parsed.expectedRevision
86
88
  });
87
89
  if (!result) {
88
90
  return c.json({ success: false, error: 'Document not found' }, 404);
@@ -98,6 +100,14 @@ export const documentsByIdRouter = new Hono()
98
100
  if (error instanceof PermissionError) {
99
101
  return c.json({ success: false, error: 'Forbidden', message: error.message }, 403);
100
102
  }
103
+ if (error instanceof RevisionConflictError) {
104
+ return c.json({
105
+ success: false,
106
+ error: 'Conflict',
107
+ message: error.message,
108
+ currentRevision: error.currentRevision
109
+ }, 409);
110
+ }
101
111
  if (error instanceof Error && error.message.includes('validation errors')) {
102
112
  return c.json({ success: false, error: 'Validation failed', message: error.message }, 400);
103
113
  }
@@ -1 +1 @@
1
- {"version":3,"file":"documents-publish.d.ts","sourceRoot":"","sources":["../../../../src/lib/server/api/routes/documents-publish.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAI5B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEzC,eAAO,MAAM,sBAAsB,EAAE,IAAI,CAAC,QAAQ,CA4J/C,CAAC"}
1
+ {"version":3,"file":"documents-publish.d.ts","sourceRoot":"","sources":["../../../../src/lib/server/api/routes/documents-publish.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAU5B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEzC,eAAO,MAAM,sBAAsB,EAAE,IAAI,CAAC,QAAQ,CAkU/C,CAAC"}
@@ -1,8 +1,119 @@
1
1
  import { Hono } from 'hono';
2
2
  import { authToContext } from '../../../local-api/auth-helpers.js';
3
3
  import { PermissionError } from '../../../local-api/permissions.js';
4
+ import { RevisionConflictError } from '../../../db/interfaces.js';
4
5
  import { cmsLogger } from '../../../utils/logger.js';
6
+ import { scheduleDocumentRequest, publishDocumentRequest, unpublishDocumentRequest } from '../../../api/schemas/documents.js';
5
7
  export const documentsPublishRouter = new Hono()
8
+ .post('/:id/schedule', async (c) => {
9
+ try {
10
+ const { localAPI } = c.var.aphexCMS;
11
+ const context = authToContext(c.var.auth);
12
+ const id = c.req.param('id');
13
+ if (!id) {
14
+ return c.json({ success: false, error: 'Missing document ID' }, 400);
15
+ }
16
+ const parsed = scheduleDocumentRequest.safeParse(await c.req.json().catch(() => null));
17
+ if (!parsed.success) {
18
+ return c.json({ success: false, error: 'Invalid request', issues: parsed.error.issues }, 400);
19
+ }
20
+ const { action, runAt } = parsed.data;
21
+ const found = await localAPI.findDocumentById(context, id);
22
+ if (!found) {
23
+ return c.json({ success: false, error: 'Document not found' }, 404);
24
+ }
25
+ const collection = localAPI.getCollection(found.type);
26
+ if (!collection) {
27
+ return c.json({
28
+ success: false,
29
+ error: 'Invalid document type',
30
+ message: `Collection '${found.type}' not found`
31
+ }, 400);
32
+ }
33
+ const when = new Date(runAt);
34
+ const job = action === 'publish'
35
+ ? await collection.schedulePublish(context, id, when)
36
+ : await collection.scheduleUnpublish(context, id, when);
37
+ return c.json({
38
+ success: true,
39
+ data: { jobId: job.id, type: job.type, runAt: job.runAt.toISOString(), status: job.status },
40
+ message: `Document ${action} scheduled for ${job.runAt.toISOString()}`
41
+ });
42
+ }
43
+ catch (error) {
44
+ cmsLogger.error('Failed to schedule document action:', error);
45
+ if (error instanceof PermissionError) {
46
+ return c.json({ success: false, error: 'Forbidden', message: error.message }, 403);
47
+ }
48
+ return c.json({
49
+ success: false,
50
+ error: 'Failed to schedule document action',
51
+ message: error instanceof Error ? error.message : 'Unknown error'
52
+ }, 500);
53
+ }
54
+ })
55
+ .get('/:id/schedule', async (c) => {
56
+ // Pending scheduled publish/unpublish for this document — powers the editor's
57
+ // "scheduled for …" indicator. Read-gated inside the collection.
58
+ try {
59
+ const { localAPI } = c.var.aphexCMS;
60
+ const context = authToContext(c.var.auth);
61
+ const id = c.req.param('id');
62
+ if (!id)
63
+ return c.json({ success: false, error: 'Missing document ID' }, 400);
64
+ const found = await localAPI.findDocumentById(context, id);
65
+ if (!found)
66
+ return c.json({ success: false, error: 'Document not found' }, 404);
67
+ const collection = localAPI.getCollection(found.type);
68
+ if (!collection) {
69
+ return c.json({ success: false, error: 'Invalid document type' }, 400);
70
+ }
71
+ const jobs = await collection.getScheduled(context, id);
72
+ return c.json({
73
+ success: true,
74
+ data: jobs.map((j) => ({
75
+ jobId: j.id,
76
+ type: j.type,
77
+ runAt: j.runAt.toISOString(),
78
+ status: j.status,
79
+ createdAt: j.createdAt.toISOString()
80
+ }))
81
+ });
82
+ }
83
+ catch (error) {
84
+ cmsLogger.error('Failed to read document schedule:', error);
85
+ if (error instanceof PermissionError) {
86
+ return c.json({ success: false, error: 'Forbidden', message: error.message }, 403);
87
+ }
88
+ return c.json({ success: false, error: 'Failed to read document schedule' }, 500);
89
+ }
90
+ })
91
+ .delete('/:id/schedule', async (c) => {
92
+ // Cancel the pending schedule for this document.
93
+ try {
94
+ const { localAPI } = c.var.aphexCMS;
95
+ const context = authToContext(c.var.auth);
96
+ const id = c.req.param('id');
97
+ if (!id)
98
+ return c.json({ success: false, error: 'Missing document ID' }, 400);
99
+ const found = await localAPI.findDocumentById(context, id);
100
+ if (!found)
101
+ return c.json({ success: false, error: 'Document not found' }, 404);
102
+ const collection = localAPI.getCollection(found.type);
103
+ if (!collection) {
104
+ return c.json({ success: false, error: 'Invalid document type' }, 400);
105
+ }
106
+ const cancelled = await collection.cancelScheduled(context, id);
107
+ return c.json({ success: true, data: { cancelled } });
108
+ }
109
+ catch (error) {
110
+ cmsLogger.error('Failed to cancel document schedule:', error);
111
+ if (error instanceof PermissionError) {
112
+ return c.json({ success: false, error: 'Forbidden', message: error.message }, 403);
113
+ }
114
+ return c.json({ success: false, error: 'Failed to cancel document schedule' }, 500);
115
+ }
116
+ })
6
117
  .post('/:id/publish', async (c) => {
7
118
  try {
8
119
  const { localAPI } = c.var.aphexCMS;
@@ -31,7 +142,16 @@ export const documentsPublishRouter = new Hono()
31
142
  message: `Collection '${found.type}' not found`
32
143
  }, 400);
33
144
  }
34
- const publishedDocument = await collection.publish(context, id);
145
+ // Body is optional — a bare POST with no body is still valid, only
146
+ // carries the CAS guard when the caller has one to send.
147
+ const body = await c.req.json().catch(() => ({}));
148
+ const parsed = publishDocumentRequest.safeParse(body);
149
+ if (!parsed.success) {
150
+ return c.json({ success: false, error: 'Invalid request', issues: parsed.error.issues }, 400);
151
+ }
152
+ const publishedDocument = await collection.publish(context, id, {
153
+ expectedRevision: parsed.data.expectedRevision
154
+ });
35
155
  if (!publishedDocument) {
36
156
  return c.json({
37
157
  success: false,
@@ -50,6 +170,14 @@ export const documentsPublishRouter = new Hono()
50
170
  if (error instanceof PermissionError) {
51
171
  return c.json({ success: false, error: 'Forbidden', message: error.message }, 403);
52
172
  }
173
+ if (error instanceof RevisionConflictError) {
174
+ return c.json({
175
+ success: false,
176
+ error: 'Conflict',
177
+ message: error.message,
178
+ currentRevision: error.currentRevision
179
+ }, 409);
180
+ }
53
181
  if (error instanceof Error && error.message.includes('validation errors')) {
54
182
  return c.json({
55
183
  success: false,
@@ -92,7 +220,14 @@ export const documentsPublishRouter = new Hono()
92
220
  message: `Collection '${found.type}' not found`
93
221
  }, 400);
94
222
  }
95
- const unpublishedDocument = await collection.unpublish(context, id);
223
+ const body = await c.req.json().catch(() => ({}));
224
+ const parsed = unpublishDocumentRequest.safeParse(body);
225
+ if (!parsed.success) {
226
+ return c.json({ success: false, error: 'Invalid request', issues: parsed.error.issues }, 400);
227
+ }
228
+ const unpublishedDocument = await collection.unpublish(context, id, {
229
+ expectedRevision: parsed.data.expectedRevision
230
+ });
96
231
  if (!unpublishedDocument) {
97
232
  return c.json({
98
233
  success: false,
@@ -111,6 +246,14 @@ export const documentsPublishRouter = new Hono()
111
246
  if (error instanceof PermissionError) {
112
247
  return c.json({ success: false, error: 'Forbidden', message: error.message }, 403);
113
248
  }
249
+ if (error instanceof RevisionConflictError) {
250
+ return c.json({
251
+ success: false,
252
+ error: 'Conflict',
253
+ message: error.message,
254
+ currentRevision: error.currentRevision
255
+ }, 409);
256
+ }
114
257
  return c.json({
115
258
  success: false,
116
259
  error: 'Failed to unpublish document',
@@ -0,0 +1,4 @@
1
+ import { Hono } from 'hono';
2
+ import type { AphexEnv } from '../index.js';
3
+ export declare const jobsRouter: Hono<AphexEnv>;
4
+ //# sourceMappingURL=jobs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jobs.d.ts","sourceRoot":"","sources":["../../../../src/lib/server/api/routes/jobs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAK5B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AA6CzC,eAAO,MAAM,UAAU,EAAE,IAAI,CAAC,QAAQ,CAkDnC,CAAC"}
@@ -0,0 +1,94 @@
1
+ import { Hono } from 'hono';
2
+ import { z } from 'zod';
3
+ import { authToContext } from '../../../local-api/auth-helpers.js';
4
+ import { hasCapability } from '../../../types/capabilities.js';
5
+ import { cmsLogger } from '../../../utils/logger.js';
6
+ import { withCreatedByNames } from './resolve-created-by.js';
7
+ // Read-only history / observability for the durable spine. Gated on `document.read`:
8
+ // the operational log of publish work is visible to anyone who can read content.
9
+ // Mirrors JobStatus (types/events) as a zod enum — the API contract's source of truth.
10
+ const jobStatus = z.enum(['pending', 'leased', 'completed', 'failed', 'cancelled']);
11
+ const listJobsQuery = z.object({
12
+ status: jobStatus.optional(),
13
+ type: z.string().optional(),
14
+ limit: z.coerce.number().int().min(1).max(200).optional(),
15
+ offset: z.coerce.number().int().min(0).optional()
16
+ });
17
+ const listEventsQuery = z.object({
18
+ type: z.string().optional(),
19
+ limit: z.coerce.number().int().min(1).max(200).optional(),
20
+ offset: z.coerce.number().int().min(0).optional()
21
+ });
22
+ /** Map an adapter Page into the ApiResponse `pagination` shape the client expects. */
23
+ function toPagination(page) {
24
+ const pageSize = page.limit || 1;
25
+ return {
26
+ total: page.total,
27
+ page: Math.floor(page.offset / pageSize) + 1,
28
+ pageSize,
29
+ totalPages: Math.max(1, Math.ceil(page.total / pageSize)),
30
+ hasNextPage: page.offset + page.limit < page.total,
31
+ hasPrevPage: page.offset > 0
32
+ };
33
+ }
34
+ function requireHistoryAccess(c) {
35
+ const auth = c.var.auth;
36
+ if (!auth || auth.type === 'partial_session') {
37
+ return { error: c.json({ success: false, error: 'Authentication required' }, 401) };
38
+ }
39
+ if (!hasCapability(auth, 'document.read')) {
40
+ return { error: c.json({ success: false, error: 'Insufficient permissions' }, 403) };
41
+ }
42
+ return { organizationId: authToContext(auth).organizationId };
43
+ }
44
+ export const jobsRouter = new Hono()
45
+ .get('/jobs', async (c) => {
46
+ try {
47
+ const gate = requireHistoryAccess(c);
48
+ if ('error' in gate)
49
+ return gate.error;
50
+ const parsed = listJobsQuery.safeParse(c.req.query());
51
+ if (!parsed.success) {
52
+ return c.json({ success: false, error: 'Invalid query', issues: parsed.error.issues }, 400);
53
+ }
54
+ const { status, type, limit, offset } = parsed.data;
55
+ const { databaseAdapter } = c.var.aphexCMS;
56
+ const page = await databaseAdapter.listJobs({
57
+ organizationId: gate.organizationId,
58
+ status,
59
+ type,
60
+ limit,
61
+ offset
62
+ });
63
+ return c.json({ success: true, data: page.items, pagination: toPagination(page) });
64
+ }
65
+ catch (error) {
66
+ cmsLogger.error('Failed to list jobs:', error);
67
+ return c.json({ success: false, error: 'Failed to list jobs' }, 500);
68
+ }
69
+ })
70
+ .get('/events', async (c) => {
71
+ try {
72
+ const gate = requireHistoryAccess(c);
73
+ if ('error' in gate)
74
+ return gate.error;
75
+ const parsed = listEventsQuery.safeParse(c.req.query());
76
+ if (!parsed.success) {
77
+ return c.json({ success: false, error: 'Invalid query', issues: parsed.error.issues }, 400);
78
+ }
79
+ const { type, limit, offset } = parsed.data;
80
+ const { databaseAdapter, auth } = c.var.aphexCMS;
81
+ const page = await databaseAdapter.listEvents({
82
+ organizationId: gate.organizationId,
83
+ type,
84
+ limit,
85
+ offset
86
+ });
87
+ const items = await withCreatedByNames(page.items, auth);
88
+ return c.json({ success: true, data: items, pagination: toPagination(page) });
89
+ }
90
+ catch (error) {
91
+ cmsLogger.error('Failed to list events:', error);
92
+ return c.json({ success: false, error: 'Failed to list events' }, 500);
93
+ }
94
+ });
@@ -0,0 +1,13 @@
1
+ import type { AuthProvider } from '../../../auth/provider.js';
2
+ /**
3
+ * Resolves `createdBy` user ids on a list of rows to a display name (or `'API Key'` for a
4
+ * `apikey:<id>` synthetic id — see `authToContext`'s API-key branch). Shared by every
5
+ * read-only history view (`GET /api/events`, `GET /api/agent/change-sets`, ...) — an audit
6
+ * trail whose whole point is accountability needs to show *who*, not a raw id.
7
+ */
8
+ export declare function withCreatedByNames<T extends {
9
+ createdBy: string | null;
10
+ }>(rows: T[], auth: AuthProvider | undefined): Promise<Array<T & {
11
+ createdByName: string | null;
12
+ }>>;
13
+ //# sourceMappingURL=resolve-created-by.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-created-by.d.ts","sourceRoot":"","sources":["../../../../src/lib/server/api/routes/resolve-created-by.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAE3D;;;;;GAKG;AACH,wBAAsB,kBAAkB,CAAC,CAAC,SAAS;IAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,EAC9E,IAAI,EAAE,CAAC,EAAE,EACT,IAAI,EAAE,YAAY,GAAG,SAAS,GAC5B,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG;IAAE,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CAAC,CAyBtD"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Resolves `createdBy` user ids on a list of rows to a display name (or `'API Key'` for a
3
+ * `apikey:<id>` synthetic id — see `authToContext`'s API-key branch). Shared by every
4
+ * read-only history view (`GET /api/events`, `GET /api/agent/change-sets`, ...) — an audit
5
+ * trail whose whole point is accountability needs to show *who*, not a raw id.
6
+ */
7
+ export async function withCreatedByNames(rows, auth) {
8
+ const userIds = [...new Set(rows.map((r) => r.createdBy).filter((id) => !!id))];
9
+ const userMap = new Map();
10
+ if (userIds.length > 0 && auth) {
11
+ await Promise.all(userIds.map(async (userId) => {
12
+ if (userId.startsWith('apikey:')) {
13
+ userMap.set(userId, 'API Key');
14
+ return;
15
+ }
16
+ try {
17
+ const user = await auth.getUserById(userId);
18
+ if (user)
19
+ userMap.set(userId, user.name || user.email);
20
+ }
21
+ catch {
22
+ // User not found — skip
23
+ }
24
+ }));
25
+ }
26
+ return rows.map((r) => ({
27
+ ...r,
28
+ createdByName: r.createdBy ? (userMap.get(r.createdBy) ?? null) : null
29
+ }));
30
+ }
@@ -0,0 +1,4 @@
1
+ import { Hono } from 'hono';
2
+ import type { AphexEnv } from '../index.js';
3
+ export declare const workersRunRouter: Hono<AphexEnv, import("hono/types").BlankSchema, "/">;
4
+ //# sourceMappingURL=workers-run.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workers-run.d.ts","sourceRoot":"","sources":["../../../../src/lib/server/api/routes/workers-run.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAezC,eAAO,MAAM,gBAAgB,uDAAuB,CAAC"}