@aphexcms/cms-core 9.7.0 → 9.8.1

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 (330) 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 +8 -3
  23. package/dist/api/documents.d.ts.map +1 -1
  24. package/dist/api/documents.js +6 -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 +22 -0
  32. package/dist/api/schemas/documents.d.ts.map +1 -1
  33. package/dist/api/schemas/documents.js +20 -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 +1 -0
  41. package/dist/client/ui.d.ts.map +1 -1
  42. package/dist/client/ui.js +1 -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 +251 -42
  46. package/dist/components/admin/ActivityView.svelte.d.ts.map +1 -1
  47. package/dist/components/admin/AgentChat.svelte +977 -0
  48. package/dist/components/admin/AgentChat.svelte.d.ts +17 -0
  49. package/dist/components/admin/AgentChat.svelte.d.ts.map +1 -0
  50. package/dist/components/admin/DocumentEditor.svelte +273 -60
  51. package/dist/components/admin/DocumentEditor.svelte.d.ts +6 -0
  52. package/dist/components/admin/DocumentEditor.svelte.d.ts.map +1 -1
  53. package/dist/components/admin/ObjectModal.svelte +4 -2
  54. package/dist/components/admin/fields/ArrayField.svelte +4 -1
  55. package/dist/components/admin/fields/ReferenceField.svelte +12 -1
  56. package/dist/components/admin/fields/ReferenceField.svelte.d.ts.map +1 -1
  57. package/dist/components/index.d.ts +1 -0
  58. package/dist/components/index.d.ts.map +1 -1
  59. package/dist/components/index.js +1 -0
  60. package/dist/components/layout/Sidebar.svelte +26 -2
  61. package/dist/components/layout/Sidebar.svelte.d.ts +1 -0
  62. package/dist/components/layout/Sidebar.svelte.d.ts.map +1 -1
  63. package/dist/db/interfaces/agent-change-sets.d.ts +17 -0
  64. package/dist/db/interfaces/agent-change-sets.d.ts.map +1 -0
  65. package/dist/db/interfaces/agent-change-sets.js +1 -0
  66. package/dist/db/interfaces/document.d.ts +25 -3
  67. package/dist/db/interfaces/document.d.ts.map +1 -1
  68. package/dist/db/interfaces/document.js +19 -1
  69. package/dist/db/interfaces/index.d.ts +4 -1
  70. package/dist/db/interfaces/index.d.ts.map +1 -1
  71. package/dist/db/interfaces/index.js +1 -1
  72. package/dist/document-refresh.svelte.d.ts +2 -0
  73. package/dist/document-refresh.svelte.d.ts.map +1 -1
  74. package/dist/document-refresh.svelte.js +15 -0
  75. package/dist/document-workspace-registry.svelte.d.ts +15 -0
  76. package/dist/document-workspace-registry.svelte.d.ts.map +1 -0
  77. package/dist/document-workspace-registry.svelte.js +30 -0
  78. package/dist/field-validation/utils.d.ts.map +1 -1
  79. package/dist/field-validation/utils.js +211 -29
  80. package/dist/hooks.d.ts +2 -0
  81. package/dist/hooks.d.ts.map +1 -1
  82. package/dist/hooks.js +2 -0
  83. package/dist/lib/agent-chat-state.svelte.d.ts +38 -0
  84. package/dist/lib/agent-chat-state.svelte.d.ts.map +1 -0
  85. package/dist/lib/agent-chat-state.svelte.js +87 -0
  86. package/dist/lib/agent-chat-state.svelte.js.map +1 -0
  87. package/dist/lib/ai/content-workspace-tools.d.ts +3 -0
  88. package/dist/lib/ai/content-workspace-tools.d.ts.map +1 -0
  89. package/dist/lib/ai/content-workspace-tools.js +51 -0
  90. package/dist/lib/ai/content-workspace-tools.js.map +1 -0
  91. package/dist/lib/ai/default-system-prompt.d.ts +2 -0
  92. package/dist/lib/ai/default-system-prompt.d.ts.map +1 -0
  93. package/dist/lib/ai/default-system-prompt.js +16 -0
  94. package/dist/lib/ai/default-system-prompt.js.map +1 -0
  95. package/dist/lib/ai/index.d.ts +2 -0
  96. package/dist/lib/ai/index.d.ts.map +1 -0
  97. package/dist/lib/ai/index.js +5 -0
  98. package/dist/lib/ai/index.js.map +1 -0
  99. package/dist/lib/ai/interfaces/ai-provider.d.ts +67 -0
  100. package/dist/lib/ai/interfaces/ai-provider.d.ts.map +1 -0
  101. package/dist/lib/ai/interfaces/ai-provider.js +17 -0
  102. package/dist/lib/ai/interfaces/ai-provider.js.map +1 -0
  103. package/dist/lib/ai/run-agent-turn.d.ts +29 -0
  104. package/dist/lib/ai/run-agent-turn.d.ts.map +1 -0
  105. package/dist/lib/ai/run-agent-turn.js +167 -0
  106. package/dist/lib/ai/run-agent-turn.js.map +1 -0
  107. package/dist/lib/api/agent-chat.d.ts +27 -0
  108. package/dist/lib/api/agent-chat.d.ts.map +1 -0
  109. package/dist/lib/api/agent-chat.js +65 -0
  110. package/dist/lib/api/agent-chat.js.map +1 -0
  111. package/dist/lib/api/documents.d.ts +8 -3
  112. package/dist/lib/api/documents.d.ts.map +1 -1
  113. package/dist/lib/api/documents.js +6 -6
  114. package/dist/lib/api/documents.js.map +1 -1
  115. package/dist/lib/api/schemas/agent-chat.d.ts +45 -0
  116. package/dist/lib/api/schemas/agent-chat.d.ts.map +1 -0
  117. package/dist/lib/api/schemas/agent-chat.js +36 -0
  118. package/dist/lib/api/schemas/agent-chat.js.map +1 -0
  119. package/dist/lib/api/schemas/agent-operations.d.ts +13 -0
  120. package/dist/lib/api/schemas/agent-operations.d.ts.map +1 -0
  121. package/dist/lib/api/schemas/agent-operations.js +16 -0
  122. package/dist/lib/api/schemas/agent-operations.js.map +1 -0
  123. package/dist/lib/api/schemas/documents.d.ts +22 -0
  124. package/dist/lib/api/schemas/documents.d.ts.map +1 -1
  125. package/dist/lib/api/schemas/documents.js +20 -2
  126. package/dist/lib/api/schemas/documents.js.map +1 -1
  127. package/dist/lib/chunk-recovery.d.ts +33 -0
  128. package/dist/lib/chunk-recovery.d.ts.map +1 -0
  129. package/dist/lib/chunk-recovery.js +132 -0
  130. package/dist/lib/chunk-recovery.js.map +1 -0
  131. package/dist/lib/client/index.d.ts +1 -0
  132. package/dist/lib/client/index.d.ts.map +1 -1
  133. package/dist/lib/client/index.js +1 -0
  134. package/dist/lib/client/index.js.map +1 -1
  135. package/dist/lib/client/ui.d.ts +1 -0
  136. package/dist/lib/client/ui.d.ts.map +1 -1
  137. package/dist/lib/client/ui.js +1 -0
  138. package/dist/lib/client/ui.js.map +1 -1
  139. package/dist/lib/components/index.d.ts +1 -0
  140. package/dist/lib/components/index.d.ts.map +1 -1
  141. package/dist/lib/components/index.js +1 -0
  142. package/dist/lib/components/index.js.map +1 -1
  143. package/dist/lib/db/interfaces/agent-change-sets.d.ts +17 -0
  144. package/dist/lib/db/interfaces/agent-change-sets.d.ts.map +1 -0
  145. package/dist/lib/db/interfaces/agent-change-sets.js +2 -0
  146. package/dist/lib/db/interfaces/agent-change-sets.js.map +1 -0
  147. package/dist/lib/db/interfaces/document.d.ts +25 -3
  148. package/dist/lib/db/interfaces/document.d.ts.map +1 -1
  149. package/dist/lib/db/interfaces/document.js +19 -1
  150. package/dist/lib/db/interfaces/document.js.map +1 -1
  151. package/dist/lib/db/interfaces/index.d.ts +4 -1
  152. package/dist/lib/db/interfaces/index.d.ts.map +1 -1
  153. package/dist/lib/db/interfaces/index.js +1 -1
  154. package/dist/lib/db/interfaces/index.js.map +1 -1
  155. package/dist/lib/document-refresh.svelte.d.ts +2 -0
  156. package/dist/lib/document-refresh.svelte.d.ts.map +1 -1
  157. package/dist/lib/document-refresh.svelte.js +15 -0
  158. package/dist/lib/document-refresh.svelte.js.map +1 -1
  159. package/dist/lib/document-workspace-registry.svelte.d.ts +15 -0
  160. package/dist/lib/document-workspace-registry.svelte.d.ts.map +1 -0
  161. package/dist/lib/document-workspace-registry.svelte.js +31 -0
  162. package/dist/lib/document-workspace-registry.svelte.js.map +1 -0
  163. package/dist/lib/field-validation/utils.d.ts.map +1 -1
  164. package/dist/lib/field-validation/utils.js +211 -29
  165. package/dist/lib/field-validation/utils.js.map +1 -1
  166. package/dist/lib/hooks.d.ts +2 -0
  167. package/dist/lib/hooks.d.ts.map +1 -1
  168. package/dist/lib/hooks.js +2 -0
  169. package/dist/lib/hooks.js.map +1 -1
  170. package/dist/lib/local-api/collection-api.d.ts +7 -2
  171. package/dist/lib/local-api/collection-api.d.ts.map +1 -1
  172. package/dist/lib/local-api/collection-api.js +17 -10
  173. package/dist/lib/local-api/collection-api.js.map +1 -1
  174. package/dist/lib/mcp/tools.d.ts +39 -4
  175. package/dist/lib/mcp/tools.d.ts.map +1 -1
  176. package/dist/lib/mcp/tools.js +546 -362
  177. package/dist/lib/mcp/tools.js.map +1 -1
  178. package/dist/lib/plugins/resolver.d.ts +8 -1
  179. package/dist/lib/plugins/resolver.d.ts.map +1 -1
  180. package/dist/lib/plugins/resolver.js +14 -1
  181. package/dist/lib/plugins/resolver.js.map +1 -1
  182. package/dist/lib/plugins/types.d.ts +23 -2
  183. package/dist/lib/plugins/types.d.ts.map +1 -1
  184. package/dist/lib/plugins/types.js.map +1 -1
  185. package/dist/lib/preview/stega.d.ts +2 -2
  186. package/dist/lib/preview/stega.d.ts.map +1 -1
  187. package/dist/lib/preview/stega.js +52 -29
  188. package/dist/lib/preview/stega.js.map +1 -1
  189. package/dist/lib/schema-utils/validator.d.ts.map +1 -1
  190. package/dist/lib/schema-utils/validator.js +5 -2
  191. package/dist/lib/schema-utils/validator.js.map +1 -1
  192. package/dist/lib/server/api/index.d.ts.map +1 -1
  193. package/dist/lib/server/api/index.js +8 -0
  194. package/dist/lib/server/api/index.js.map +1 -1
  195. package/dist/lib/server/api/routes/agent-change-sets.d.ts +4 -0
  196. package/dist/lib/server/api/routes/agent-change-sets.d.ts.map +1 -0
  197. package/dist/lib/server/api/routes/agent-change-sets.js +132 -0
  198. package/dist/lib/server/api/routes/agent-change-sets.js.map +1 -0
  199. package/dist/lib/server/api/routes/agent-chat.d.ts +14 -0
  200. package/dist/lib/server/api/routes/agent-chat.d.ts.map +1 -0
  201. package/dist/lib/server/api/routes/agent-chat.js +224 -0
  202. package/dist/lib/server/api/routes/agent-chat.js.map +1 -0
  203. package/dist/lib/server/api/routes/document-versions.d.ts.map +1 -1
  204. package/dist/lib/server/api/routes/document-versions.js +16 -2
  205. package/dist/lib/server/api/routes/document-versions.js.map +1 -1
  206. package/dist/lib/server/api/routes/documents-by-id.d.ts.map +1 -1
  207. package/dist/lib/server/api/routes/documents-by-id.js +11 -1
  208. package/dist/lib/server/api/routes/documents-by-id.js.map +1 -1
  209. package/dist/lib/server/api/routes/documents-publish.d.ts.map +1 -1
  210. package/dist/lib/server/api/routes/documents-publish.js +36 -3
  211. package/dist/lib/server/api/routes/documents-publish.js.map +1 -1
  212. package/dist/lib/server/api/routes/jobs.d.ts.map +1 -1
  213. package/dist/lib/server/api/routes/jobs.js +4 -2
  214. package/dist/lib/server/api/routes/jobs.js.map +1 -1
  215. package/dist/lib/server/api/routes/resolve-created-by.d.ts +13 -0
  216. package/dist/lib/server/api/routes/resolve-created-by.d.ts.map +1 -0
  217. package/dist/lib/server/api/routes/resolve-created-by.js +31 -0
  218. package/dist/lib/server/api/routes/resolve-created-by.js.map +1 -0
  219. package/dist/lib/server/index.d.ts +1 -0
  220. package/dist/lib/server/index.d.ts.map +1 -1
  221. package/dist/lib/server/index.js +1 -0
  222. package/dist/lib/server/index.js.map +1 -1
  223. package/dist/lib/services/references-service.d.ts +1 -1
  224. package/dist/lib/services/references-service.d.ts.map +1 -1
  225. package/dist/lib/services/version-service.d.ts +4 -4
  226. package/dist/lib/services/version-service.d.ts.map +1 -1
  227. package/dist/lib/services/version-service.js +15 -11
  228. package/dist/lib/services/version-service.js.map +1 -1
  229. package/dist/lib/type-gen.d.ts.map +1 -1
  230. package/dist/lib/type-gen.js +11 -0
  231. package/dist/lib/type-gen.js.map +1 -1
  232. package/dist/lib/types/agent-change-sets.d.ts +70 -0
  233. package/dist/lib/types/agent-change-sets.d.ts.map +1 -0
  234. package/dist/lib/types/agent-change-sets.js +7 -0
  235. package/dist/lib/types/agent-change-sets.js.map +1 -0
  236. package/dist/lib/types/agent-stream.d.ts +60 -0
  237. package/dist/lib/types/agent-stream.d.ts.map +1 -0
  238. package/dist/lib/types/agent-stream.js +12 -0
  239. package/dist/lib/types/agent-stream.js.map +1 -0
  240. package/dist/lib/types/agent-tools.d.ts +65 -0
  241. package/dist/lib/types/agent-tools.d.ts.map +1 -0
  242. package/dist/lib/types/agent-tools.js +2 -0
  243. package/dist/lib/types/agent-tools.js.map +1 -0
  244. package/dist/lib/types/config.d.ts +19 -0
  245. package/dist/lib/types/config.d.ts.map +1 -1
  246. package/dist/lib/types/document-workspace.d.ts +53 -0
  247. package/dist/lib/types/document-workspace.d.ts.map +1 -0
  248. package/dist/lib/types/document-workspace.js +15 -0
  249. package/dist/lib/types/document-workspace.js.map +1 -0
  250. package/dist/lib/types/document.d.ts +5 -0
  251. package/dist/lib/types/document.d.ts.map +1 -1
  252. package/dist/lib/types/index.d.ts +2 -0
  253. package/dist/lib/types/index.d.ts.map +1 -1
  254. package/dist/lib/types/index.js +2 -0
  255. package/dist/lib/types/index.js.map +1 -1
  256. package/dist/lib/types/schemas.js +1 -1
  257. package/dist/lib/types/schemas.js.map +1 -1
  258. package/dist/lib/utils/fetch-remote-file.d.ts +11 -0
  259. package/dist/lib/utils/fetch-remote-file.d.ts.map +1 -0
  260. package/dist/lib/utils/fetch-remote-file.js +169 -0
  261. package/dist/lib/utils/fetch-remote-file.js.map +1 -0
  262. package/dist/local-api/collection-api.d.ts +7 -2
  263. package/dist/local-api/collection-api.d.ts.map +1 -1
  264. package/dist/local-api/collection-api.js +17 -10
  265. package/dist/mcp/tools.d.ts +39 -4
  266. package/dist/mcp/tools.d.ts.map +1 -1
  267. package/dist/mcp/tools.js +546 -362
  268. package/dist/plugins/resolver.d.ts +8 -1
  269. package/dist/plugins/resolver.d.ts.map +1 -1
  270. package/dist/plugins/resolver.js +14 -1
  271. package/dist/plugins/types.d.ts +23 -2
  272. package/dist/plugins/types.d.ts.map +1 -1
  273. package/dist/preview/stega.d.ts +2 -2
  274. package/dist/preview/stega.d.ts.map +1 -1
  275. package/dist/preview/stega.js +52 -29
  276. package/dist/schema-utils/validator.d.ts.map +1 -1
  277. package/dist/schema-utils/validator.js +5 -2
  278. package/dist/server/api/index.d.ts.map +1 -1
  279. package/dist/server/api/index.js +8 -0
  280. package/dist/server/api/routes/agent-change-sets.d.ts +4 -0
  281. package/dist/server/api/routes/agent-change-sets.d.ts.map +1 -0
  282. package/dist/server/api/routes/agent-change-sets.js +131 -0
  283. package/dist/server/api/routes/agent-chat.d.ts +14 -0
  284. package/dist/server/api/routes/agent-chat.d.ts.map +1 -0
  285. package/dist/server/api/routes/agent-chat.js +223 -0
  286. package/dist/server/api/routes/document-versions.d.ts.map +1 -1
  287. package/dist/server/api/routes/document-versions.js +16 -2
  288. package/dist/server/api/routes/documents-by-id.d.ts.map +1 -1
  289. package/dist/server/api/routes/documents-by-id.js +11 -1
  290. package/dist/server/api/routes/documents-publish.d.ts.map +1 -1
  291. package/dist/server/api/routes/documents-publish.js +36 -3
  292. package/dist/server/api/routes/jobs.d.ts.map +1 -1
  293. package/dist/server/api/routes/jobs.js +4 -2
  294. package/dist/server/api/routes/resolve-created-by.d.ts +13 -0
  295. package/dist/server/api/routes/resolve-created-by.d.ts.map +1 -0
  296. package/dist/server/api/routes/resolve-created-by.js +30 -0
  297. package/dist/server/index.d.ts +1 -0
  298. package/dist/server/index.d.ts.map +1 -1
  299. package/dist/server/index.js +1 -0
  300. package/dist/services/references-service.d.ts +1 -1
  301. package/dist/services/references-service.d.ts.map +1 -1
  302. package/dist/services/version-service.d.ts +4 -4
  303. package/dist/services/version-service.d.ts.map +1 -1
  304. package/dist/services/version-service.js +15 -11
  305. package/dist/type-gen.d.ts.map +1 -1
  306. package/dist/type-gen.js +11 -0
  307. package/dist/types/agent-change-sets.d.ts +70 -0
  308. package/dist/types/agent-change-sets.d.ts.map +1 -0
  309. package/dist/types/agent-change-sets.js +6 -0
  310. package/dist/types/agent-stream.d.ts +60 -0
  311. package/dist/types/agent-stream.d.ts.map +1 -0
  312. package/dist/types/agent-stream.js +11 -0
  313. package/dist/types/agent-tools.d.ts +65 -0
  314. package/dist/types/agent-tools.d.ts.map +1 -0
  315. package/dist/types/agent-tools.js +1 -0
  316. package/dist/types/config.d.ts +19 -0
  317. package/dist/types/config.d.ts.map +1 -1
  318. package/dist/types/document-workspace.d.ts +53 -0
  319. package/dist/types/document-workspace.d.ts.map +1 -0
  320. package/dist/types/document-workspace.js +14 -0
  321. package/dist/types/document.d.ts +5 -0
  322. package/dist/types/document.d.ts.map +1 -1
  323. package/dist/types/index.d.ts +2 -0
  324. package/dist/types/index.d.ts.map +1 -1
  325. package/dist/types/index.js +2 -0
  326. package/dist/types/schemas.js +1 -1
  327. package/dist/utils/fetch-remote-file.d.ts +11 -0
  328. package/dist/utils/fetch-remote-file.d.ts.map +1 -0
  329. package/dist/utils/fetch-remote-file.js +168 -0
  330. package/package.json +5 -2
@@ -0,0 +1,70 @@
1
+ export type AgentChangeSetStatus = 'in_progress' | 'completed' | 'failed';
2
+ /** One agent turn. Created eagerly, before the model is even called, so token usage is
3
+ * captured regardless of whether the turn ends up mutating anything. */
4
+ export interface AgentChangeSet {
5
+ id: string;
6
+ organizationId: string;
7
+ createdBy: string | null;
8
+ status: AgentChangeSetStatus;
9
+ /** The turn's first user message, truncated — a human-readable label for the activity list. */
10
+ summary: string | null;
11
+ /** `AIProviderAdapter.name`, e.g. `'anthropic'` / `'openai'` / `'openrouter'`. */
12
+ provider: string;
13
+ model: string;
14
+ promptTokens: number;
15
+ completionTokens: number;
16
+ createdAt: Date;
17
+ completedAt: Date | null;
18
+ }
19
+ export interface CreateAgentChangeSetInput {
20
+ organizationId: string;
21
+ createdBy?: string | null;
22
+ summary?: string | null;
23
+ provider: string;
24
+ model: string;
25
+ }
26
+ export interface CompleteAgentChangeSetInput {
27
+ status: AgentChangeSetStatus;
28
+ promptTokens?: number;
29
+ completionTokens?: number;
30
+ }
31
+ /** One mutating tool call within a turn. `versionBefore` is what an undo restores to — null
32
+ * means there's nothing to restore to (e.g. this was a `create_document`, which isn't
33
+ * undoable in this pass). */
34
+ export interface AgentOperation {
35
+ id: string;
36
+ changeSetId: string;
37
+ organizationId: string;
38
+ collection: string;
39
+ documentId: string;
40
+ toolName: string;
41
+ arguments: Record<string, unknown>;
42
+ success: boolean;
43
+ error: string | null;
44
+ versionBefore: number | null;
45
+ versionAfter: number | null;
46
+ createdAt: Date;
47
+ }
48
+ export interface RecordAgentOperationInput {
49
+ changeSetId: string;
50
+ organizationId: string;
51
+ collection: string;
52
+ documentId: string;
53
+ toolName: string;
54
+ arguments: Record<string, unknown>;
55
+ success: boolean;
56
+ error?: string | null;
57
+ versionBefore?: number | null;
58
+ versionAfter?: number | null;
59
+ }
60
+ /** A change-set with its operations attached — what the undo endpoint and the activity
61
+ * detail view both need. */
62
+ export interface AgentChangeSetWithOperations extends AgentChangeSet {
63
+ operations: AgentOperation[];
64
+ }
65
+ export interface ListAgentChangeSetsOptions {
66
+ organizationId: string;
67
+ limit?: number;
68
+ offset?: number;
69
+ }
70
+ //# sourceMappingURL=agent-change-sets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-change-sets.d.ts","sourceRoot":"","sources":["../../../src/lib/types/agent-change-sets.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,oBAAoB,GAAG,aAAa,GAAG,WAAW,GAAG,QAAQ,CAAC;AAE1E;wEACwE;AACxE,MAAM,WAAW,cAAc;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,MAAM,EAAE,oBAAoB,CAAC;IAC7B,+FAA+F;IAC/F,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,kFAAkF;IAClF,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,IAAI,CAAC;IAChB,WAAW,EAAE,IAAI,GAAG,IAAI,CAAC;CACzB;AAED,MAAM,WAAW,yBAAyB;IACzC,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,2BAA2B;IAC3C,MAAM,EAAE,oBAAoB,CAAC;IAC7B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;6BAE6B;AAC7B,MAAM,WAAW,cAAc;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,SAAS,EAAE,IAAI,CAAC;CAChB;AAED,MAAM,WAAW,yBAAyB;IACzC,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED;4BAC4B;AAC5B,MAAM,WAAW,4BAA6B,SAAQ,cAAc;IACnE,UAAU,EAAE,cAAc,EAAE,CAAC;CAC7B;AAED,MAAM,WAAW,0BAA0B;IAC1C,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB"}
@@ -0,0 +1,7 @@
1
+ // Dialect-agnostic shapes for the agent audit/undo trail — mirrors `types/events.ts`'s
2
+ // relationship to `cms_domain_events`/`cms_jobs`, but for `cms_agent_change_sets`/
3
+ // `cms_agent_operations`. One `AgentChangeSet` row per agent turn (not per mutation — a
4
+ // pure Q&A turn still costs tokens and is still worth an audit/cost row), with zero or more
5
+ // `AgentOperation` children recording the mutating tool calls that turn made.
6
+ export {};
7
+ //# sourceMappingURL=agent-change-sets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-change-sets.js","sourceRoot":"","sources":["../../../src/lib/types/agent-change-sets.ts"],"names":[],"mappings":"AAAA,uFAAuF;AACvF,mFAAmF;AACnF,wFAAwF;AACxF,4FAA4F;AAC5F,8EAA8E"}
@@ -0,0 +1,60 @@
1
+ import type { AIMessage } from '../ai/interfaces/ai-provider.js';
2
+ /** One event in an agent turn's response stream. */
3
+ export type AgentStreamEvent = {
4
+ type: 'text';
5
+ delta: string;
6
+ } | {
7
+ type: 'toolCall';
8
+ toolCallId: string;
9
+ name: string;
10
+ arguments: Record<string, unknown>;
11
+ } | {
12
+ type: 'toolResult';
13
+ toolCallId: string;
14
+ name: string;
15
+ success: boolean;
16
+ data?: unknown;
17
+ /** Present when `success` is false — a message safe to show the model/user. */
18
+ error?: string;
19
+ } | {
20
+ type: 'usage';
21
+ promptTokens: number;
22
+ completionTokens: number;
23
+ } | {
24
+ type: 'error';
25
+ message: string;
26
+ } | {
27
+ type: 'done';
28
+ /**
29
+ * `'awaiting_workspace_tool'` means the model requested one or more
30
+ * `execution: 'workspace'` tool calls this round — those can only be executed by
31
+ * the browser (they touch a live, possibly-unsaved editor draft), so the server
32
+ * stopped short of resolving them. `pendingWorkspaceCalls` lists exactly which
33
+ * ones need a result before the turn can continue; the caller resolves them
34
+ * locally, appends `tool` messages, and re-POSTs to resume — see
35
+ * `server/api/routes/agent-chat.ts` and `AgentChat.svelte`.
36
+ */
37
+ finishReason: 'stop' | 'tool_calls' | 'length' | 'error' | 'awaiting_workspace_tool';
38
+ /**
39
+ * The complete running conversation, including every intermediate
40
+ * `assistant`(toolCalls)/`tool` message this turn produced — not just the final
41
+ * user-visible text. `/api/agent/chat` is stateless per call, so the caller is
42
+ * expected to resend this wholesale as `messages` on the next turn rather than
43
+ * reconstructing it client-side (easy to get subtly wrong — see the history bug
44
+ * this replaced).
45
+ */
46
+ messages: AIMessage[];
47
+ /** Only present when `finishReason === 'awaiting_workspace_tool'`. */
48
+ pendingWorkspaceCalls?: {
49
+ toolCallId: string;
50
+ name: string;
51
+ arguments: Record<string, unknown>;
52
+ }[];
53
+ /**
54
+ * Stamped by `agent-chat.ts` (not `runAgentTurn`, which has no DB access) on every
55
+ * `done` event so a resume request can echo it back and the audit trail's
56
+ * `cms_agent_change_sets` row stays the same across a paused turn's multiple legs.
57
+ */
58
+ changeSetId?: string | null;
59
+ };
60
+ //# sourceMappingURL=agent-stream.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-stream.d.ts","sourceRoot":"","sources":["../../../src/lib/types/agent-stream.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAE9D,oDAAoD;AACpD,MAAM,MAAM,gBAAgB,GACzB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC/B;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GAC1F;IACA,IAAI,EAAE,YAAY,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,+EAA+E;IAC/E,KAAK,CAAC,EAAE,MAAM,CAAC;CACd,GACD;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,gBAAgB,EAAE,MAAM,CAAA;CAAE,GACjE;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAClC;IACA,IAAI,EAAE,MAAM,CAAC;IACb;;;;;;;;OAQG;IACH,YAAY,EAAE,MAAM,GAAG,YAAY,GAAG,QAAQ,GAAG,OAAO,GAAG,yBAAyB,CAAC;IACrF;;;;;;;OAOG;IACH,QAAQ,EAAE,SAAS,EAAE,CAAC;IACtB,sEAAsE;IACtE,qBAAqB,CAAC,EAAE;QACvB,UAAU,EAAE,MAAM,CAAC;QACnB,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACnC,EAAE,CAAC;IACJ;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B,CAAC"}
@@ -0,0 +1,12 @@
1
+ // types/agent-stream.ts
2
+ //
3
+ // Browser-facing stream contract for an agent turn — what an SSE/NDJSON chat
4
+ // endpoint actually sends over the wire. Deliberately close to `AIProviderAdapter`'s `AIStreamEvent`
5
+ // (ai/interfaces/ai-provider.ts) since most events pass through unchanged — this type
6
+ // adds the one thing the provider boundary doesn't have: the *result* of a tool call
7
+ // the runtime executed, which the browser needs to render (and which the model needs
8
+ // fed back as a `tool` message for the next round trip).
9
+ //
10
+ // Client-safe: no DB handles, no provider SDKs, just the wire shape.
11
+ export {};
12
+ //# sourceMappingURL=agent-stream.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-stream.js","sourceRoot":"","sources":["../../../src/lib/types/agent-stream.ts"],"names":[],"mappings":"AAAA,wBAAwB;AACxB,EAAE;AACF,6EAA6E;AAC7E,qGAAqG;AACrG,sFAAsF;AACtF,qFAAqF;AACrF,qFAAqF;AACrF,yDAAyD;AACzD,EAAE;AACF,qEAAqE"}
@@ -0,0 +1,65 @@
1
+ import type { z } from 'zod';
2
+ import type { Capability } from './capabilities.js';
3
+ import type { CMSInstances } from '../hooks.js';
4
+ import type { LocalAPIContext } from '../local-api/index.js';
5
+ /**
6
+ * Where a tool's `execute` actually runs.
7
+ *
8
+ * - `server`: runs entirely in this process against the database — the vast
9
+ * majority of tools (read, patch, publish, ...).
10
+ * - `workspace`: must round-trip to a live editor tab holding the in-progress
11
+ * draft (e.g. "apply this change to what's currently open, unsaved, in the
12
+ * browser"). `run-agent-turn.ts` never calls `execute` for a tool declared
13
+ * this way — it pauses the turn instead (`AgentStreamEvent`'s
14
+ * `awaiting_workspace_tool` finish reason) and the caller resolves it
15
+ * client-side against a `DocumentWorkspace` (types/document-workspace.ts),
16
+ * then resumes. Only advertised at all when `resolveAgentTools` is given a
17
+ * `documentContext` (mcp/tools.ts) — see `ai/content-workspace-tools.ts` for
18
+ * the two tools that currently use this mode.
19
+ */
20
+ export type AgentToolExecutionMode = 'server' | 'workspace';
21
+ /**
22
+ * Serializable description of a tool — the part an LLM/UI needs to know a
23
+ * tool exists and how to call it, without knowing how to run it.
24
+ */
25
+ export interface AgentToolDefinition<TInput = unknown> {
26
+ /** Unique, namespaced by package to avoid collisions (e.g. `content_patch_fields`). */
27
+ name: string;
28
+ description: string;
29
+ /**
30
+ * Whether invoking this tool can change stored data. A coarse, cheap-to-display
31
+ * hint for approval flows and audit — not itself an authorization mechanism
32
+ * (`requiredCapabilities` is what's actually enforced).
33
+ */
34
+ mutates: boolean;
35
+ /**
36
+ * Capabilities required to see AND to invoke this tool — checked at both
37
+ * advertisement (don't list a tool the caller can't use) and execution
38
+ * (don't trust the advertisement check alone). A tool hidden from an
39
+ * unauthorized caller must also reject direct invocation.
40
+ */
41
+ requiredCapabilities: Capability[];
42
+ execution: AgentToolExecutionMode;
43
+ /** zod schema for the tool's arguments — single source of truth for validation. */
44
+ inputSchema: z.ZodType<TInput>;
45
+ }
46
+ /** Outcome of a single tool call. */
47
+ export interface AgentToolResult {
48
+ success: boolean;
49
+ data?: unknown;
50
+ /** Present when `success` is false — a message safe to show the model/user. */
51
+ error?: string;
52
+ }
53
+ /** Everything an `execute` function needs to act on behalf of the calling request. */
54
+ export interface AgentToolExecutionContext {
55
+ aphexCMS: CMSInstances;
56
+ context: LocalAPIContext;
57
+ }
58
+ /**
59
+ * Runs a tool call. Receives services via `ctx` at call time rather than
60
+ * static import, so a module defining an executor never has a heavy/server
61
+ * import at its top level — safe to sit alongside a definition in a plugin
62
+ * part that's also referenced from client-shared code.
63
+ */
64
+ export type AgentToolExecutor<TInput = unknown> = (input: TInput, ctx: AgentToolExecutionContext) => Promise<AgentToolResult>;
65
+ //# sourceMappingURL=agent-tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-tools.d.ts","sourceRoot":"","sources":["../../../src/lib/types/agent-tools.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAE1D;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,sBAAsB,GAAG,QAAQ,GAAG,WAAW,CAAC;AAE5D;;;GAGG;AACH,MAAM,WAAW,mBAAmB,CAAC,MAAM,GAAG,OAAO;IACpD,uFAAuF;IACvF,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,OAAO,EAAE,OAAO,CAAC;IACjB;;;;;OAKG;IACH,oBAAoB,EAAE,UAAU,EAAE,CAAC;IACnC,SAAS,EAAE,sBAAsB,CAAC;IAClC,mFAAmF;IACnF,WAAW,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;CAC/B;AAED,qCAAqC;AACrC,MAAM,WAAW,eAAe;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,+EAA+E;IAC/E,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED,sFAAsF;AACtF,MAAM,WAAW,yBAAyB;IACzC,QAAQ,EAAE,YAAY,CAAC;IACvB,OAAO,EAAE,eAAe,CAAC;CACzB;AAED;;;;;GAKG;AACH,MAAM,MAAM,iBAAiB,CAAC,MAAM,GAAG,OAAO,IAAI,CACjD,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,yBAAyB,KAC1B,OAAO,CAAC,eAAe,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=agent-tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-tools.js","sourceRoot":"","sources":["../../../src/lib/types/agent-tools.ts"],"names":[],"mappings":""}
@@ -4,6 +4,7 @@ import type { CacheAdapter } from '../cache/index.js';
4
4
  import type { DatabaseAdapter } from '../db/index.js';
5
5
  import type { StorageAdapter } from '../storage/interfaces/index.js';
6
6
  import type { EmailAdapter } from '../email/index.js';
7
+ import type { AIProviderAdapter } from '../ai/index.js';
7
8
  import type { GraphQLConfig } from '../graphql/index.js';
8
9
  import type { AphexEnv } from '../server/api/index.js';
9
10
  import type { SchemaType } from './schemas.js';
@@ -25,6 +26,24 @@ export interface CMSConfig {
25
26
  plugins?: CMSPlugin[];
26
27
  storage?: StorageAdapter | null;
27
28
  email?: EmailAdapter | null;
29
+ /** Model backend for the in-admin agent. Omit to leave the agent panel disabled. */
30
+ aiProvider?: AIProviderAdapter | null;
31
+ /**
32
+ * Default provider-specific model id used by `/api/agent/chat`, e.g.
33
+ * `claude-sonnet-4-5` (Anthropic) or `gpt-4.1` (OpenAI/OpenRouter). A request may
34
+ * override it per-call. Required when `aiProvider` is set — the route 501s without it.
35
+ */
36
+ agentModel?: string;
37
+ /**
38
+ * System prompt injected ahead of every `/api/agent/chat` turn (fresh per request — never
39
+ * persisted into the conversation itself, so changing this takes effect immediately for
40
+ * open conversations too). Overrides the built-in default (`ai/default-system-prompt.ts`),
41
+ * which only covers behavioral guardrails (draft-first, confirm before broad changes) —
42
+ * schema/tool knowledge is already self-describing via the `describe_cms` tool, so it
43
+ * doesn't need to be repeated here. Useful for an agency giving a client's deployment its
44
+ * own tone or house rules.
45
+ */
46
+ agentSystemPrompt?: string;
28
47
  customization?: {
29
48
  branding?: {
30
49
  title?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/lib/types/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/lib/types/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ /** A change to apply to the open document's in-memory draft. Extensible — a future
2
+ * operation kind (e.g. replaying a multiplayer remote op) is a new variant here, routed
3
+ * through the same `apply()`/`validate()`/CAS-save pipeline, not a new bridge. */
4
+ export type DocumentWorkspaceOperation = {
5
+ type: 'patchFields';
6
+ /** Shallow-merged onto the current draft, same semantics as a manual field edit and as
7
+ * `CollectionAPI.update`'s own merge — whole-value replacement per top-level field key. */
8
+ fields: Record<string, unknown>;
9
+ };
10
+ /** Who's driving a batch of operations. `'agent'` is the only real source today; the type
11
+ * stays an open string so a future source (e.g. a multiplayer sync layer) doesn't require
12
+ * changing this type — just adding a caller. */
13
+ export type DocumentWorkspaceBatchSource = 'agent' | (string & {});
14
+ export interface DocumentWorkspaceSnapshot {
15
+ documentId: string | null;
16
+ collection: string;
17
+ data: Record<string, unknown>;
18
+ status: 'new' | 'draft' | 'published' | 'unpublished';
19
+ revision: number | null;
20
+ }
21
+ export interface DocumentWorkspaceValidationResult {
22
+ isValid: boolean;
23
+ errors: {
24
+ field: string;
25
+ errors: string[];
26
+ }[];
27
+ }
28
+ export interface DocumentWorkspaceSaveResult {
29
+ success: boolean;
30
+ revision?: number;
31
+ /** True when the write was rejected by the CAS revision check — the caller should treat
32
+ * this distinctly from a generic failure (matches the existing 409 handling in
33
+ * `DocumentEditor.svelte`'s manual save/publish/restore paths). */
34
+ conflict?: boolean;
35
+ error?: string;
36
+ }
37
+ export interface DocumentWorkspace {
38
+ getSnapshot(): DocumentWorkspaceSnapshot;
39
+ getSelection(): {
40
+ fieldName: string | null;
41
+ };
42
+ /** Mutates the in-memory draft only — never persists. */
43
+ apply(operation: DocumentWorkspaceOperation): void;
44
+ validate(): Promise<DocumentWorkspaceValidationResult>;
45
+ flushSave(expectedRevision: number | undefined): Promise<DocumentWorkspaceSaveResult>;
46
+ publish(expectedRevision: number | undefined): Promise<DocumentWorkspaceSaveResult>;
47
+ /** Suppresses the editor's own autosave debounce until `endBatch()` — so a burst of
48
+ * `apply()` calls (e.g. one agent turn's patches) doesn't produce one CAS write per
49
+ * patch. Exactly one `flushSave` should follow before/at `endBatch()`. */
50
+ beginBatch(source: DocumentWorkspaceBatchSource): void;
51
+ endBatch(): void;
52
+ }
53
+ //# sourceMappingURL=document-workspace.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document-workspace.d.ts","sourceRoot":"","sources":["../../../src/lib/types/document-workspace.ts"],"names":[],"mappings":"AAcA;;kFAEkF;AAClF,MAAM,MAAM,0BAA0B,GAAG;IACxC,IAAI,EAAE,aAAa,CAAC;IACpB;+FAC2F;IAC3F,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC,CAAC;AAEF;;gDAEgD;AAChD,MAAM,MAAM,4BAA4B,GAAG,OAAO,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;AAEnE,MAAM,WAAW,yBAAyB;IACzC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,MAAM,EAAE,KAAK,GAAG,OAAO,GAAG,WAAW,GAAG,aAAa,CAAC;IACtD,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED,MAAM,WAAW,iCAAiC;IACjD,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE,EAAE,CAAC;CAC9C;AAED,MAAM,WAAW,2BAA2B;IAC3C,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;uEAEmE;IACnE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,iBAAiB;IACjC,WAAW,IAAI,yBAAyB,CAAC;IACzC,YAAY,IAAI;QAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;IAC7C,yDAAyD;IACzD,KAAK,CAAC,SAAS,EAAE,0BAA0B,GAAG,IAAI,CAAC;IACnD,QAAQ,IAAI,OAAO,CAAC,iCAAiC,CAAC,CAAC;IACvD,SAAS,CAAC,gBAAgB,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,2BAA2B,CAAC,CAAC;IACtF,OAAO,CAAC,gBAAgB,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,2BAA2B,CAAC,CAAC;IACpF;;8EAE0E;IAC1E,UAAU,CAAC,MAAM,EAAE,4BAA4B,GAAG,IAAI,CAAC;IACvD,QAAQ,IAAI,IAAI,CAAC;CACjB"}
@@ -0,0 +1,15 @@
1
+ // types/document-workspace.ts
2
+ //
3
+ // A live handle onto a document currently open (and possibly unsaved) in an editor tab —
4
+ // not an AI-specific type. The agent's `content_patch_fields`/`content_save_draft` tools
5
+ // (ai/content-workspace-tools.ts) are its first consumer, not its only intended one: a
6
+ // future multiplayer feature would need the exact same primitives (apply an incoming
7
+ // operation to the live draft, batch/suppress autosave while a burst of operations lands,
8
+ // find which document sessions are open in this tab). `apply()`'s operation type and
9
+ // `beginBatch()`'s source are both open unions for that reason — a new consumer is a new
10
+ // union member, not a redesign of this interface.
11
+ //
12
+ // Client-safe: no server imports. Implemented by `DocumentEditor.svelte`, registered into
13
+ // `document-workspace-registry.svelte.ts` while mounted.
14
+ export {};
15
+ //# sourceMappingURL=document-workspace.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document-workspace.js","sourceRoot":"","sources":["../../../src/lib/types/document-workspace.ts"],"names":[],"mappings":"AAAA,8BAA8B;AAC9B,EAAE;AACF,yFAAyF;AACzF,yFAAyF;AACzF,uFAAuF;AACvF,qFAAqF;AACrF,0FAA0F;AAC1F,qFAAqF;AACrF,yFAAyF;AACzF,kDAAkD;AAClD,EAAE;AACF,0FAA0F;AAC1F,yDAAyD"}
@@ -10,6 +10,10 @@ export interface Document {
10
10
  draftData: any;
11
11
  publishedData: any;
12
12
  publishedHash: string | null;
13
+ /** Monotonic draft revision, incremented on every draft write. Used as the
14
+ * compare-and-swap guard on `updateDocDraft`/`publishDoc`/`unpublishDoc` —
15
+ * callers pass the revision they last read as `expectedRevision`. */
16
+ revision: number;
13
17
  createdBy: string | AuthUser | null;
14
18
  updatedBy: string | null;
15
19
  publishedAt: Date | null;
@@ -26,6 +30,7 @@ export interface NewDocument {
26
30
  draftData?: any;
27
31
  publishedData?: any;
28
32
  publishedHash?: string | null;
33
+ revision?: number;
29
34
  createdBy?: string | null;
30
35
  updatedBy?: string | null;
31
36
  publishedAt?: Date | null;
@@ -1 +1 @@
1
- {"version":3,"file":"document.d.ts","sourceRoot":"","sources":["../../../src/lib/types/document.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C;;GAEG;AACH,MAAM,WAAW,QAAQ;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,GAAG,WAAW,GAAG,aAAa,GAAG,IAAI,CAAC;IACrD,SAAS,EAAE,GAAG,CAAC;IACf,aAAa,EAAE,GAAG,CAAC;IACnB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,SAAS,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAAC;IACpC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,WAAW,EAAE,IAAI,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,IAAI,GAAG,IAAI,CAAC;IACvB,SAAS,EAAE,IAAI,GAAG,IAAI,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC3B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,OAAO,GAAG,WAAW,GAAG,aAAa,GAAG,IAAI,CAAC;IACtD,SAAS,CAAC,EAAE,GAAG,CAAC;IAChB,aAAa,CAAC,EAAE,GAAG,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,WAAW,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IAC1B,SAAS,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACxB,SAAS,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;CACxB"}
1
+ {"version":3,"file":"document.d.ts","sourceRoot":"","sources":["../../../src/lib/types/document.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C;;GAEG;AACH,MAAM,WAAW,QAAQ;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,GAAG,WAAW,GAAG,aAAa,GAAG,IAAI,CAAC;IACrD,SAAS,EAAE,GAAG,CAAC;IACf,aAAa,EAAE,GAAG,CAAC;IACnB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B;;0EAEsE;IACtE,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAAC;IACpC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,WAAW,EAAE,IAAI,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,IAAI,GAAG,IAAI,CAAC;IACvB,SAAS,EAAE,IAAI,GAAG,IAAI,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC3B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,OAAO,GAAG,WAAW,GAAG,aAAa,GAAG,IAAI,CAAC;IACtD,SAAS,CAAC,EAAE,GAAG,CAAC;IAChB,aAAa,CAAC,EAAE,GAAG,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,WAAW,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IAC1B,SAAS,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACxB,SAAS,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;CACxB"}
@@ -7,8 +7,10 @@ export * from './user.js';
7
7
  export * from './sidebar.js';
8
8
  export * from './organization.js';
9
9
  export * from './capabilities.js';
10
+ export * from './agent-tools.js';
10
11
  export * from './filters.js';
11
12
  export * from './instance.js';
12
13
  export * from './version.js';
13
14
  export * from './events.js';
15
+ export * from './agent-change-sets.js';
14
16
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/types/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,QAAQ,CAAC;AACvB,cAAc,WAAW,CAAC;AAC1B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/types/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,QAAQ,CAAC;AACvB,cAAc,WAAW,CAAC;AAC1B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,qBAAqB,CAAC"}
@@ -7,8 +7,10 @@ export * from './user.js';
7
7
  export * from './sidebar.js';
8
8
  export * from './organization.js';
9
9
  export * from './capabilities.js';
10
+ export * from './agent-tools.js';
10
11
  export * from './filters.js';
11
12
  export * from './instance.js';
12
13
  export * from './version.js';
13
14
  export * from './events.js';
15
+ export * from './agent-change-sets.js';
14
16
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/types/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,QAAQ,CAAC;AACvB,cAAc,WAAW,CAAC;AAC1B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/types/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,QAAQ,CAAC;AACvB,cAAc,WAAW,CAAC;AAC1B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,qBAAqB,CAAC"}
@@ -1,4 +1,4 @@
1
1
  export function isBlockArray(field) {
2
- return field.of.some((ref) => ref.type === 'block');
2
+ return (field.of ?? []).some((ref) => ref.type === 'block');
3
3
  }
4
4
  //# sourceMappingURL=schemas.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"schemas.js","sourceRoot":"","sources":["../../../src/lib/types/schemas.ts"],"names":[],"mappings":"AA2QA,MAAM,UAAU,YAAY,CAAC,KAAiB;IAC7C,OAAO,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC;AACrD,CAAC"}
1
+ {"version":3,"file":"schemas.js","sourceRoot":"","sources":["../../../src/lib/types/schemas.ts"],"names":[],"mappings":"AA2QA,MAAM,UAAU,YAAY,CAAC,KAAiB;IAC7C,OAAO,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC;AAC7D,CAAC"}
@@ -0,0 +1,11 @@
1
+ export declare const MAX_REMOTE_FILE_BYTES: number;
2
+ export interface RemoteFile {
3
+ buffer: Buffer;
4
+ contentType: string | null;
5
+ }
6
+ /** Fetch a URL with SSRF guards: http(s)-only, private/link-local/multicast IPs blocked and the
7
+ * validated address pinned for the actual connection (re-checked and re-pinned on every redirect
8
+ * hop), a request timeout, and a streamed size cap (not just a Content-Length check, since that
9
+ * header can lie). */
10
+ export declare function fetchRemoteFile(url: string): Promise<RemoteFile>;
11
+ //# sourceMappingURL=fetch-remote-file.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch-remote-file.d.ts","sourceRoot":"","sources":["../../../src/lib/utils/fetch-remote-file.ts"],"names":[],"mappings":"AAeA,eAAO,MAAM,qBAAqB,QAAmB,CAAC;AA6EtD,MAAM,WAAW,UAAU;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED;;;sBAGsB;AACtB,wBAAsB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAuEtE"}
@@ -0,0 +1,169 @@
1
+ // Fetches a remote file for the `upload_asset` agent tool's `url` input. The caller (an LLM)
2
+ // can be steered by content it merely *read* (a document field, a scraped page) — an indirect
3
+ // prompt-injection vector — so this is a genuine SSRF surface, not just a convenience fetch.
4
+ //
5
+ // Every redirect hop re-resolves and re-checks the hostname; a naive "check the input URL once"
6
+ // implementation is bypassable by redirecting to a private address only after the first check
7
+ // passes. More importantly, the resolved IP is *pinned* for the actual connection via a custom
8
+ // `undici` dispatcher — resolving with `dns.lookup()` to validate, then handing the plain
9
+ // hostname to `fetch()` and letting it resolve again to connect, reopens the same hole via DNS
10
+ // rebinding (a short-TTL record that answers differently a few hundred ms apart): the address
11
+ // that gets validated and the address that gets connected to must be the exact same one.
12
+ import { lookup } from 'node:dns/promises';
13
+ import net from 'node:net';
14
+ import { Agent, fetch as undiciFetch } from 'undici';
15
+ export const MAX_REMOTE_FILE_BYTES = 10 * 1024 * 1024; // matches the API's global JSON body cap
16
+ const FETCH_TIMEOUT_MS = 10_000;
17
+ const MAX_REDIRECTS = 5;
18
+ const TRANSIENT_RETRY_DELAY_MS = 300;
19
+ const TRANSIENT_STATUSES = new Set([502, 503, 504]);
20
+ // A bare request with no headers reads as bot traffic to a lot of image CDNs (including
21
+ // Unsplash's), which will deprioritize or outright reject it — sending a normal-looking
22
+ // User-Agent/Accept pair alone clears up a meaningful share of otherwise-transient failures.
23
+ const REQUEST_HEADERS = {
24
+ 'User-Agent': 'AphexCMS-Agent-Fetch/1.0 (+asset upload tool)',
25
+ Accept: 'image/*,*/*;q=0.8'
26
+ };
27
+ function sleep(ms) {
28
+ return new Promise((resolve) => setTimeout(resolve, ms));
29
+ }
30
+ function isPrivateOrReservedIp(ip) {
31
+ if (net.isIPv4(ip)) {
32
+ const octets = ip.split('.').map(Number);
33
+ const a = octets[0] ?? -1;
34
+ const b = octets[1] ?? -1;
35
+ if (a === 10 || a === 127 || a === 0)
36
+ return true;
37
+ if (a === 169 && b === 254)
38
+ return true; // link-local — includes cloud metadata endpoints
39
+ if (a === 172 && b >= 16 && b <= 31)
40
+ return true;
41
+ if (a === 192 && b === 168)
42
+ return true;
43
+ if (a === 100 && b >= 64 && b <= 127)
44
+ return true; // CGNAT
45
+ if (a >= 224)
46
+ return true; // multicast (224-239) + reserved/broadcast (240-255)
47
+ return false;
48
+ }
49
+ if (net.isIPv6(ip)) {
50
+ const lower = ip.toLowerCase();
51
+ if (lower === '::1' || lower === '::')
52
+ return true;
53
+ if (lower.startsWith('fe80:') || lower.startsWith('fc') || lower.startsWith('fd'))
54
+ return true;
55
+ if (lower.startsWith('ff'))
56
+ return true; // multicast
57
+ if (lower.startsWith('::ffff:'))
58
+ return isPrivateOrReservedIp(lower.slice(7));
59
+ return false;
60
+ }
61
+ return true; // unrecognized address shape — fail closed
62
+ }
63
+ async function resolvePinnedHost(hostname) {
64
+ if (hostname.toLowerCase() === 'localhost') {
65
+ throw new Error('URL host is not allowed.');
66
+ }
67
+ const records = await lookup(hostname, { all: true });
68
+ if (records.length === 0)
69
+ throw new Error('Could not resolve host.');
70
+ for (const { address } of records) {
71
+ if (isPrivateOrReservedIp(address)) {
72
+ throw new Error('URL resolves to a private/internal address, which is not allowed.');
73
+ }
74
+ }
75
+ const chosen = records[0];
76
+ return { address: chosen.address, family: chosen.family === 6 ? 6 : 4 };
77
+ }
78
+ /** A dispatcher whose DNS step is short-circuited to the one address we already validated —
79
+ * whatever hostname undici asks it to resolve, it hands back this exact IP, so the socket that
80
+ * actually opens is guaranteed to be the one that passed `isPrivateOrReservedIp`. The hostname
81
+ * itself still flows through normally for the Host header and TLS SNI/cert validation. */
82
+ function pinnedDispatcher(host) {
83
+ return new Agent({
84
+ connect: {
85
+ lookup: (_hostname, options, callback) => {
86
+ const result = { address: host.address, family: host.family };
87
+ callback(null, options.all ? [result] : result.address);
88
+ }
89
+ }
90
+ });
91
+ }
92
+ /** Fetch a URL with SSRF guards: http(s)-only, private/link-local/multicast IPs blocked and the
93
+ * validated address pinned for the actual connection (re-checked and re-pinned on every redirect
94
+ * hop), a request timeout, and a streamed size cap (not just a Content-Length check, since that
95
+ * header can lie). */
96
+ export async function fetchRemoteFile(url) {
97
+ let current = url;
98
+ for (let hop = 0; hop <= MAX_REDIRECTS; hop++) {
99
+ const parsed = new URL(current);
100
+ if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
101
+ throw new Error('Only http/https URLs are allowed.');
102
+ }
103
+ const pinnedHost = await resolvePinnedHost(parsed.hostname);
104
+ let res;
105
+ // One retry, only for a transient upstream 5xx (502/503/504) — not for 4xx (a bad URL
106
+ // won't fix itself) and not for a network-level exception (already a distinct failure
107
+ // mode, handled by the catch below without a retry).
108
+ for (let attempt = 0; attempt < 2; attempt++) {
109
+ const controller = new AbortController();
110
+ const timeout = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
111
+ try {
112
+ res = await undiciFetch(current, {
113
+ redirect: 'manual',
114
+ signal: controller.signal,
115
+ dispatcher: pinnedDispatcher(pinnedHost),
116
+ headers: REQUEST_HEADERS
117
+ });
118
+ }
119
+ catch (err) {
120
+ throw new Error(`Fetch failed: ${err instanceof Error ? err.message : 'network error'}`);
121
+ }
122
+ finally {
123
+ clearTimeout(timeout);
124
+ }
125
+ if (attempt === 0 && TRANSIENT_STATUSES.has(res.status)) {
126
+ await sleep(TRANSIENT_RETRY_DELAY_MS);
127
+ continue;
128
+ }
129
+ break;
130
+ }
131
+ res = res;
132
+ if (res.status >= 300 && res.status < 400) {
133
+ const location = res.headers.get('location');
134
+ if (!location)
135
+ throw new Error('Redirect response missing a Location header.');
136
+ current = new URL(location, current).toString();
137
+ continue;
138
+ }
139
+ if (!res.ok) {
140
+ const transientNote = TRANSIENT_STATUSES.has(res.status)
141
+ ? ' (upstream temporarily unavailable, retried once)'
142
+ : '';
143
+ throw new Error(`Fetch failed with status ${res.status}.${transientNote}`);
144
+ }
145
+ const contentLength = res.headers.get('content-length');
146
+ if (contentLength && Number(contentLength) > MAX_REMOTE_FILE_BYTES) {
147
+ throw new Error(`File too large (max ${MAX_REMOTE_FILE_BYTES / (1024 * 1024)}MB).`);
148
+ }
149
+ if (!res.body)
150
+ throw new Error('Response had no body.');
151
+ const reader = res.body.getReader();
152
+ const chunks = [];
153
+ let total = 0;
154
+ for (;;) {
155
+ const { done, value } = await reader.read();
156
+ if (done)
157
+ break;
158
+ total += value.byteLength;
159
+ if (total > MAX_REMOTE_FILE_BYTES) {
160
+ await reader.cancel();
161
+ throw new Error(`File too large (max ${MAX_REMOTE_FILE_BYTES / (1024 * 1024)}MB).`);
162
+ }
163
+ chunks.push(value);
164
+ }
165
+ return { buffer: Buffer.concat(chunks), contentType: res.headers.get('content-type') };
166
+ }
167
+ throw new Error('Too many redirects.');
168
+ }
169
+ //# sourceMappingURL=fetch-remote-file.js.map