@aglyn/plugins-ai 1.0.0-beta.143

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 (717) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +25 -0
  3. package/package.json +60 -0
  4. package/src/index.d.ts +21 -0
  5. package/src/index.js +22 -0
  6. package/src/index.js.map +1 -0
  7. package/src/lib/activity/ai-activity-actions.d.ts +106 -0
  8. package/src/lib/activity/ai-activity-actions.js +209 -0
  9. package/src/lib/activity/ai-activity-actions.js.map +1 -0
  10. package/src/lib/activity/ai-activity.d.ts +219 -0
  11. package/src/lib/activity/ai-activity.js +251 -0
  12. package/src/lib/activity/ai-activity.js.map +1 -0
  13. package/src/lib/billing/ai-overage-charge.d.ts +102 -0
  14. package/src/lib/billing/ai-overage-charge.js +258 -0
  15. package/src/lib/billing/ai-overage-charge.js.map +1 -0
  16. package/src/lib/billing/ai-overage-close.d.ts +62 -0
  17. package/src/lib/billing/ai-overage-close.js +129 -0
  18. package/src/lib/billing/ai-overage-close.js.map +1 -0
  19. package/src/lib/billing/ai-overage-cutover.d.ts +63 -0
  20. package/src/lib/billing/ai-overage-cutover.js +114 -0
  21. package/src/lib/billing/ai-overage-cutover.js.map +1 -0
  22. package/src/lib/billing/ai-overage-events.d.ts +77 -0
  23. package/src/lib/billing/ai-overage-events.js +174 -0
  24. package/src/lib/billing/ai-overage-events.js.map +1 -0
  25. package/src/lib/billing/ai-overage-gate.d.ts +147 -0
  26. package/src/lib/billing/ai-overage-gate.js +177 -0
  27. package/src/lib/billing/ai-overage-gate.js.map +1 -0
  28. package/src/lib/billing/ai-overage-ledger.d.ts +135 -0
  29. package/src/lib/billing/ai-overage-ledger.js +278 -0
  30. package/src/lib/billing/ai-overage-ledger.js.map +1 -0
  31. package/src/lib/billing/ai-overage-standing-writes.d.ts +110 -0
  32. package/src/lib/billing/ai-overage-standing-writes.js +205 -0
  33. package/src/lib/billing/ai-overage-standing-writes.js.map +1 -0
  34. package/src/lib/billing/ai-overage-standing.d.ts +168 -0
  35. package/src/lib/billing/ai-overage-standing.js +215 -0
  36. package/src/lib/billing/ai-overage-standing.js.map +1 -0
  37. package/src/lib/billing/ai-overage-trigger.d.ts +30 -0
  38. package/src/lib/billing/ai-overage-trigger.js +76 -0
  39. package/src/lib/billing/ai-overage-trigger.js.map +1 -0
  40. package/src/lib/components/ai-allotment-editor.component.d.ts +40 -0
  41. package/src/lib/components/ai-allotment-editor.component.js +213 -0
  42. package/src/lib/components/ai-allotment-editor.component.js.map +1 -0
  43. package/src/lib/components/ai-assist-actions-context.d.ts +13 -0
  44. package/src/lib/components/ai-assist-actions-context.js +21 -0
  45. package/src/lib/components/ai-assist-actions-context.js.map +1 -0
  46. package/src/lib/components/ai-assist-provider.component.d.ts +51 -0
  47. package/src/lib/components/ai-assist-provider.component.js +519 -0
  48. package/src/lib/components/ai-assist-provider.component.js.map +1 -0
  49. package/src/lib/components/ai-brief-dialog.component.d.ts +56 -0
  50. package/src/lib/components/ai-brief-dialog.component.js +319 -0
  51. package/src/lib/components/ai-brief-dialog.component.js.map +1 -0
  52. package/src/lib/components/ai-collaborator-permissions-column.component.d.ts +32 -0
  53. package/src/lib/components/ai-collaborator-permissions-column.component.js +132 -0
  54. package/src/lib/components/ai-collaborator-permissions-column.component.js.map +1 -0
  55. package/src/lib/components/ai-credits-card.component.d.ts +34 -0
  56. package/src/lib/components/ai-credits-card.component.js +131 -0
  57. package/src/lib/components/ai-credits-card.component.js.map +1 -0
  58. package/src/lib/components/ai-credits-columns.component.d.ts +56 -0
  59. package/src/lib/components/ai-credits-columns.component.js +118 -0
  60. package/src/lib/components/ai-credits-columns.component.js.map +1 -0
  61. package/src/lib/components/ai-crm-email-draft.component.d.ts +17 -0
  62. package/src/lib/components/ai-crm-email-draft.component.js +159 -0
  63. package/src/lib/components/ai-crm-email-draft.component.js.map +1 -0
  64. package/src/lib/components/ai-crm-import-mapping.component.d.ts +20 -0
  65. package/src/lib/components/ai-crm-import-mapping.component.js +167 -0
  66. package/src/lib/components/ai-crm-import-mapping.component.js.map +1 -0
  67. package/src/lib/components/ai-crm-record-card.component.d.ts +27 -0
  68. package/src/lib/components/ai-crm-record-card.component.js +263 -0
  69. package/src/lib/components/ai-crm-record-card.component.js.map +1 -0
  70. package/src/lib/components/ai-describe-automation.component.d.ts +31 -0
  71. package/src/lib/components/ai-describe-automation.component.js +226 -0
  72. package/src/lib/components/ai-describe-automation.component.js.map +1 -0
  73. package/src/lib/components/ai-describe-button.component.d.ts +39 -0
  74. package/src/lib/components/ai-describe-button.component.js +87 -0
  75. package/src/lib/components/ai-describe-button.component.js.map +1 -0
  76. package/src/lib/components/ai-describe-page.component.d.ts +26 -0
  77. package/src/lib/components/ai-describe-page.component.js +18 -0
  78. package/src/lib/components/ai-describe-page.component.js.map +1 -0
  79. package/src/lib/components/ai-experiment-cards.component.d.ts +75 -0
  80. package/src/lib/components/ai-experiment-cards.component.js +573 -0
  81. package/src/lib/components/ai-experiment-cards.component.js.map +1 -0
  82. package/src/lib/components/ai-explain-automation.component.d.ts +31 -0
  83. package/src/lib/components/ai-explain-automation.component.js +265 -0
  84. package/src/lib/components/ai-explain-automation.component.js.map +1 -0
  85. package/src/lib/components/ai-insight-dialog.component.d.ts +37 -0
  86. package/src/lib/components/ai-insight-dialog.component.js +441 -0
  87. package/src/lib/components/ai-insight-dialog.component.js.map +1 -0
  88. package/src/lib/components/ai-job-plan.component.d.ts +46 -0
  89. package/src/lib/components/ai-job-plan.component.js +192 -0
  90. package/src/lib/components/ai-job-plan.component.js.map +1 -0
  91. package/src/lib/components/ai-model-selector.component.d.ts +21 -0
  92. package/src/lib/components/ai-model-selector.component.js +109 -0
  93. package/src/lib/components/ai-model-selector.component.js.map +1 -0
  94. package/src/lib/components/ai-page-brief-dialog.component.d.ts +29 -0
  95. package/src/lib/components/ai-page-brief-dialog.component.js +27 -0
  96. package/src/lib/components/ai-page-brief-dialog.component.js.map +1 -0
  97. package/src/lib/components/ai-permissions-on-host.component.d.ts +55 -0
  98. package/src/lib/components/ai-permissions-on-host.component.js +91 -0
  99. package/src/lib/components/ai-permissions-on-host.component.js.map +1 -0
  100. package/src/lib/components/ai-product-copy-card.component.d.ts +25 -0
  101. package/src/lib/components/ai-product-copy-card.component.js +328 -0
  102. package/src/lib/components/ai-product-copy-card.component.js.map +1 -0
  103. package/src/lib/components/ai-product-import-option.component.d.ts +14 -0
  104. package/src/lib/components/ai-product-import-option.component.js +58 -0
  105. package/src/lib/components/ai-product-import-option.component.js.map +1 -0
  106. package/src/lib/components/ai-products-hub-card.component.d.ts +15 -0
  107. package/src/lib/components/ai-products-hub-card.component.js +418 -0
  108. package/src/lib/components/ai-products-hub-card.component.js.map +1 -0
  109. package/src/lib/components/ai-products-proposals.component.d.ts +19 -0
  110. package/src/lib/components/ai-products-proposals.component.js +547 -0
  111. package/src/lib/components/ai-products-proposals.component.js.map +1 -0
  112. package/src/lib/components/ai-save-as-component.component.d.ts +38 -0
  113. package/src/lib/components/ai-save-as-component.component.js +231 -0
  114. package/src/lib/components/ai-save-as-component.component.js.map +1 -0
  115. package/src/lib/components/ai-seo-audit-card.component.d.ts +9 -0
  116. package/src/lib/components/ai-seo-audit-card.component.js +620 -0
  117. package/src/lib/components/ai-seo-audit-card.component.js.map +1 -0
  118. package/src/lib/components/ai-seo-fields-card.component.d.ts +10 -0
  119. package/src/lib/components/ai-seo-fields-card.component.js +453 -0
  120. package/src/lib/components/ai-seo-fields-card.component.js.map +1 -0
  121. package/src/lib/components/ai-site-batch-card.component.d.ts +32 -0
  122. package/src/lib/components/ai-site-batch-card.component.js +531 -0
  123. package/src/lib/components/ai-site-batch-card.component.js.map +1 -0
  124. package/src/lib/components/ai-site-seo-start-card.component.d.ts +26 -0
  125. package/src/lib/components/ai-site-seo-start-card.component.js +178 -0
  126. package/src/lib/components/ai-site-seo-start-card.component.js.map +1 -0
  127. package/src/lib/components/ai-site-start-card.component.d.ts +19 -0
  128. package/src/lib/components/ai-site-start-card.component.js +348 -0
  129. package/src/lib/components/ai-site-start-card.component.js.map +1 -0
  130. package/src/lib/components/ai-template-collection-field.component.d.ts +32 -0
  131. package/src/lib/components/ai-template-collection-field.component.js +63 -0
  132. package/src/lib/components/ai-template-collection-field.component.js.map +1 -0
  133. package/src/lib/components/ai-theme-proposal-card.component.d.ts +6 -0
  134. package/src/lib/components/ai-theme-proposal-card.component.js +619 -0
  135. package/src/lib/components/ai-theme-proposal-card.component.js.map +1 -0
  136. package/src/lib/components/ai-usage-strip.component.d.ts +27 -0
  137. package/src/lib/components/ai-usage-strip.component.js +145 -0
  138. package/src/lib/components/ai-usage-strip.component.js.map +1 -0
  139. package/src/lib/components/assist-edit-canvas.d.ts +169 -0
  140. package/src/lib/components/assist-edit-canvas.js +636 -0
  141. package/src/lib/components/assist-edit-canvas.js.map +1 -0
  142. package/src/lib/components/assist-edit-card.component.d.ts +16 -0
  143. package/src/lib/components/assist-edit-card.component.js +181 -0
  144. package/src/lib/components/assist-edit-card.component.js.map +1 -0
  145. package/src/lib/components/assist-jobs-drawer.component.d.ts +72 -0
  146. package/src/lib/components/assist-jobs-drawer.component.js +626 -0
  147. package/src/lib/components/assist-jobs-drawer.component.js.map +1 -0
  148. package/src/lib/components/assist-panel.component.d.ts +136 -0
  149. package/src/lib/components/assist-panel.component.js +1099 -0
  150. package/src/lib/components/assist-panel.component.js.map +1 -0
  151. package/src/lib/components/assist-signals-page.component.d.ts +3 -0
  152. package/src/lib/components/assist-signals-page.component.js +1017 -0
  153. package/src/lib/components/assist-signals-page.component.js.map +1 -0
  154. package/src/lib/components/besigner-ai-controls.component.d.ts +29 -0
  155. package/src/lib/components/besigner-ai-controls.component.js +81 -0
  156. package/src/lib/components/besigner-ai-controls.component.js.map +1 -0
  157. package/src/lib/components/billing-ai-allotments.component.d.ts +36 -0
  158. package/src/lib/components/billing-ai-allotments.component.js +486 -0
  159. package/src/lib/components/billing-ai-allotments.component.js.map +1 -0
  160. package/src/lib/components/billing-ai-top-users.component.d.ts +44 -0
  161. package/src/lib/components/billing-ai-top-users.component.js +304 -0
  162. package/src/lib/components/billing-ai-top-users.component.js.map +1 -0
  163. package/src/lib/components/billing-assist-overage-card.component.d.ts +69 -0
  164. package/src/lib/components/billing-assist-overage-card.component.js +437 -0
  165. package/src/lib/components/billing-assist-overage-card.component.js.map +1 -0
  166. package/src/lib/components/host-ai-allotments.component.d.ts +40 -0
  167. package/src/lib/components/host-ai-allotments.component.js +239 -0
  168. package/src/lib/components/host-ai-allotments.component.js.map +1 -0
  169. package/src/lib/components/member-ai-allotment-card.component.d.ts +28 -0
  170. package/src/lib/components/member-ai-allotment-card.component.js +172 -0
  171. package/src/lib/components/member-ai-allotment-card.component.js.map +1 -0
  172. package/src/lib/components/member-ai-usage-card.component.d.ts +28 -0
  173. package/src/lib/components/member-ai-usage-card.component.js +240 -0
  174. package/src/lib/components/member-ai-usage-card.component.js.map +1 -0
  175. package/src/lib/components/staff-org-ai-card.component.d.ts +17 -0
  176. package/src/lib/components/staff-org-ai-card.component.js +739 -0
  177. package/src/lib/components/staff-org-ai-card.component.js.map +1 -0
  178. package/src/lib/components/staff-org-usage-ai-columns.component.d.ts +41 -0
  179. package/src/lib/components/staff-org-usage-ai-columns.component.js +65 -0
  180. package/src/lib/components/staff-org-usage-ai-columns.component.js.map +1 -0
  181. package/src/lib/components/staff-orgs-ai-spend-column.component.d.ts +28 -0
  182. package/src/lib/components/staff-orgs-ai-spend-column.component.js +89 -0
  183. package/src/lib/components/staff-orgs-ai-spend-column.component.js.map +1 -0
  184. package/src/lib/components/staff-user-ai-usage-card.component.d.ts +27 -0
  185. package/src/lib/components/staff-user-ai-usage-card.component.js +183 -0
  186. package/src/lib/components/staff-user-ai-usage-card.component.js.map +1 -0
  187. package/src/lib/components/use-ai-allotments.d.ts +49 -0
  188. package/src/lib/components/use-ai-allotments.js +171 -0
  189. package/src/lib/components/use-ai-allotments.js.map +1 -0
  190. package/src/lib/components/use-ai-crm-answer.d.ts +50 -0
  191. package/src/lib/components/use-ai-crm-answer.js +220 -0
  192. package/src/lib/components/use-ai-crm-answer.js.map +1 -0
  193. package/src/lib/components/use-ai-job-run.d.ts +51 -0
  194. package/src/lib/components/use-ai-job-run.js +176 -0
  195. package/src/lib/components/use-ai-job-run.js.map +1 -0
  196. package/src/lib/components/use-ai-model-choice.d.ts +47 -0
  197. package/src/lib/components/use-ai-model-choice.js +150 -0
  198. package/src/lib/components/use-ai-model-choice.js.map +1 -0
  199. package/src/lib/components/use-ai-products-jobs.d.ts +36 -0
  200. package/src/lib/components/use-ai-products-jobs.js +190 -0
  201. package/src/lib/components/use-ai-products-jobs.js.map +1 -0
  202. package/src/lib/components/use-ai-usage-meter.d.ts +11 -0
  203. package/src/lib/components/use-ai-usage-meter.js +96 -0
  204. package/src/lib/components/use-ai-usage-meter.js.map +1 -0
  205. package/src/lib/components/use-org-ai-usage.d.ts +42 -0
  206. package/src/lib/components/use-org-ai-usage.js +181 -0
  207. package/src/lib/components/use-org-ai-usage.js.map +1 -0
  208. package/src/lib/components/use-staff-orgs-ai-spend.d.ts +18 -0
  209. package/src/lib/components/use-staff-orgs-ai-spend.js +127 -0
  210. package/src/lib/components/use-staff-orgs-ai-spend.js.map +1 -0
  211. package/src/lib/constants.d.ts +24 -0
  212. package/src/lib/constants.js +23 -0
  213. package/src/lib/constants.js.map +1 -0
  214. package/src/lib/declarations.d.ts +48 -0
  215. package/src/lib/declarations.js +129 -0
  216. package/src/lib/declarations.js.map +1 -0
  217. package/src/lib/declarations.server.d.ts +35 -0
  218. package/src/lib/declarations.server.js +138 -0
  219. package/src/lib/declarations.server.js.map +1 -0
  220. package/src/lib/insights/ai-figure-readers.d.ts +90 -0
  221. package/src/lib/insights/ai-figure-readers.js +863 -0
  222. package/src/lib/insights/ai-figure-readers.js.map +1 -0
  223. package/src/lib/insights/ai-insight-digest.d.ts +165 -0
  224. package/src/lib/insights/ai-insight-digest.js +363 -0
  225. package/src/lib/insights/ai-insight-digest.js.map +1 -0
  226. package/src/lib/insights/ai-insight-readers.d.ts +71 -0
  227. package/src/lib/insights/ai-insight-readers.js +141 -0
  228. package/src/lib/insights/ai-insight-readers.js.map +1 -0
  229. package/src/lib/jobs/ai-crm-access.d.ts +61 -0
  230. package/src/lib/jobs/ai-crm-access.js +94 -0
  231. package/src/lib/jobs/ai-crm-access.js.map +1 -0
  232. package/src/lib/jobs/ai-email-bindings.d.ts +97 -0
  233. package/src/lib/jobs/ai-email-bindings.js +147 -0
  234. package/src/lib/jobs/ai-email-bindings.js.map +1 -0
  235. package/src/lib/jobs/ai-job-admission.d.ts +82 -0
  236. package/src/lib/jobs/ai-job-admission.js +45 -0
  237. package/src/lib/jobs/ai-job-admission.js.map +1 -0
  238. package/src/lib/jobs/ai-job-budget.d.ts +167 -0
  239. package/src/lib/jobs/ai-job-budget.js +161 -0
  240. package/src/lib/jobs/ai-job-budget.js.map +1 -0
  241. package/src/lib/jobs/ai-job-campaign-step.d.ts +108 -0
  242. package/src/lib/jobs/ai-job-campaign-step.js +340 -0
  243. package/src/lib/jobs/ai-job-campaign-step.js.map +1 -0
  244. package/src/lib/jobs/ai-job-component-checks.d.ts +74 -0
  245. package/src/lib/jobs/ai-job-component-checks.js +442 -0
  246. package/src/lib/jobs/ai-job-component-checks.js.map +1 -0
  247. package/src/lib/jobs/ai-job-component-step.d.ts +75 -0
  248. package/src/lib/jobs/ai-job-component-step.js +262 -0
  249. package/src/lib/jobs/ai-job-component-step.js.map +1 -0
  250. package/src/lib/jobs/ai-job-crm-step.d.ts +192 -0
  251. package/src/lib/jobs/ai-job-crm-step.js +734 -0
  252. package/src/lib/jobs/ai-job-crm-step.js.map +1 -0
  253. package/src/lib/jobs/ai-job-draft-ids.d.ts +62 -0
  254. package/src/lib/jobs/ai-job-draft-ids.js +132 -0
  255. package/src/lib/jobs/ai-job-draft-ids.js.map +1 -0
  256. package/src/lib/jobs/ai-job-drafts.d.ts +304 -0
  257. package/src/lib/jobs/ai-job-drafts.js +557 -0
  258. package/src/lib/jobs/ai-job-drafts.js.map +1 -0
  259. package/src/lib/jobs/ai-job-email-step.d.ts +195 -0
  260. package/src/lib/jobs/ai-job-email-step.js +547 -0
  261. package/src/lib/jobs/ai-job-email-step.js.map +1 -0
  262. package/src/lib/jobs/ai-job-experiment-step.d.ts +105 -0
  263. package/src/lib/jobs/ai-job-experiment-step.js +445 -0
  264. package/src/lib/jobs/ai-job-experiment-step.js.map +1 -0
  265. package/src/lib/jobs/ai-job-form-step.d.ts +250 -0
  266. package/src/lib/jobs/ai-job-form-step.js +634 -0
  267. package/src/lib/jobs/ai-job-form-step.js.map +1 -0
  268. package/src/lib/jobs/ai-job-generation.d.ts +114 -0
  269. package/src/lib/jobs/ai-job-generation.js +384 -0
  270. package/src/lib/jobs/ai-job-generation.js.map +1 -0
  271. package/src/lib/jobs/ai-job-insight-budget.d.ts +41 -0
  272. package/src/lib/jobs/ai-job-insight-budget.js +46 -0
  273. package/src/lib/jobs/ai-job-insight-budget.js.map +1 -0
  274. package/src/lib/jobs/ai-job-insight-step.d.ts +58 -0
  275. package/src/lib/jobs/ai-job-insight-step.js +350 -0
  276. package/src/lib/jobs/ai-job-insight-step.js.map +1 -0
  277. package/src/lib/jobs/ai-job-layout-step.d.ts +103 -0
  278. package/src/lib/jobs/ai-job-layout-step.js +340 -0
  279. package/src/lib/jobs/ai-job-layout-step.js.map +1 -0
  280. package/src/lib/jobs/ai-job-page-budget.d.ts +57 -0
  281. package/src/lib/jobs/ai-job-page-budget.js +60 -0
  282. package/src/lib/jobs/ai-job-page-budget.js.map +1 -0
  283. package/src/lib/jobs/ai-job-page-sections.d.ts +150 -0
  284. package/src/lib/jobs/ai-job-page-sections.js +450 -0
  285. package/src/lib/jobs/ai-job-page-sections.js.map +1 -0
  286. package/src/lib/jobs/ai-job-page-step.d.ts +198 -0
  287. package/src/lib/jobs/ai-job-page-step.js +667 -0
  288. package/src/lib/jobs/ai-job-page-step.js.map +1 -0
  289. package/src/lib/jobs/ai-job-plan-conformance.d.ts +107 -0
  290. package/src/lib/jobs/ai-job-plan-conformance.js +164 -0
  291. package/src/lib/jobs/ai-job-plan-conformance.js.map +1 -0
  292. package/src/lib/jobs/ai-job-plan-step.d.ts +196 -0
  293. package/src/lib/jobs/ai-job-plan-step.js +458 -0
  294. package/src/lib/jobs/ai-job-plan-step.js.map +1 -0
  295. package/src/lib/jobs/ai-job-plugin-drafts.d.ts +76 -0
  296. package/src/lib/jobs/ai-job-plugin-drafts.js +91 -0
  297. package/src/lib/jobs/ai-job-plugin-drafts.js.map +1 -0
  298. package/src/lib/jobs/ai-job-products-step.d.ts +106 -0
  299. package/src/lib/jobs/ai-job-products-step.js +436 -0
  300. package/src/lib/jobs/ai-job-products-step.js.map +1 -0
  301. package/src/lib/jobs/ai-job-seo-budget.d.ts +52 -0
  302. package/src/lib/jobs/ai-job-seo-budget.js +63 -0
  303. package/src/lib/jobs/ai-job-seo-budget.js.map +1 -0
  304. package/src/lib/jobs/ai-job-seo-step.d.ts +145 -0
  305. package/src/lib/jobs/ai-job-seo-step.js +809 -0
  306. package/src/lib/jobs/ai-job-seo-step.js.map +1 -0
  307. package/src/lib/jobs/ai-job-site-step.d.ts +252 -0
  308. package/src/lib/jobs/ai-job-site-step.js +538 -0
  309. package/src/lib/jobs/ai-job-site-step.js.map +1 -0
  310. package/src/lib/jobs/ai-job-template-step.d.ts +105 -0
  311. package/src/lib/jobs/ai-job-template-step.js +391 -0
  312. package/src/lib/jobs/ai-job-template-step.js.map +1 -0
  313. package/src/lib/jobs/ai-job-text-step.d.ts +125 -0
  314. package/src/lib/jobs/ai-job-text-step.js +128 -0
  315. package/src/lib/jobs/ai-job-text-step.js.map +1 -0
  316. package/src/lib/jobs/ai-job-theme-budget.d.ts +38 -0
  317. package/src/lib/jobs/ai-job-theme-budget.js +43 -0
  318. package/src/lib/jobs/ai-job-theme-budget.js.map +1 -0
  319. package/src/lib/jobs/ai-job-theme-step.d.ts +115 -0
  320. package/src/lib/jobs/ai-job-theme-step.js +337 -0
  321. package/src/lib/jobs/ai-job-theme-step.js.map +1 -0
  322. package/src/lib/jobs/ai-job-workflow-step.d.ts +139 -0
  323. package/src/lib/jobs/ai-job-workflow-step.js +530 -0
  324. package/src/lib/jobs/ai-job-workflow-step.js.map +1 -0
  325. package/src/lib/jobs/ai-jobs-beat.d.ts +78 -0
  326. package/src/lib/jobs/ai-jobs-beat.js +93 -0
  327. package/src/lib/jobs/ai-jobs-beat.js.map +1 -0
  328. package/src/lib/jobs/ai-jobs-pause.d.ts +38 -0
  329. package/src/lib/jobs/ai-jobs-pause.js +45 -0
  330. package/src/lib/jobs/ai-jobs-pause.js.map +1 -0
  331. package/src/lib/jobs/ai-jobs.d.ts +558 -0
  332. package/src/lib/jobs/ai-jobs.js +1410 -0
  333. package/src/lib/jobs/ai-jobs.js.map +1 -0
  334. package/src/lib/jobs/ai-media-asset-server.d.ts +34 -0
  335. package/src/lib/jobs/ai-media-asset-server.js +34 -0
  336. package/src/lib/jobs/ai-media-asset-server.js.map +1 -0
  337. package/src/lib/jobs/ai-media-asset.d.ts +59 -0
  338. package/src/lib/jobs/ai-media-asset.js +86 -0
  339. package/src/lib/jobs/ai-media-asset.js.map +1 -0
  340. package/src/lib/jobs/ai-product-image.d.ts +78 -0
  341. package/src/lib/jobs/ai-product-image.js +113 -0
  342. package/src/lib/jobs/ai-product-image.js.map +1 -0
  343. package/src/lib/jobs/ai-theme-brand-inputs.d.ts +125 -0
  344. package/src/lib/jobs/ai-theme-brand-inputs.js +378 -0
  345. package/src/lib/jobs/ai-theme-brand-inputs.js.map +1 -0
  346. package/src/lib/jobs/ai-theme-brand-server.d.ts +33 -0
  347. package/src/lib/jobs/ai-theme-brand-server.js +33 -0
  348. package/src/lib/jobs/ai-theme-brand-server.js.map +1 -0
  349. package/src/lib/jobs/ai-workflow-records.d.ts +84 -0
  350. package/src/lib/jobs/ai-workflow-records.js +158 -0
  351. package/src/lib/jobs/ai-workflow-records.js.map +1 -0
  352. package/src/lib/jobs/fixtures/ai-free-page-built-recording.d.ts +31 -0
  353. package/src/lib/jobs/fixtures/ai-free-page-built-recording.js +367 -0
  354. package/src/lib/jobs/fixtures/ai-free-page-built-recording.js.map +1 -0
  355. package/src/lib/jobs/fixtures/ai-free-page-recording.d.ts +69 -0
  356. package/src/lib/jobs/fixtures/ai-free-page-recording.js +442 -0
  357. package/src/lib/jobs/fixtures/ai-free-page-recording.js.map +1 -0
  358. package/src/lib/jobs/fixtures/ai-page-briefs.d.ts +146 -0
  359. package/src/lib/jobs/fixtures/ai-page-briefs.js +1850 -0
  360. package/src/lib/jobs/fixtures/ai-page-briefs.js.map +1 -0
  361. package/src/lib/model/ai-allotments.d.ts +208 -0
  362. package/src/lib/model/ai-allotments.js +269 -0
  363. package/src/lib/model/ai-allotments.js.map +1 -0
  364. package/src/lib/model/ai-automation-draft.d.ts +74 -0
  365. package/src/lib/model/ai-automation-draft.js +310 -0
  366. package/src/lib/model/ai-automation-draft.js.map +1 -0
  367. package/src/lib/model/ai-automation-outline.d.ts +50 -0
  368. package/src/lib/model/ai-automation-outline.js +262 -0
  369. package/src/lib/model/ai-automation-outline.js.map +1 -0
  370. package/src/lib/model/ai-build-plan.d.ts +197 -0
  371. package/src/lib/model/ai-build-plan.js +438 -0
  372. package/src/lib/model/ai-build-plan.js.map +1 -0
  373. package/src/lib/model/ai-crm.d.ts +237 -0
  374. package/src/lib/model/ai-crm.js +225 -0
  375. package/src/lib/model/ai-crm.js.map +1 -0
  376. package/src/lib/model/ai-experiment-proposal.d.ts +68 -0
  377. package/src/lib/model/ai-experiment-proposal.js +146 -0
  378. package/src/lib/model/ai-experiment-proposal.js.map +1 -0
  379. package/src/lib/model/ai-experiment.d.ts +309 -0
  380. package/src/lib/model/ai-experiment.js +395 -0
  381. package/src/lib/model/ai-experiment.js.map +1 -0
  382. package/src/lib/model/ai-insight.d.ts +178 -0
  383. package/src/lib/model/ai-insight.js +201 -0
  384. package/src/lib/model/ai-insight.js.map +1 -0
  385. package/src/lib/model/ai-jobs.types.d.ts +412 -0
  386. package/src/lib/model/ai-jobs.types.js +42 -0
  387. package/src/lib/model/ai-jobs.types.js.map +1 -0
  388. package/src/lib/model/ai-page-job.d.ts +92 -0
  389. package/src/lib/model/ai-page-job.js +159 -0
  390. package/src/lib/model/ai-page-job.js.map +1 -0
  391. package/src/lib/model/ai-permissions.d.ts +49 -0
  392. package/src/lib/model/ai-permissions.js +97 -0
  393. package/src/lib/model/ai-permissions.js.map +1 -0
  394. package/src/lib/model/ai-plan-capabilities.d.ts +139 -0
  395. package/src/lib/model/ai-plan-capabilities.js +149 -0
  396. package/src/lib/model/ai-plan-capabilities.js.map +1 -0
  397. package/src/lib/model/ai-products.d.ts +251 -0
  398. package/src/lib/model/ai-products.js +253 -0
  399. package/src/lib/model/ai-products.js.map +1 -0
  400. package/src/lib/model/ai-seo.d.ts +208 -0
  401. package/src/lib/model/ai-seo.js +150 -0
  402. package/src/lib/model/ai-seo.js.map +1 -0
  403. package/src/lib/model/ai-site-inventory.d.ts +164 -0
  404. package/src/lib/model/ai-site-inventory.js +145 -0
  405. package/src/lib/model/ai-site-inventory.js.map +1 -0
  406. package/src/lib/model/ai-site-job.d.ts +247 -0
  407. package/src/lib/model/ai-site-job.js +314 -0
  408. package/src/lib/model/ai-site-job.js.map +1 -0
  409. package/src/lib/model/ai-site-start-seo.d.ts +103 -0
  410. package/src/lib/model/ai-site-start-seo.js +154 -0
  411. package/src/lib/model/ai-site-start-seo.js.map +1 -0
  412. package/src/lib/model/ai-site-start.d.ts +122 -0
  413. package/src/lib/model/ai-site-start.js +159 -0
  414. package/src/lib/model/ai-site-start.js.map +1 -0
  415. package/src/lib/model/ai-site-switch.d.ts +56 -0
  416. package/src/lib/model/ai-site-switch.js +73 -0
  417. package/src/lib/model/ai-site-switch.js.map +1 -0
  418. package/src/lib/model/ai-storefront-claims.d.ts +70 -0
  419. package/src/lib/model/ai-storefront-claims.js +130 -0
  420. package/src/lib/model/ai-storefront-claims.js.map +1 -0
  421. package/src/lib/model/ai-template-subjects.d.ts +82 -0
  422. package/src/lib/model/ai-template-subjects.js +136 -0
  423. package/src/lib/model/ai-template-subjects.js.map +1 -0
  424. package/src/lib/model/ai-theme-proposal.d.ts +210 -0
  425. package/src/lib/model/ai-theme-proposal.js +506 -0
  426. package/src/lib/model/ai-theme-proposal.js.map +1 -0
  427. package/src/lib/model/ai-tokens.d.ts +96 -0
  428. package/src/lib/model/ai-tokens.js +117 -0
  429. package/src/lib/model/ai-tokens.js.map +1 -0
  430. package/src/lib/model/ai-usage-by-user.d.ts +120 -0
  431. package/src/lib/model/ai-usage-by-user.js +139 -0
  432. package/src/lib/model/ai-usage-by-user.js.map +1 -0
  433. package/src/lib/model/ai-workflow-job.d.ts +111 -0
  434. package/src/lib/model/ai-workflow-job.js +183 -0
  435. package/src/lib/model/ai-workflow-job.js.map +1 -0
  436. package/src/lib/model/assist-edit.d.ts +261 -0
  437. package/src/lib/model/assist-edit.js +175 -0
  438. package/src/lib/model/assist-edit.js.map +1 -0
  439. package/src/lib/plugin-config.d.ts +33 -0
  440. package/src/lib/plugin-config.js +118 -0
  441. package/src/lib/plugin-config.js.map +1 -0
  442. package/src/lib/plugin.d.ts +30 -0
  443. package/src/lib/plugin.js +525 -0
  444. package/src/lib/plugin.js.map +1 -0
  445. package/src/lib/providers/anthropic.d.ts +84 -0
  446. package/src/lib/providers/anthropic.js +432 -0
  447. package/src/lib/providers/anthropic.js.map +1 -0
  448. package/src/lib/providers/catalog.d.ts +197 -0
  449. package/src/lib/providers/catalog.js +312 -0
  450. package/src/lib/providers/catalog.js.map +1 -0
  451. package/src/lib/providers/contract.d.ts +464 -0
  452. package/src/lib/providers/contract.js +274 -0
  453. package/src/lib/providers/contract.js.map +1 -0
  454. package/src/lib/providers/model-choice.d.ts +119 -0
  455. package/src/lib/providers/model-choice.js +416 -0
  456. package/src/lib/providers/model-choice.js.map +1 -0
  457. package/src/lib/providers/openai-compatible.d.ts +58 -0
  458. package/src/lib/providers/openai-compatible.js +361 -0
  459. package/src/lib/providers/openai-compatible.js.map +1 -0
  460. package/src/lib/providers/registry.d.ts +49 -0
  461. package/src/lib/providers/registry.js +71 -0
  462. package/src/lib/providers/registry.js.map +1 -0
  463. package/src/lib/providers/routing.d.ts +98 -0
  464. package/src/lib/providers/routing.js +450 -0
  465. package/src/lib/providers/routing.js.map +1 -0
  466. package/src/lib/runtime/ai-abuse-guards.d.ts +113 -0
  467. package/src/lib/runtime/ai-abuse-guards.js +148 -0
  468. package/src/lib/runtime/ai-abuse-guards.js.map +1 -0
  469. package/src/lib/runtime/ai-component-bindings.d.ts +67 -0
  470. package/src/lib/runtime/ai-component-bindings.js +106 -0
  471. package/src/lib/runtime/ai-component-bindings.js.map +1 -0
  472. package/src/lib/runtime/ai-device-audit.d.ts +109 -0
  473. package/src/lib/runtime/ai-device-audit.js +97 -0
  474. package/src/lib/runtime/ai-device-audit.js.map +1 -0
  475. package/src/lib/runtime/ai-doctrine-validators.d.ts +720 -0
  476. package/src/lib/runtime/ai-doctrine-validators.js +3133 -0
  477. package/src/lib/runtime/ai-doctrine-validators.js.map +1 -0
  478. package/src/lib/runtime/ai-doctrine.d.ts +372 -0
  479. package/src/lib/runtime/ai-doctrine.js +944 -0
  480. package/src/lib/runtime/ai-doctrine.js.map +1 -0
  481. package/src/lib/runtime/ai-eval-live.d.ts +321 -0
  482. package/src/lib/runtime/ai-eval-live.js +1257 -0
  483. package/src/lib/runtime/ai-eval-live.js.map +1 -0
  484. package/src/lib/runtime/ai-eval-memory-firestore.d.ts +51 -0
  485. package/src/lib/runtime/ai-eval-memory-firestore.js +183 -0
  486. package/src/lib/runtime/ai-eval-memory-firestore.js.map +1 -0
  487. package/src/lib/runtime/ai-eval.d.ts +441 -0
  488. package/src/lib/runtime/ai-eval.js +1151 -0
  489. package/src/lib/runtime/ai-eval.js.map +1 -0
  490. package/src/lib/runtime/ai-gate.d.ts +130 -0
  491. package/src/lib/runtime/ai-gate.js +272 -0
  492. package/src/lib/runtime/ai-gate.js.map +1 -0
  493. package/src/lib/runtime/ai-generation-bounds.d.ts +24 -0
  494. package/src/lib/runtime/ai-generation-bounds.js +23 -0
  495. package/src/lib/runtime/ai-generation-bounds.js.map +1 -0
  496. package/src/lib/runtime/ai-insight-check.d.ts +76 -0
  497. package/src/lib/runtime/ai-insight-check.js +281 -0
  498. package/src/lib/runtime/ai-insight-check.js.map +1 -0
  499. package/src/lib/runtime/ai-node-tree.d.ts +181 -0
  500. package/src/lib/runtime/ai-node-tree.js +931 -0
  501. package/src/lib/runtime/ai-node-tree.js.map +1 -0
  502. package/src/lib/runtime/ai-page-links.d.ts +79 -0
  503. package/src/lib/runtime/ai-page-links.js +135 -0
  504. package/src/lib/runtime/ai-page-links.js.map +1 -0
  505. package/src/lib/runtime/ai-palette.d.ts +252 -0
  506. package/src/lib/runtime/ai-palette.generated.d.ts +34 -0
  507. package/src/lib/runtime/ai-palette.generated.js +5263 -0
  508. package/src/lib/runtime/ai-palette.generated.js.map +1 -0
  509. package/src/lib/runtime/ai-palette.js +187 -0
  510. package/src/lib/runtime/ai-palette.js.map +1 -0
  511. package/src/lib/runtime/ai-products-generation.d.ts +107 -0
  512. package/src/lib/runtime/ai-products-generation.js +250 -0
  513. package/src/lib/runtime/ai-products-generation.js.map +1 -0
  514. package/src/lib/runtime/ai-repeated-items.d.ts +95 -0
  515. package/src/lib/runtime/ai-repeated-items.js +397 -0
  516. package/src/lib/runtime/ai-repeated-items.js.map +1 -0
  517. package/src/lib/runtime/ai-runtime.d.ts +148 -0
  518. package/src/lib/runtime/ai-runtime.js +237 -0
  519. package/src/lib/runtime/ai-runtime.js.map +1 -0
  520. package/src/lib/runtime/ai-template-examples.d.ts +71 -0
  521. package/src/lib/runtime/ai-template-examples.js +135 -0
  522. package/src/lib/runtime/ai-template-examples.js.map +1 -0
  523. package/src/lib/runtime/assist-answer-cache.d.ts +80 -0
  524. package/src/lib/runtime/assist-answer-cache.js +184 -0
  525. package/src/lib/runtime/assist-answer-cache.js.map +1 -0
  526. package/src/lib/runtime/seo-audit.d.ts +93 -0
  527. package/src/lib/runtime/seo-audit.js +260 -0
  528. package/src/lib/runtime/seo-audit.js.map +1 -0
  529. package/src/lib/runtime/seo-content-fixes.d.ts +41 -0
  530. package/src/lib/runtime/seo-content-fixes.js +168 -0
  531. package/src/lib/runtime/seo-content-fixes.js.map +1 -0
  532. package/src/lib/runtime/seo-fields.d.ts +152 -0
  533. package/src/lib/runtime/seo-fields.js +215 -0
  534. package/src/lib/runtime/seo-fields.js.map +1 -0
  535. package/src/lib/runtime/seo-page-facts.d.ts +61 -0
  536. package/src/lib/runtime/seo-page-facts.js +150 -0
  537. package/src/lib/runtime/seo-page-facts.js.map +1 -0
  538. package/src/lib/runtime/site-inventory.d.ts +63 -0
  539. package/src/lib/runtime/site-inventory.js +230 -0
  540. package/src/lib/runtime/site-inventory.js.map +1 -0
  541. package/src/lib/server/ai-admin-org.d.ts +33 -0
  542. package/src/lib/server/ai-admin-org.js +381 -0
  543. package/src/lib/server/ai-admin-org.js.map +1 -0
  544. package/src/lib/server/ai-admin-orgs-spend.d.ts +40 -0
  545. package/src/lib/server/ai-admin-orgs-spend.js +129 -0
  546. package/src/lib/server/ai-admin-orgs-spend.js.map +1 -0
  547. package/src/lib/server/ai-admin-overage.d.ts +19 -0
  548. package/src/lib/server/ai-admin-overage.js +246 -0
  549. package/src/lib/server/ai-admin-overage.js.map +1 -0
  550. package/src/lib/server/ai-admin-signals.d.ts +34 -0
  551. package/src/lib/server/ai-admin-signals.js +330 -0
  552. package/src/lib/server/ai-admin-signals.js.map +1 -0
  553. package/src/lib/server/ai-admin-user.d.ts +27 -0
  554. package/src/lib/server/ai-admin-user.js +128 -0
  555. package/src/lib/server/ai-admin-user.js.map +1 -0
  556. package/src/lib/server/ai-allotments.d.ts +27 -0
  557. package/src/lib/server/ai-allotments.js +544 -0
  558. package/src/lib/server/ai-allotments.js.map +1 -0
  559. package/src/lib/server/ai-assist-prompts.d.ts +102 -0
  560. package/src/lib/server/ai-assist-prompts.js +207 -0
  561. package/src/lib/server/ai-assist-prompts.js.map +1 -0
  562. package/src/lib/server/ai-assist.d.ts +119 -0
  563. package/src/lib/server/ai-assist.js +517 -0
  564. package/src/lib/server/ai-assist.js.map +1 -0
  565. package/src/lib/server/ai-crm-answer.d.ts +30 -0
  566. package/src/lib/server/ai-crm-answer.js +98 -0
  567. package/src/lib/server/ai-crm-answer.js.map +1 -0
  568. package/src/lib/server/ai-generate-component.d.ts +111 -0
  569. package/src/lib/server/ai-generate-component.js +643 -0
  570. package/src/lib/server/ai-generate-component.js.map +1 -0
  571. package/src/lib/server/ai-host-permissions.d.ts +46 -0
  572. package/src/lib/server/ai-host-permissions.js +204 -0
  573. package/src/lib/server/ai-host-permissions.js.map +1 -0
  574. package/src/lib/server/ai-insight-answer.d.ts +30 -0
  575. package/src/lib/server/ai-insight-answer.js +83 -0
  576. package/src/lib/server/ai-insight-answer.js.map +1 -0
  577. package/src/lib/server/ai-insight-digest-route.d.ts +30 -0
  578. package/src/lib/server/ai-insight-digest-route.js +156 -0
  579. package/src/lib/server/ai-insight-digest-route.js.map +1 -0
  580. package/src/lib/server/ai-jobs-batch.d.ts +48 -0
  581. package/src/lib/server/ai-jobs-batch.js +306 -0
  582. package/src/lib/server/ai-jobs-batch.js.map +1 -0
  583. package/src/lib/server/ai-jobs-beat-route.d.ts +36 -0
  584. package/src/lib/server/ai-jobs-beat-route.js +86 -0
  585. package/src/lib/server/ai-jobs-beat-route.js.map +1 -0
  586. package/src/lib/server/ai-jobs-cancel.d.ts +30 -0
  587. package/src/lib/server/ai-jobs-cancel.js +74 -0
  588. package/src/lib/server/ai-jobs-cancel.js.map +1 -0
  589. package/src/lib/server/ai-jobs-events-route.d.ts +31 -0
  590. package/src/lib/server/ai-jobs-events-route.js +51 -0
  591. package/src/lib/server/ai-jobs-events-route.js.map +1 -0
  592. package/src/lib/server/ai-jobs-events.d.ts +55 -0
  593. package/src/lib/server/ai-jobs-events.js +144 -0
  594. package/src/lib/server/ai-jobs-events.js.map +1 -0
  595. package/src/lib/server/ai-jobs-gate.d.ts +47 -0
  596. package/src/lib/server/ai-jobs-gate.js +106 -0
  597. package/src/lib/server/ai-jobs-gate.js.map +1 -0
  598. package/src/lib/server/ai-jobs-resume.d.ts +23 -0
  599. package/src/lib/server/ai-jobs-resume.js +209 -0
  600. package/src/lib/server/ai-jobs-resume.js.map +1 -0
  601. package/src/lib/server/ai-jobs-route.d.ts +32 -0
  602. package/src/lib/server/ai-jobs-route.js +307 -0
  603. package/src/lib/server/ai-jobs-route.js.map +1 -0
  604. package/src/lib/server/ai-models.d.ts +18 -0
  605. package/src/lib/server/ai-models.js +134 -0
  606. package/src/lib/server/ai-models.js.map +1 -0
  607. package/src/lib/server/ai-seo-apply.d.ts +53 -0
  608. package/src/lib/server/ai-seo-apply.js +294 -0
  609. package/src/lib/server/ai-seo-apply.js.map +1 -0
  610. package/src/lib/server/ai-usage.d.ts +18 -0
  611. package/src/lib/server/ai-usage.js +220 -0
  612. package/src/lib/server/ai-usage.js.map +1 -0
  613. package/src/lib/server/assist-chat.d.ts +234 -0
  614. package/src/lib/server/assist-chat.js +1446 -0
  615. package/src/lib/server/assist-chat.js.map +1 -0
  616. package/src/lib/server/assist-edit-applied.d.ts +22 -0
  617. package/src/lib/server/assist-edit-applied.js +239 -0
  618. package/src/lib/server/assist-edit-applied.js.map +1 -0
  619. package/src/lib/server/assist-edit.d.ts +124 -0
  620. package/src/lib/server/assist-edit.js +1000 -0
  621. package/src/lib/server/assist-edit.js.map +1 -0
  622. package/src/lib/server/assist-feedback.d.ts +31 -0
  623. package/src/lib/server/assist-feedback.js +115 -0
  624. package/src/lib/server/assist-feedback.js.map +1 -0
  625. package/src/lib/server/assist-view-context.d.ts +343 -0
  626. package/src/lib/server/assist-view-context.js +690 -0
  627. package/src/lib/server/assist-view-context.js.map +1 -0
  628. package/src/lib/server/billing-credits.d.ts +59 -0
  629. package/src/lib/server/billing-credits.js +146 -0
  630. package/src/lib/server/billing-credits.js.map +1 -0
  631. package/src/lib/server/billing-overage.d.ts +19 -0
  632. package/src/lib/server/billing-overage.js +337 -0
  633. package/src/lib/server/billing-overage.js.map +1 -0
  634. package/src/lib/server.d.ts +32 -0
  635. package/src/lib/server.js +265 -0
  636. package/src/lib/server.js.map +1 -0
  637. package/src/lib/subprocessors.d.ts +18 -0
  638. package/src/lib/subprocessors.js +52 -0
  639. package/src/lib/subprocessors.js.map +1 -0
  640. package/src/lib/tools/ai-component-tool.d.ts +99 -0
  641. package/src/lib/tools/ai-component-tool.js +369 -0
  642. package/src/lib/tools/ai-component-tool.js.map +1 -0
  643. package/src/lib/tools/ai-crm-tool.d.ts +106 -0
  644. package/src/lib/tools/ai-crm-tool.js +488 -0
  645. package/src/lib/tools/ai-crm-tool.js.map +1 -0
  646. package/src/lib/tools/ai-duplicate-resource-tool.d.ts +71 -0
  647. package/src/lib/tools/ai-duplicate-resource-tool.js +164 -0
  648. package/src/lib/tools/ai-duplicate-resource-tool.js.map +1 -0
  649. package/src/lib/tools/ai-experiment-tool.d.ts +40 -0
  650. package/src/lib/tools/ai-experiment-tool.js +155 -0
  651. package/src/lib/tools/ai-experiment-tool.js.map +1 -0
  652. package/src/lib/tools/ai-insight-tool.d.ts +46 -0
  653. package/src/lib/tools/ai-insight-tool.js +200 -0
  654. package/src/lib/tools/ai-insight-tool.js.map +1 -0
  655. package/src/lib/tools/ai-inventory-lookup-tool.d.ts +86 -0
  656. package/src/lib/tools/ai-inventory-lookup-tool.js +164 -0
  657. package/src/lib/tools/ai-inventory-lookup-tool.js.map +1 -0
  658. package/src/lib/tools/ai-products-tool.d.ts +65 -0
  659. package/src/lib/tools/ai-products-tool.js +644 -0
  660. package/src/lib/tools/ai-products-tool.js.map +1 -0
  661. package/src/lib/tools/ai-seo-tool.d.ts +162 -0
  662. package/src/lib/tools/ai-seo-tool.js +546 -0
  663. package/src/lib/tools/ai-seo-tool.js.map +1 -0
  664. package/src/lib/tools/ai-theme-tool.d.ts +101 -0
  665. package/src/lib/tools/ai-theme-tool.js +562 -0
  666. package/src/lib/tools/ai-theme-tool.js.map +1 -0
  667. package/src/lib/tools/ai-workflow-tool.d.ts +166 -0
  668. package/src/lib/tools/ai-workflow-tool.js +860 -0
  669. package/src/lib/tools/ai-workflow-tool.js.map +1 -0
  670. package/src/lib/usage/ai-allotment-alerts.d.ts +72 -0
  671. package/src/lib/usage/ai-allotment-alerts.js +157 -0
  672. package/src/lib/usage/ai-allotment-alerts.js.map +1 -0
  673. package/src/lib/usage/ai-allotments.d.ts +125 -0
  674. package/src/lib/usage/ai-allotments.js +239 -0
  675. package/src/lib/usage/ai-allotments.js.map +1 -0
  676. package/src/lib/usage/ai-model-sample.d.ts +36 -0
  677. package/src/lib/usage/ai-model-sample.js +68 -0
  678. package/src/lib/usage/ai-model-sample.js.map +1 -0
  679. package/src/lib/usage/ai-usage-alerts.d.ts +55 -0
  680. package/src/lib/usage/ai-usage-alerts.js +114 -0
  681. package/src/lib/usage/ai-usage-alerts.js.map +1 -0
  682. package/src/lib/usage/ai-usage-by-user.d.ts +161 -0
  683. package/src/lib/usage/ai-usage-by-user.js +211 -0
  684. package/src/lib/usage/ai-usage-by-user.js.map +1 -0
  685. package/src/lib/usage/ai-usage-eraser.d.ts +29 -0
  686. package/src/lib/usage/ai-usage-eraser.js +40 -0
  687. package/src/lib/usage/ai-usage-eraser.js.map +1 -0
  688. package/src/lib/usage/ai-usage-meter.d.ts +39 -0
  689. package/src/lib/usage/ai-usage-meter.js +85 -0
  690. package/src/lib/usage/ai-usage-meter.js.map +1 -0
  691. package/src/lib/usage/ai-usage-wire.d.ts +184 -0
  692. package/src/lib/usage/ai-usage-wire.js +98 -0
  693. package/src/lib/usage/ai-usage-wire.js.map +1 -0
  694. package/src/lib/usage/assist-ceiling.d.ts +87 -0
  695. package/src/lib/usage/assist-ceiling.js +110 -0
  696. package/src/lib/usage/assist-ceiling.js.map +1 -0
  697. package/src/lib/usage/assist-free-taste.d.ts +225 -0
  698. package/src/lib/usage/assist-free-taste.js +308 -0
  699. package/src/lib/usage/assist-free-taste.js.map +1 -0
  700. package/src/lib/usage/assist-refusals.d.ts +69 -0
  701. package/src/lib/usage/assist-refusals.js +79 -0
  702. package/src/lib/usage/assist-refusals.js.map +1 -0
  703. package/src/lib/usage/assist-signal-mining.d.ts +375 -0
  704. package/src/lib/usage/assist-signal-mining.js +344 -0
  705. package/src/lib/usage/assist-signal-mining.js.map +1 -0
  706. package/src/lib/usage/assist-usage.d.ts +571 -0
  707. package/src/lib/usage/assist-usage.js +978 -0
  708. package/src/lib/usage/assist-usage.js.map +1 -0
  709. package/src/lib/usage/staff-org-ai.d.ts +242 -0
  710. package/src/lib/usage/staff-org-ai.js +173 -0
  711. package/src/lib/usage/staff-org-ai.js.map +1 -0
  712. package/src/lib/usage/staff-org-usage-ai.d.ts +83 -0
  713. package/src/lib/usage/staff-org-usage-ai.js +59 -0
  714. package/src/lib/usage/staff-org-usage-ai.js.map +1 -0
  715. package/src/lib/usage/staff-orgs-ai-spend.d.ts +83 -0
  716. package/src/lib/usage/staff-orgs-ai-spend.js +114 -0
  717. package/src/lib/usage/staff-orgs-ai-spend.js.map +1 -0
@@ -0,0 +1,294 @@
1
+ import { _ as _extends } from "@swc/helpers/_/_extends";
2
+ /**
3
+ * @license
4
+ * Copyright 2026 Aglyn LLC
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */ // lockdown-423: via libs/plugins/ai/src/lib/server/ai-jobs-gate.ts
18
+ // The gate carries the org verdict; the handler adds the site's own below,
19
+ // with the host document in hand.
20
+ import { checkEntitlement, createResourceUid, encodeStoredNodes, hostRoleCanWrite } from "@aglyn/aglyn/server";
21
+ import { pageContentRootId } from "@aglyn/aglyn/app-utils/page-markdown";
22
+ import { decodeStoredNodes } from "@aglyn/aglyn/app-utils/stored-nodes";
23
+ import { lockdownRefusal } from "@aglyn/tenant-data-admin/server/lockdown";
24
+ import { logAiSeoApplied } from "../activity/ai-activity.js";
25
+ import { aiJobSummary, getAiJob, recordAiJobApplied, writeAiJobAudit } from "../jobs/ai-jobs.js";
26
+ import { aiSeoAuditView, aiSeoJobTarget } from "../model/ai-seo.js";
27
+ import { applyAiSeoContentFixes } from "../runtime/seo-content-fixes.js";
28
+ import { aiJobsGate } from "./ai-jobs-gate.js";
29
+ /**
30
+ * Apply a site audit (AGL-2910): `POST /api/ai/seo/apply { orgId, hostId, jobId }`.
31
+ *
32
+ * "Apply all" does two things and neither changes what the published site
33
+ * serves.
34
+ *
35
+ * - **Content fixes open a NEW version per page.** The page's published
36
+ * version is copied, the fixes are applied to the copy — an image
37
+ * description, the page's one main heading — and the copy is stored as a
38
+ * new unpublished version. The published version and the screen's
39
+ * `versionId` are never touched: a person opens the draft, looks, and
40
+ * publishes it through the door that already exists.
41
+ * - **Listing values are STAGED, not written.** A page's search title and
42
+ * description are served straight from the screen document, so writing
43
+ * them would publish them. The apply records which pages have values
44
+ * waiting; the page's SEO card offers them, and its Save SEO is the write.
45
+ *
46
+ * The site-wide proposals — structured data and the agent guidance — are the
47
+ * site SEO form's to save, and the card puts them there as unsaved edits; this
48
+ * door never writes the host document.
49
+ *
50
+ * Idempotent per job: a page this job already opened a version for keeps
51
+ * that version, so a second press opens nothing new.
52
+ *
53
+ * ## The rungs
54
+ *
55
+ * The jobs read gate (membership, the release flag, `aiGenerative`, the org
56
+ * lockdown), then the site: it must be the job's and the org's, the caller
57
+ * must hold a role that writes the site's content — the role creating a
58
+ * version asks for — and the site's own lockdown verdict must admit a write.
59
+ * Nothing here spends a token, so there is no reservation.
60
+ */ const ID_CHARS = /^[A-Za-z0-9_-]{1,100}$/;
61
+ /** The version history sentence the versions route gives, for a plan without it. */ export const AI_SEO_APPLY_VERSIONING_COPY = 'Version history requires a Pro plan — see Billing to upgrade';
62
+ const str = (value)=>typeof value === 'string' ? value.trim() : '';
63
+ /**
64
+ * Open the versions and record the apply. Exported for the spec, which drives
65
+ * it against a Firestore double and proves what it leaves alone.
66
+ */ export async function applyAiSeoAudit(firestore, input) {
67
+ var _input_now, _ref, _ref1;
68
+ var _input_job_applied, _input_job_applied1;
69
+ const now = (_input_now = input.now) != null ? _input_now : new Date();
70
+ const hostRef = firestore.collection('hosts').doc(input.hostId);
71
+ const opened = _extends({}, (_ref = (_input_job_applied = input.job.applied) == null ? void 0 : _input_job_applied.versions) != null ? _ref : {});
72
+ const staged = new Set((_ref1 = (_input_job_applied1 = input.job.applied) == null ? void 0 : _input_job_applied1.staged) != null ? _ref1 : []);
73
+ const names = new Map(input.view.report.pages.map((page)=>[
74
+ page.screenId,
75
+ page.name
76
+ ]));
77
+ const versions = [];
78
+ const skipped = [];
79
+ for (const fix of Object.values(input.view.fixes)){
80
+ var _names_get;
81
+ const screenId = fix.screenId;
82
+ const name = (_names_get = names.get(screenId)) != null ? _names_get : screenId;
83
+ if (Object.keys(fix.values).length) staged.add(screenId);
84
+ if (!fix.content.length) continue;
85
+ const screenRef = hostRef.collection('screens').doc(screenId);
86
+ const earlier = opened[screenId];
87
+ if (earlier && (await screenRef.collection('versions').doc(earlier).get()).exists) {
88
+ versions.push({
89
+ screenId,
90
+ versionId: earlier,
91
+ name,
92
+ fixes: 0
93
+ });
94
+ continue;
95
+ }
96
+ if (!input.versioning) {
97
+ skipped.push({
98
+ screenId,
99
+ reason: AI_SEO_APPLY_VERSIONING_COPY
100
+ });
101
+ continue;
102
+ }
103
+ const screenSnapshot = await screenRef.get();
104
+ if (!screenSnapshot.exists || screenSnapshot.get('deletedAt')) {
105
+ skipped.push({
106
+ screenId,
107
+ reason: 'The page no longer exists.'
108
+ });
109
+ continue;
110
+ }
111
+ const publishedId = str(screenSnapshot.get('versionId'));
112
+ const source = publishedId ? await screenRef.collection('versions').doc(publishedId).get() : null;
113
+ const sourceData = (source == null ? void 0 : source.exists) ? source.data() : null;
114
+ const nodes = sourceData ? decodeStoredNodes(sourceData['nodes']) : null;
115
+ if (!sourceData || !nodes) {
116
+ skipped.push({
117
+ screenId,
118
+ reason: 'The page has no published version to start from.'
119
+ });
120
+ continue;
121
+ }
122
+ const rootId = typeof sourceData['rootId'] === 'string' ? sourceData['rootId'] : undefined;
123
+ const result = applyAiSeoContentFixes(nodes, fix.content, pageContentRootId(nodes, rootId));
124
+ if (!result.applied.length) {
125
+ var _ref2;
126
+ var _result_skipped_;
127
+ skipped.push({
128
+ screenId,
129
+ reason: (_ref2 = (_result_skipped_ = result.skipped[0]) == null ? void 0 : _result_skipped_.reason) != null ? _ref2 : 'Nothing on the page needed changing.'
130
+ });
131
+ continue;
132
+ }
133
+ const versionId = createResourceUid();
134
+ // Compressed at rest, as every write of a version's nodes is.
135
+ const packed = encodeStoredNodes(result.nodes);
136
+ await screenRef.collection('versions').doc(versionId).create(_extends({}, sourceData, {
137
+ nodes: packed ? Buffer.from(packed) : result.nodes,
138
+ displayName: 'SEO fixes',
139
+ createdAt: now,
140
+ updatedAt: now,
141
+ createdBy: input.uid
142
+ }));
143
+ opened[screenId] = versionId;
144
+ versions.push({
145
+ screenId,
146
+ versionId,
147
+ name,
148
+ fixes: result.applied.length
149
+ });
150
+ }
151
+ const applied = {
152
+ // The Admin SDK stores a `Date` as the timestamp the type describes.
153
+ at: now,
154
+ by: input.uid,
155
+ versions: opened,
156
+ staged: [
157
+ ...staged
158
+ ]
159
+ };
160
+ const job = await recordAiJobApplied(firestore, input.orgId, input.job.$id, applied, now);
161
+ return {
162
+ job,
163
+ versions,
164
+ staged: [
165
+ ...staged
166
+ ],
167
+ skipped
168
+ };
169
+ }
170
+ export async function POST(request) {
171
+ var _body_orgId, _host_memberRoles, _job_outputs, _decoded_email;
172
+ let body;
173
+ try {
174
+ var _ref;
175
+ body = (_ref = await request.json()) != null ? _ref : {};
176
+ } catch (unused) {
177
+ body = {};
178
+ }
179
+ const gate = await aiJobsGate(request, String((_body_orgId = body['orgId']) != null ? _body_orgId : ''));
180
+ if (gate instanceof Response) return gate;
181
+ const hostId = str(body['hostId']);
182
+ const jobId = str(body['jobId']);
183
+ if (!ID_CHARS.test(hostId) || !ID_CHARS.test(jobId)) {
184
+ return Response.json({
185
+ error: 'Name the site and the audit to apply'
186
+ }, {
187
+ status: 400
188
+ });
189
+ }
190
+ const { firestore, orgId, uid, staff, org, decoded } = gate;
191
+ const hostSnapshot = await firestore.collection('hosts').doc(hostId).get();
192
+ const host = hostSnapshot.exists ? hostSnapshot.data() : null;
193
+ if (!host || host['orgId'] !== orgId) {
194
+ return Response.json({
195
+ error: 'Unknown site'
196
+ }, {
197
+ status: 404
198
+ });
199
+ }
200
+ const role = ((_host_memberRoles = host['memberRoles']) != null ? _host_memberRoles : {})[uid];
201
+ if (!staff && !hostRoleCanWrite(role)) {
202
+ return Response.json({
203
+ error: 'Editing requires the editor role'
204
+ }, {
205
+ status: 403
206
+ });
207
+ }
208
+ const locked = await lockdownRefusal({
209
+ request,
210
+ staff,
211
+ uid,
212
+ org: org,
213
+ host: host
214
+ });
215
+ if (locked) return locked;
216
+ const job = await getAiJob(firestore, orgId, jobId);
217
+ if (!job || job.kind !== 'seo' || job.hostId !== hostId || aiSeoJobTarget(job.inputs) !== 'site') {
218
+ return Response.json({
219
+ error: 'Unknown audit'
220
+ }, {
221
+ status: 404
222
+ });
223
+ }
224
+ if (job.status !== 'done') {
225
+ return Response.json({
226
+ error: 'The audit is still running — apply it once it has finished'
227
+ }, {
228
+ status: 409
229
+ });
230
+ }
231
+ const view = aiSeoAuditView((_job_outputs = job.outputs) != null ? _job_outputs : []);
232
+ if (!view) {
233
+ return Response.json({
234
+ error: 'This audit has nothing to apply'
235
+ }, {
236
+ status: 409
237
+ });
238
+ }
239
+ const result = await applyAiSeoAudit(firestore, {
240
+ orgId,
241
+ hostId,
242
+ job,
243
+ view,
244
+ uid,
245
+ versioning: checkEntitlement(org, 'versioning')
246
+ });
247
+ const opened = result.versions.filter((entry)=>entry.fixes > 0);
248
+ await writeAiJobAudit(firestore, {
249
+ action: 'ai.job.apply',
250
+ actorUid: uid,
251
+ actorEmail: (_decoded_email = decoded.email) != null ? _decoded_email : null,
252
+ orgId,
253
+ jobId,
254
+ after: {
255
+ hostId,
256
+ versions: Object.fromEntries(opened.map((entry)=>[
257
+ entry.screenId,
258
+ entry.versionId
259
+ ])),
260
+ staged: result.staged
261
+ }
262
+ });
263
+ if (opened.length || result.staged.length) {
264
+ var _decoded_email1;
265
+ await logAiSeoApplied(orgId, {
266
+ uid,
267
+ email: (_decoded_email1 = decoded.email) != null ? _decoded_email1 : null
268
+ }, {
269
+ jobId,
270
+ hostId,
271
+ hostName: str(host['displayName']) || null,
272
+ versions: opened.length,
273
+ staged: result.staged.length
274
+ }).catch((error)=>console.error('ai seo apply activity failed', {
275
+ orgId,
276
+ jobId,
277
+ error
278
+ }));
279
+ }
280
+ return Response.json({
281
+ job: aiJobSummary(result.job),
282
+ versions: result.versions,
283
+ staged: result.staged,
284
+ skipped: result.skipped
285
+ }, {
286
+ status: 200,
287
+ headers: {
288
+ 'Cache-Control': 'no-store'
289
+ }
290
+ });
291
+ }
292
+ export const dynamic = 'force-dynamic';
293
+
294
+ //# sourceMappingURL=ai-seo-apply.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/server/ai-seo-apply.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// lockdown-423: via libs/plugins/ai/src/lib/server/ai-jobs-gate.ts\n// The gate carries the org verdict; the handler adds the site's own below,\n// with the host document in hand.\n\nimport {\n checkEntitlement,\n createResourceUid,\n encodeStoredNodes,\n hostRoleCanWrite,\n} from '@aglyn/aglyn/server'\nimport { pageContentRootId } from '@aglyn/aglyn/app-utils/page-markdown'\nimport { decodeStoredNodes } from '@aglyn/aglyn/app-utils/stored-nodes'\nimport { lockdownRefusal } from '@aglyn/tenant-data-admin/server/lockdown'\nimport { logAiSeoApplied } from '../activity/ai-activity'\nimport {\n aiJobSummary,\n getAiJob,\n recordAiJobApplied,\n writeAiJobAudit,\n} from '../jobs/ai-jobs'\nimport type { AiJob, AiJobApplied } from '../model/ai-jobs.types'\nimport { aiSeoAuditView, aiSeoJobTarget, type AiSeoAuditView } from '../model/ai-seo'\nimport { applyAiSeoContentFixes } from '../runtime/seo-content-fixes'\nimport { aiJobsGate } from './ai-jobs-gate'\n\n/**\n * Apply a site audit (AGL-2910): `POST /api/ai/seo/apply { orgId, hostId, jobId }`.\n *\n * \"Apply all\" does two things and neither changes what the published site\n * serves.\n *\n * - **Content fixes open a NEW version per page.** The page's published\n * version is copied, the fixes are applied to the copy — an image\n * description, the page's one main heading — and the copy is stored as a\n * new unpublished version. The published version and the screen's\n * `versionId` are never touched: a person opens the draft, looks, and\n * publishes it through the door that already exists.\n * - **Listing values are STAGED, not written.** A page's search title and\n * description are served straight from the screen document, so writing\n * them would publish them. The apply records which pages have values\n * waiting; the page's SEO card offers them, and its Save SEO is the write.\n *\n * The site-wide proposals — structured data and the agent guidance — are the\n * site SEO form's to save, and the card puts them there as unsaved edits; this\n * door never writes the host document.\n *\n * Idempotent per job: a page this job already opened a version for keeps\n * that version, so a second press opens nothing new.\n *\n * ## The rungs\n *\n * The jobs read gate (membership, the release flag, `aiGenerative`, the org\n * lockdown), then the site: it must be the job's and the org's, the caller\n * must hold a role that writes the site's content — the role creating a\n * version asks for — and the site's own lockdown verdict must admit a write.\n * Nothing here spends a token, so there is no reservation.\n */\n\nconst ID_CHARS = /^[A-Za-z0-9_-]{1,100}$/\n\n/** The version history sentence the versions route gives, for a plan without it. */\nexport const AI_SEO_APPLY_VERSIONING_COPY =\n 'Version history requires a Pro plan — see Billing to upgrade'\n\nexport interface AiSeoApplyInput {\n orgId: string\n hostId: string\n job: AiJob\n view: AiSeoAuditView\n uid: string\n /** Whether the org's plan keeps more than one version of a page. */\n versioning: boolean\n now?: Date\n}\n\nexport interface AiSeoApplyResult {\n job: AiJob\n /** The version each page's content fixes went into; `fixes` is 0 for one opened by an earlier apply. */\n versions: Array<{ screenId: string; versionId: string; name: string; fixes: number }>\n /** Pages whose listing values wait in their SEO card. */\n staged: string[]\n skipped: Array<{ screenId: string; reason: string }>\n}\n\nconst str = (value: unknown): string => (typeof value === 'string' ? value.trim() : '')\n\n/**\n * Open the versions and record the apply. Exported for the spec, which drives\n * it against a Firestore double and proves what it leaves alone.\n */\nexport async function applyAiSeoAudit(\n firestore: FirebaseFirestore.Firestore,\n input: AiSeoApplyInput,\n): Promise<AiSeoApplyResult> {\n const now = input.now ?? new Date()\n const hostRef = firestore.collection('hosts').doc(input.hostId)\n const opened = { ...(input.job.applied?.versions ?? {}) }\n const staged = new Set(input.job.applied?.staged ?? [])\n const names = new Map(input.view.report.pages.map((page) => [page.screenId, page.name]))\n const versions: AiSeoApplyResult['versions'] = []\n const skipped: AiSeoApplyResult['skipped'] = []\n\n for (const fix of Object.values(input.view.fixes)) {\n const screenId = fix.screenId\n const name = names.get(screenId) ?? screenId\n if (Object.keys(fix.values).length) staged.add(screenId)\n if (!fix.content.length) continue\n const screenRef = hostRef.collection('screens').doc(screenId)\n\n const earlier = opened[screenId]\n if (earlier && (await screenRef.collection('versions').doc(earlier).get()).exists) {\n versions.push({ screenId, versionId: earlier, name, fixes: 0 })\n continue\n }\n if (!input.versioning) {\n skipped.push({ screenId, reason: AI_SEO_APPLY_VERSIONING_COPY })\n continue\n }\n const screenSnapshot = await screenRef.get()\n if (!screenSnapshot.exists || screenSnapshot.get('deletedAt')) {\n skipped.push({ screenId, reason: 'The page no longer exists.' })\n continue\n }\n const publishedId = str(screenSnapshot.get('versionId'))\n const source = publishedId ? await screenRef.collection('versions').doc(publishedId).get() : null\n const sourceData = source?.exists ? (source.data() as Record<string, unknown>) : null\n const nodes = sourceData ? decodeStoredNodes<Record<string, unknown>>(sourceData['nodes']) : null\n if (!sourceData || !nodes) {\n skipped.push({ screenId, reason: 'The page has no published version to start from.' })\n continue\n }\n const rootId = typeof sourceData['rootId'] === 'string' ? sourceData['rootId'] : undefined\n const result = applyAiSeoContentFixes(\n nodes,\n fix.content,\n pageContentRootId(nodes as never, rootId),\n )\n if (!result.applied.length) {\n skipped.push({ screenId, reason: result.skipped[0]?.reason ?? 'Nothing on the page needed changing.' })\n continue\n }\n const versionId = createResourceUid()\n // Compressed at rest, as every write of a version's nodes is.\n const packed = encodeStoredNodes(result.nodes)\n await screenRef\n .collection('versions')\n .doc(versionId)\n .create({\n ...sourceData,\n nodes: packed ? Buffer.from(packed) : result.nodes,\n displayName: 'SEO fixes',\n createdAt: now,\n updatedAt: now,\n createdBy: input.uid,\n })\n opened[screenId] = versionId\n versions.push({ screenId, versionId, name, fixes: result.applied.length })\n }\n\n const applied: AiJobApplied = {\n // The Admin SDK stores a `Date` as the timestamp the type describes.\n at: now as unknown as AiJobApplied['at'],\n by: input.uid,\n versions: opened,\n staged: [...staged],\n }\n const job = await recordAiJobApplied(firestore, input.orgId, input.job.$id, applied, now)\n return { job, versions, staged: [...staged], skipped }\n}\n\nexport async function POST(request: Request): Promise<Response> {\n let body: Record<string, unknown>\n try {\n body = ((await request.json()) ?? {}) as Record<string, unknown>\n } catch {\n body = {}\n }\n const gate = await aiJobsGate(request, String(body['orgId'] ?? ''))\n if (gate instanceof Response) return gate\n const hostId = str(body['hostId'])\n const jobId = str(body['jobId'])\n if (!ID_CHARS.test(hostId) || !ID_CHARS.test(jobId)) {\n return Response.json({ error: 'Name the site and the audit to apply' }, { status: 400 })\n }\n const { firestore, orgId, uid, staff, org, decoded } = gate\n\n const hostSnapshot = await firestore.collection('hosts').doc(hostId).get()\n const host = hostSnapshot.exists ? (hostSnapshot.data() as Record<string, unknown>) : null\n if (!host || host['orgId'] !== orgId) {\n return Response.json({ error: 'Unknown site' }, { status: 404 })\n }\n const role = ((host['memberRoles'] ?? {}) as Record<string, unknown>)[uid]\n if (!staff && !hostRoleCanWrite(role)) {\n return Response.json({ error: 'Editing requires the editor role' }, { status: 403 })\n }\n const locked = await lockdownRefusal({\n request,\n staff,\n uid,\n org: org as Record<string, unknown>,\n host: host as never,\n })\n if (locked) return locked\n\n const job = await getAiJob(firestore, orgId, jobId)\n if (!job || job.kind !== 'seo' || job.hostId !== hostId || aiSeoJobTarget(job.inputs) !== 'site') {\n return Response.json({ error: 'Unknown audit' }, { status: 404 })\n }\n if (job.status !== 'done') {\n return Response.json({ error: 'The audit is still running — apply it once it has finished' }, { status: 409 })\n }\n const view = aiSeoAuditView(job.outputs ?? [])\n if (!view) {\n return Response.json({ error: 'This audit has nothing to apply' }, { status: 409 })\n }\n\n const result = await applyAiSeoAudit(firestore, {\n orgId,\n hostId,\n job,\n view,\n uid,\n versioning: checkEntitlement(org, 'versioning'),\n })\n const opened = result.versions.filter((entry) => entry.fixes > 0)\n await writeAiJobAudit(firestore, {\n action: 'ai.job.apply',\n actorUid: uid,\n actorEmail: decoded.email ?? null,\n orgId,\n jobId,\n after: {\n hostId,\n versions: Object.fromEntries(opened.map((entry) => [entry.screenId, entry.versionId])),\n staged: result.staged,\n },\n })\n if (opened.length || result.staged.length) {\n await logAiSeoApplied(orgId, { uid, email: decoded.email ?? null }, {\n jobId,\n hostId,\n hostName: str(host['displayName']) || null,\n versions: opened.length,\n staged: result.staged.length,\n }).catch((error) => console.error('ai seo apply activity failed', { orgId, jobId, error }))\n }\n return Response.json(\n {\n job: aiJobSummary(result.job),\n versions: result.versions,\n staged: result.staged,\n skipped: result.skipped,\n },\n { status: 200, headers: { 'Cache-Control': 'no-store' } },\n )\n}\n\nexport const dynamic = 'force-dynamic'\n"],"names":["checkEntitlement","createResourceUid","encodeStoredNodes","hostRoleCanWrite","pageContentRootId","decodeStoredNodes","lockdownRefusal","logAiSeoApplied","aiJobSummary","getAiJob","recordAiJobApplied","writeAiJobAudit","aiSeoAuditView","aiSeoJobTarget","applyAiSeoContentFixes","aiJobsGate","ID_CHARS","AI_SEO_APPLY_VERSIONING_COPY","str","value","trim","applyAiSeoAudit","firestore","input","now","Date","hostRef","collection","doc","hostId","opened","job","applied","versions","staged","Set","names","Map","view","report","pages","map","page","screenId","name","skipped","fix","Object","values","fixes","get","keys","length","add","content","screenRef","earlier","exists","push","versionId","versioning","reason","screenSnapshot","publishedId","source","sourceData","data","nodes","rootId","undefined","result","packed","create","Buffer","from","displayName","createdAt","updatedAt","createdBy","uid","at","by","orgId","$id","POST","request","body","host","decoded","json","gate","String","Response","jobId","test","error","status","staff","org","hostSnapshot","role","locked","kind","inputs","outputs","filter","entry","action","actorUid","actorEmail","email","after","fromEntries","hostName","catch","console","headers","dynamic"],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ declare function handler(request: Request): Promise<Response>;
18
+ export { handler as GET };
@@ -0,0 +1,220 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */ import { csvCell, pluginRequestFromWeb } from "@aglyn/aglyn/server";
17
+ import { emailUnverifiedResponse, firebaseAdmin, isImpersonationSession, memberHasOrgPermission, resolveOrgMembership } from "@aglyn/tenant-data-admin";
18
+ import { aiUsageMonthKeys, aiUsageMonthWithinRetention, aiUsageShare } from "../model/ai-usage-by-user.js";
19
+ import { readOrgAiUsageByUser, readUserAiUsageMonths } from "../usage/ai-usage-by-user.js";
20
+ import { FieldValue } from "firebase-admin/firestore";
21
+ import { invalidIdTokenResponse } from "@aglyn/tenant-data-admin/server/id-token-refusal";
22
+ import { AI_USAGE_CSV_HEADER, AI_USAGE_EXPORT_ROWS_HEADER, aiUsageCsvLine, toAiUsageWireRow } from "../usage/ai-usage-wire.js";
23
+ // lockdown-423: exempt — a READ-ONLY usage report that writes nothing to the
24
+ // workspace, the posture of ai/billing/credits beside it: a billing-locked
25
+ // owner working out who spent the credits needs this table more, not less.
26
+ /**
27
+ * WHO IS GENERATING WHAT, PER SITE (AGL-2928) — the customer's read of the
28
+ * per-user AI usage rollup.
29
+ *
30
+ * ## Three questions, one route
31
+ *
32
+ * - **The month's table** (`orgId`, `month`): every current member with a
33
+ * month document, dearest first, with each person's share of the
34
+ * workspace's spend. Gated on `billing.view`, the Usage page's gate, and
35
+ * served as JSON or — `format=csv` — as a streamed file.
36
+ * - **One person** (`uid`): that person's months, newest first, for the
37
+ * member detail card. The subject reads their own; anyone else needs
38
+ * `billing.view` or `org.auditLog`, which is the team page's gate and the
39
+ * pair the security rules admit for the same documents.
40
+ * - **One site** (`hostId`): the table with each row's credits ON THAT SITE
41
+ * beside it, for the site's collaborators card — the agency question,
42
+ * "which client site's collaborators spend".
43
+ *
44
+ * ## No dollar figure crosses this boundary
45
+ *
46
+ * The month document carries `estCostUsd`, our provider bill. The rows here
47
+ * carry credits and a SHARE, and the share is computed on the dollars
48
+ * server-side (`aiUsageShare`) so it is exact — a roster's credits each round
49
+ * up, the org's round once — without the dollars ever being serialized.
50
+ *
51
+ * ## The month bound
52
+ *
53
+ * `month` must be inside the retention window (`aiUsageMonthKeys`): a
54
+ * request for an older month is refused rather than answered empty, because
55
+ * "nothing for that month" and "that month has been reaped" must not read
56
+ * the same on a report somebody exports.
57
+ */ /** The most months one person's card is handed. */ const MAX_USER_MONTHS = 13;
58
+ const json = (body, status)=>Response.json(body, {
59
+ status
60
+ });
61
+ async function handler(request) {
62
+ var _headers_authorization, _params_orgId, _params_month, _params_uid, _params_hostId, _params_format;
63
+ const { method, query, headers: rawHeaders } = await pluginRequestFromWeb(request);
64
+ const headers = rawHeaders;
65
+ if (method !== 'GET') return json({
66
+ error: 'Method not allowed'
67
+ }, 405);
68
+ const authorization = (_headers_authorization = headers.authorization) != null ? _headers_authorization : '';
69
+ const idToken = authorization.startsWith('Bearer ') ? authorization.slice('Bearer '.length) : undefined;
70
+ if (!idToken) return json({
71
+ error: 'Unauthenticated'
72
+ }, 401);
73
+ const params = query != null ? query : {};
74
+ const orgId = String((_params_orgId = params['orgId']) != null ? _params_orgId : '').trim();
75
+ if (!orgId) return json({
76
+ error: 'Missing orgId'
77
+ }, 400);
78
+ const now = new Date();
79
+ const months = aiUsageMonthKeys(now);
80
+ const month = String((_params_month = params['month']) != null ? _params_month : months[0]).trim();
81
+ if (!aiUsageMonthWithinRetention(month, now)) {
82
+ return json({
83
+ error: `AI usage is kept for ${months.length} months; ` + `ask for one of ${months[months.length - 1]} through ${months[0]}.`
84
+ }, 400);
85
+ }
86
+ const subjectUid = String((_params_uid = params['uid']) != null ? _params_uid : '').trim();
87
+ const hostId = String((_params_hostId = params['hostId']) != null ? _params_hostId : '').trim();
88
+ const format = String((_params_format = params['format']) != null ? _params_format : 'json').trim();
89
+ try {
90
+ const decoded = await firebaseAdmin.app().auth().verifyIdToken(idToken);
91
+ if (!decoded.email_verified && !isImpersonationSession(decoded)) {
92
+ return emailUnverifiedResponse();
93
+ }
94
+ const staff = decoded['staff'] === true;
95
+ const membership = await resolveOrgMembership(decoded.uid, orgId);
96
+ const member = membership == null ? void 0 : membership.member;
97
+ if (!member && !staff) return json({
98
+ error: 'Not found'
99
+ }, 404);
100
+ const firestore = firebaseAdmin.app().firestore();
101
+ if (subjectUid) {
102
+ var _params_limit;
103
+ // One person. Their own months are theirs to read; anyone else's need
104
+ // the Usage page's permission or the team page's.
105
+ const own = subjectUid === decoded.uid && Boolean(member);
106
+ if (!own && !staff) {
107
+ const allowed = await memberHasOrgPermission(orgId, member, 'billing.view') || await memberHasOrgPermission(orgId, member, 'org.auditLog');
108
+ if (!allowed) return json({
109
+ error: 'billing.view required'
110
+ }, 403);
111
+ }
112
+ const limit = Math.min(MAX_USER_MONTHS, Math.max(1, Math.floor(Number((_params_limit = params['limit']) != null ? _params_limit : 2) || 2)));
113
+ const rows = await readUserAiUsageMonths(firestore, orgId, subjectUid, limit);
114
+ const orgRef = firestore.collection('orgs').doc(orgId);
115
+ const rollups = rows.length ? await firestore.getAll(...rows.map((row)=>orgRef.collection('assistUsage').doc(row.month))) : [];
116
+ const wire = {
117
+ uid: subjectUid,
118
+ months: rows.map((row, index)=>{
119
+ var _ref;
120
+ var _rollups_index;
121
+ return {
122
+ month: row.month,
123
+ credits: row.credits,
124
+ share: aiUsageShare(row.estCostUsd, Number((_ref = (_rollups_index = rollups[index]) == null ? void 0 : _rollups_index.get('estCostUsd')) != null ? _ref : 0)),
125
+ requests: row.requests,
126
+ refusals: row.refusals,
127
+ byKind: row.byKind,
128
+ byHost: row.byHost
129
+ };
130
+ })
131
+ };
132
+ return json(wire, 200);
133
+ }
134
+ // The table, which is about everyone: the Usage page's permission.
135
+ if (!staff && !await memberHasOrgPermission(orgId, member, 'billing.view')) {
136
+ return json({
137
+ error: 'billing.view required'
138
+ }, 403);
139
+ }
140
+ const usage = await readOrgAiUsageByUser(firestore, orgId, month);
141
+ const rows = usage.rows.map((row)=>toAiUsageWireRow(row, hostId));
142
+ if (hostId) {
143
+ rows.sort((a, b)=>{
144
+ var _b_hostCredits, _a_hostCredits;
145
+ return ((_b_hostCredits = b.hostCredits) != null ? _b_hostCredits : 0) - ((_a_hostCredits = a.hostCredits) != null ? _a_hostCredits : 0) || b.credits - a.credits;
146
+ });
147
+ }
148
+ if (format !== 'csv') {
149
+ const table = {
150
+ month,
151
+ months,
152
+ orgCredits: usage.orgCredits,
153
+ rows
154
+ };
155
+ return json(table, 200);
156
+ }
157
+ /*
158
+ * The file, streamed: the header first, then the rows in pages, so a
159
+ * roster of any size arrives without being held whole. The row count
160
+ * travels in a header the client checks the body against — a stream
161
+ * that dies halfway yields a well-formed shorter file, and nothing about
162
+ * the bytes says it is short.
163
+ */ const encoder = new TextEncoder();
164
+ const PAGE = 200;
165
+ let cursor = 0;
166
+ let headed = false;
167
+ const stream = new ReadableStream({
168
+ pull (controller) {
169
+ if (!headed) {
170
+ headed = true;
171
+ controller.enqueue(encoder.encode(AI_USAGE_CSV_HEADER.map(csvCell).join(',')));
172
+ return;
173
+ }
174
+ if (cursor < rows.length) {
175
+ const page = rows.slice(cursor, cursor + PAGE);
176
+ cursor += page.length;
177
+ controller.enqueue(encoder.encode(`\n${page.map(aiUsageCsvLine).join('\n')}`));
178
+ return;
179
+ }
180
+ controller.enqueue(encoder.encode('\n'));
181
+ controller.close();
182
+ }
183
+ });
184
+ // Ids and counts only, never content: a report about people leaving
185
+ // the platform is worth a row; who was in it is the workspace's own.
186
+ void firestore.collection('adminAudit').add({
187
+ actorUid: decoded.uid,
188
+ action: 'ai-usage.exported',
189
+ target: `orgs/${orgId}/aiUsageByUser`,
190
+ before: null,
191
+ after: {
192
+ month,
193
+ rows: rows.length,
194
+ hostId: hostId || null
195
+ },
196
+ at: FieldValue.serverTimestamp()
197
+ }).catch(()=>undefined);
198
+ return new Response(stream, {
199
+ status: 200,
200
+ headers: {
201
+ 'Content-Type': 'text/csv; charset=utf-8',
202
+ 'Content-Disposition': `attachment; filename="ai-usage-${month}.csv"`,
203
+ [AI_USAGE_EXPORT_ROWS_HEADER]: String(rows.length),
204
+ 'Cache-Control': 'no-store, private'
205
+ }
206
+ });
207
+ } catch (error) {
208
+ // A refused credential is a 401, not a fault of ours (AGL-1993). Null
209
+ // for anything else, so a real failure keeps the answer below.
210
+ const unauthenticated = invalidIdTokenResponse(error);
211
+ if (unauthenticated) return unauthenticated;
212
+ console.error('[ai/usage] read failed', orgId, error);
213
+ return json({
214
+ error: 'AI usage unavailable'
215
+ }, 500);
216
+ }
217
+ }
218
+ export { handler as GET };
219
+
220
+ //# sourceMappingURL=ai-usage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/server/ai-usage.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { csvCell, pluginRequestFromWeb } from '@aglyn/aglyn/server'\nimport {\n emailUnverifiedResponse,\n firebaseAdmin,\n isImpersonationSession,\n memberHasOrgPermission,\n resolveOrgMembership,\n} from '@aglyn/tenant-data-admin'\nimport {\n aiUsageMonthKeys,\n aiUsageMonthWithinRetention,\n aiUsageShare,\n type AiUsageByUserMonth,\n} from '../model/ai-usage-by-user'\nimport {\n readOrgAiUsageByUser,\n readUserAiUsageMonths,\n} from '../usage/ai-usage-by-user'\nimport { FieldValue } from 'firebase-admin/firestore'\nimport { invalidIdTokenResponse } from '@aglyn/tenant-data-admin/server/id-token-refusal'\nimport {\n AI_USAGE_CSV_HEADER,\n AI_USAGE_EXPORT_ROWS_HEADER,\n aiUsageCsvLine,\n toAiUsageWireRow,\n type OrgAiUsageTableWire,\n type UserAiUsageWire,\n} from '../usage/ai-usage-wire'\n\n// lockdown-423: exempt — a READ-ONLY usage report that writes nothing to the\n// workspace, the posture of ai/billing/credits beside it: a billing-locked\n// owner working out who spent the credits needs this table more, not less.\n\n/**\n * WHO IS GENERATING WHAT, PER SITE (AGL-2928) — the customer's read of the\n * per-user AI usage rollup.\n *\n * ## Three questions, one route\n *\n * - **The month's table** (`orgId`, `month`): every current member with a\n * month document, dearest first, with each person's share of the\n * workspace's spend. Gated on `billing.view`, the Usage page's gate, and\n * served as JSON or — `format=csv` — as a streamed file.\n * - **One person** (`uid`): that person's months, newest first, for the\n * member detail card. The subject reads their own; anyone else needs\n * `billing.view` or `org.auditLog`, which is the team page's gate and the\n * pair the security rules admit for the same documents.\n * - **One site** (`hostId`): the table with each row's credits ON THAT SITE\n * beside it, for the site's collaborators card — the agency question,\n * \"which client site's collaborators spend\".\n *\n * ## No dollar figure crosses this boundary\n *\n * The month document carries `estCostUsd`, our provider bill. The rows here\n * carry credits and a SHARE, and the share is computed on the dollars\n * server-side (`aiUsageShare`) so it is exact — a roster's credits each round\n * up, the org's round once — without the dollars ever being serialized.\n *\n * ## The month bound\n *\n * `month` must be inside the retention window (`aiUsageMonthKeys`): a\n * request for an older month is refused rather than answered empty, because\n * \"nothing for that month\" and \"that month has been reaped\" must not read\n * the same on a report somebody exports.\n */\n\n/** The most months one person's card is handed. */\nconst MAX_USER_MONTHS = 13\n\nconst json = (body: unknown, status: number) => Response.json(body, { status })\n\nasync function handler(request: Request): Promise<Response> {\n const { method, query, headers: rawHeaders } = await pluginRequestFromWeb(request)\n const headers = rawHeaders as Partial<Record<string, string>>\n if (method !== 'GET') return json({ error: 'Method not allowed' }, 405)\n\n const authorization = headers.authorization ?? ''\n const idToken = authorization.startsWith('Bearer ')\n ? authorization.slice('Bearer '.length)\n : undefined\n if (!idToken) return json({ error: 'Unauthenticated' }, 401)\n\n const params = (query ?? {}) as Record<string, unknown>\n const orgId = String(params['orgId'] ?? '').trim()\n if (!orgId) return json({ error: 'Missing orgId' }, 400)\n const now = new Date()\n const months = aiUsageMonthKeys(now)\n const month = String(params['month'] ?? months[0]).trim()\n if (!aiUsageMonthWithinRetention(month, now)) {\n return json(\n {\n error:\n `AI usage is kept for ${months.length} months; ` +\n `ask for one of ${months[months.length - 1]} through ${months[0]}.`,\n },\n 400,\n )\n }\n const subjectUid = String(params['uid'] ?? '').trim()\n const hostId = String(params['hostId'] ?? '').trim()\n const format = String(params['format'] ?? 'json').trim()\n\n try {\n const decoded = await firebaseAdmin.app().auth().verifyIdToken(idToken)\n if (!decoded.email_verified && !isImpersonationSession(decoded)) {\n return emailUnverifiedResponse()\n }\n const staff = decoded['staff'] === true\n const membership = await resolveOrgMembership(decoded.uid, orgId)\n const member = membership?.member\n if (!member && !staff) return json({ error: 'Not found' }, 404)\n\n const firestore = firebaseAdmin.app().firestore()\n\n if (subjectUid) {\n // One person. Their own months are theirs to read; anyone else's need\n // the Usage page's permission or the team page's.\n const own = subjectUid === decoded.uid && Boolean(member)\n if (!own && !staff) {\n const allowed =\n (await memberHasOrgPermission(orgId, member, 'billing.view')) ||\n (await memberHasOrgPermission(orgId, member, 'org.auditLog'))\n if (!allowed) return json({ error: 'billing.view required' }, 403)\n }\n const limit = Math.min(\n MAX_USER_MONTHS,\n Math.max(1, Math.floor(Number(params['limit'] ?? 2) || 2)),\n )\n const rows = await readUserAiUsageMonths(firestore, orgId, subjectUid, limit)\n const orgRef = firestore.collection('orgs').doc(orgId)\n const rollups = rows.length\n ? await firestore.getAll(\n ...rows.map((row) => orgRef.collection('assistUsage').doc(row.month)),\n )\n : []\n const wire: UserAiUsageWire = {\n uid: subjectUid,\n months: rows.map((row: AiUsageByUserMonth, index) => ({\n month: row.month,\n credits: row.credits,\n share: aiUsageShare(\n row.estCostUsd,\n Number(rollups[index]?.get('estCostUsd') ?? 0),\n ),\n requests: row.requests,\n refusals: row.refusals,\n byKind: row.byKind,\n byHost: row.byHost,\n })),\n }\n return json(wire, 200)\n }\n\n // The table, which is about everyone: the Usage page's permission.\n if (!staff && !(await memberHasOrgPermission(orgId, member, 'billing.view'))) {\n return json({ error: 'billing.view required' }, 403)\n }\n const usage = await readOrgAiUsageByUser(firestore, orgId, month)\n const rows = usage.rows.map((row) => toAiUsageWireRow(row, hostId))\n if (hostId) {\n rows.sort(\n (a, b) =>\n (b.hostCredits ?? 0) - (a.hostCredits ?? 0) || b.credits - a.credits,\n )\n }\n\n if (format !== 'csv') {\n const table: OrgAiUsageTableWire = {\n month,\n months,\n orgCredits: usage.orgCredits,\n rows,\n }\n return json(table, 200)\n }\n\n /*\n * The file, streamed: the header first, then the rows in pages, so a\n * roster of any size arrives without being held whole. The row count\n * travels in a header the client checks the body against — a stream\n * that dies halfway yields a well-formed shorter file, and nothing about\n * the bytes says it is short.\n */\n const encoder = new TextEncoder()\n const PAGE = 200\n let cursor = 0\n let headed = false\n const stream = new ReadableStream<Uint8Array>({\n pull(controller) {\n if (!headed) {\n headed = true\n controller.enqueue(encoder.encode(AI_USAGE_CSV_HEADER.map(csvCell).join(',')))\n return\n }\n if (cursor < rows.length) {\n const page = rows.slice(cursor, cursor + PAGE)\n cursor += page.length\n controller.enqueue(\n encoder.encode(`\\n${page.map(aiUsageCsvLine).join('\\n')}`),\n )\n return\n }\n controller.enqueue(encoder.encode('\\n'))\n controller.close()\n },\n })\n\n // Ids and counts only, never content: a report about people leaving\n // the platform is worth a row; who was in it is the workspace's own.\n void firestore\n .collection('adminAudit')\n .add({\n actorUid: decoded.uid,\n action: 'ai-usage.exported',\n target: `orgs/${orgId}/aiUsageByUser`,\n before: null,\n after: { month, rows: rows.length, hostId: hostId || null },\n at: FieldValue.serverTimestamp(),\n })\n .catch(() => undefined)\n\n return new Response(stream, {\n status: 200,\n headers: {\n 'Content-Type': 'text/csv; charset=utf-8',\n 'Content-Disposition': `attachment; filename=\"ai-usage-${month}.csv\"`,\n [AI_USAGE_EXPORT_ROWS_HEADER]: String(rows.length),\n 'Cache-Control': 'no-store, private',\n },\n })\n } catch (error) {\n // A refused credential is a 401, not a fault of ours (AGL-1993). Null\n // for anything else, so a real failure keeps the answer below.\n const unauthenticated = invalidIdTokenResponse(error)\n if (unauthenticated) return unauthenticated\n console.error('[ai/usage] read failed', orgId, error)\n return json({ error: 'AI usage unavailable' }, 500)\n }\n}\n\nexport { handler as GET }\n"],"names":["csvCell","pluginRequestFromWeb","emailUnverifiedResponse","firebaseAdmin","isImpersonationSession","memberHasOrgPermission","resolveOrgMembership","aiUsageMonthKeys","aiUsageMonthWithinRetention","aiUsageShare","readOrgAiUsageByUser","readUserAiUsageMonths","FieldValue","invalidIdTokenResponse","AI_USAGE_CSV_HEADER","AI_USAGE_EXPORT_ROWS_HEADER","aiUsageCsvLine","toAiUsageWireRow","MAX_USER_MONTHS","json","body","status","Response","handler","request","headers","params","method","query","rawHeaders","error","authorization","idToken","startsWith","slice","length","undefined","orgId","String","trim","now","Date","months","month","subjectUid","hostId","format","decoded","app","auth","verifyIdToken","email_verified","staff","membership","uid","member","firestore","own","Boolean","allowed","limit","Math","min","max","floor","Number","rows","orgRef","collection","doc","rollups","getAll","map","row","wire","index","credits","share","estCostUsd","get","requests","refusals","byKind","byHost","usage","sort","a","b","hostCredits","table","orgCredits","encoder","TextEncoder","PAGE","cursor","headed","stream","ReadableStream","pull","controller","enqueue","encode","join","page","close","add","actorUid","action","target","before","after","at","serverTimestamp","catch","unauthenticated","console","GET"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED,SAASA,OAAO,EAAEC,oBAAoB,QAAQ,sBAAqB;AACnE,SACEC,uBAAuB,EACvBC,aAAa,EACbC,sBAAsB,EACtBC,sBAAsB,EACtBC,oBAAoB,QACf,2BAA0B;AACjC,SACEC,gBAAgB,EAChBC,2BAA2B,EAC3BC,YAAY,QAEP,+BAA2B;AAClC,SACEC,oBAAoB,EACpBC,qBAAqB,QAChB,+BAA2B;AAClC,SAASC,UAAU,QAAQ,2BAA0B;AACrD,SAASC,sBAAsB,QAAQ,mDAAkD;AACzF,SACEC,mBAAmB,EACnBC,2BAA2B,EAC3BC,cAAc,EACdC,gBAAgB,QAGX,4BAAwB;AAE/B,6EAA6E;AAC7E,2EAA2E;AAC3E,2EAA2E;AAE3E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+BC,GAED,iDAAiD,GACjD,MAAMC,kBAAkB;AAExB,MAAMC,OAAO,CAACC,MAAeC,SAAmBC,SAASH,IAAI,CAACC,MAAM;QAAEC;IAAO;AAE7E,eAAeE,QAAQC,OAAgB;QAKfC,wBAODC,eAIAA,eAWKA,aACJA,gBACAA;IA5BtB,MAAM,EAAEC,MAAM,EAAEC,KAAK,EAAEH,SAASI,UAAU,EAAE,GAAG,MAAM5B,qBAAqBuB;IAC1E,MAAMC,UAAUI;IAChB,IAAIF,WAAW,OAAO,OAAOR,KAAK;QAAEW,OAAO;IAAqB,GAAG;IAEnE,MAAMC,iBAAgBN,yBAAAA,QAAQM,aAAa,YAArBN,yBAAyB;IAC/C,MAAMO,UAAUD,cAAcE,UAAU,CAAC,aACrCF,cAAcG,KAAK,CAAC,UAAUC,MAAM,IACpCC;IACJ,IAAI,CAACJ,SAAS,OAAOb,KAAK;QAAEW,OAAO;IAAkB,GAAG;IAExD,MAAMJ,SAAUE,gBAAAA,QAAS,CAAC;IAC1B,MAAMS,QAAQC,QAAOZ,gBAAAA,MAAM,CAAC,QAAQ,YAAfA,gBAAmB,IAAIa,IAAI;IAChD,IAAI,CAACF,OAAO,OAAOlB,KAAK;QAAEW,OAAO;IAAgB,GAAG;IACpD,MAAMU,MAAM,IAAIC;IAChB,MAAMC,SAASnC,iBAAiBiC;IAChC,MAAMG,QAAQL,QAAOZ,gBAAAA,MAAM,CAAC,QAAQ,YAAfA,gBAAmBgB,MAAM,CAAC,EAAE,EAAEH,IAAI;IACvD,IAAI,CAAC/B,4BAA4BmC,OAAOH,MAAM;QAC5C,OAAOrB,KACL;YACEW,OACE,CAAC,qBAAqB,EAAEY,OAAOP,MAAM,CAAC,SAAS,CAAC,GAChD,CAAC,eAAe,EAAEO,MAAM,CAACA,OAAOP,MAAM,GAAG,EAAE,CAAC,SAAS,EAAEO,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;QACvE,GACA;IAEJ;IACA,MAAME,aAAaN,QAAOZ,cAAAA,MAAM,CAAC,MAAM,YAAbA,cAAiB,IAAIa,IAAI;IACnD,MAAMM,SAASP,QAAOZ,iBAAAA,MAAM,CAAC,SAAS,YAAhBA,iBAAoB,IAAIa,IAAI;IAClD,MAAMO,SAASR,QAAOZ,iBAAAA,MAAM,CAAC,SAAS,YAAhBA,iBAAoB,QAAQa,IAAI;IAEtD,IAAI;QACF,MAAMQ,UAAU,MAAM5C,cAAc6C,GAAG,GAAGC,IAAI,GAAGC,aAAa,CAAClB;QAC/D,IAAI,CAACe,QAAQI,cAAc,IAAI,CAAC/C,uBAAuB2C,UAAU;YAC/D,OAAO7C;QACT;QACA,MAAMkD,QAAQL,OAAO,CAAC,QAAQ,KAAK;QACnC,MAAMM,aAAa,MAAM/C,qBAAqByC,QAAQO,GAAG,EAAEjB;QAC3D,MAAMkB,SAASF,8BAAAA,WAAYE,MAAM;QACjC,IAAI,CAACA,UAAU,CAACH,OAAO,OAAOjC,KAAK;YAAEW,OAAO;QAAY,GAAG;QAE3D,MAAM0B,YAAYrD,cAAc6C,GAAG,GAAGQ,SAAS;QAE/C,IAAIZ,YAAY;gBAYkBlB;YAXhC,sEAAsE;YACtE,kDAAkD;YAClD,MAAM+B,MAAMb,eAAeG,QAAQO,GAAG,IAAII,QAAQH;YAClD,IAAI,CAACE,OAAO,CAACL,OAAO;gBAClB,MAAMO,UACJ,AAAC,MAAMtD,uBAAuBgC,OAAOkB,QAAQ,mBAC5C,MAAMlD,uBAAuBgC,OAAOkB,QAAQ;gBAC/C,IAAI,CAACI,SAAS,OAAOxC,KAAK;oBAAEW,OAAO;gBAAwB,GAAG;YAChE;YACA,MAAM8B,QAAQC,KAAKC,GAAG,CACpB5C,iBACA2C,KAAKE,GAAG,CAAC,GAAGF,KAAKG,KAAK,CAACC,QAAOvC,gBAAAA,MAAM,CAAC,QAAQ,YAAfA,gBAAmB,MAAM;YAEzD,MAAMwC,OAAO,MAAMvD,sBAAsB6C,WAAWnB,OAAOO,YAAYgB;YACvE,MAAMO,SAASX,UAAUY,UAAU,CAAC,QAAQC,GAAG,CAAChC;YAChD,MAAMiC,UAAUJ,KAAK/B,MAAM,GACvB,MAAMqB,UAAUe,MAAM,IACjBL,KAAKM,GAAG,CAAC,CAACC,MAAQN,OAAOC,UAAU,CAAC,eAAeC,GAAG,CAACI,IAAI9B,KAAK,MAErE,EAAE;YACN,MAAM+B,OAAwB;gBAC5BpB,KAAKV;gBACLF,QAAQwB,KAAKM,GAAG,CAAC,CAACC,KAAyBE;;wBAKhCL;2BAL2C;wBACpD3B,OAAO8B,IAAI9B,KAAK;wBAChBiC,SAASH,IAAIG,OAAO;wBACpBC,OAAOpE,aACLgE,IAAIK,UAAU,EACdb,gBAAOK,iBAAAA,OAAO,CAACK,MAAM,qBAAdL,eAAgBS,GAAG,CAAC,gCAAiB;wBAE9CC,UAAUP,IAAIO,QAAQ;wBACtBC,UAAUR,IAAIQ,QAAQ;wBACtBC,QAAQT,IAAIS,MAAM;wBAClBC,QAAQV,IAAIU,MAAM;oBACpB;;YACF;YACA,OAAOhE,KAAKuD,MAAM;QACpB;QAEA,mEAAmE;QACnE,IAAI,CAACtB,SAAS,CAAE,MAAM/C,uBAAuBgC,OAAOkB,QAAQ,iBAAkB;YAC5E,OAAOpC,KAAK;gBAAEW,OAAO;YAAwB,GAAG;QAClD;QACA,MAAMsD,QAAQ,MAAM1E,qBAAqB8C,WAAWnB,OAAOM;QAC3D,MAAMuB,OAAOkB,MAAMlB,IAAI,CAACM,GAAG,CAAC,CAACC,MAAQxD,iBAAiBwD,KAAK5B;QAC3D,IAAIA,QAAQ;YACVqB,KAAKmB,IAAI,CACP,CAACC,GAAGC;oBACDA,gBAAuBD;uBAAxB,EAACC,iBAAAA,EAAEC,WAAW,YAAbD,iBAAiB,OAAMD,iBAAAA,EAAEE,WAAW,YAAbF,iBAAiB,MAAMC,EAAEX,OAAO,GAAGU,EAAEV,OAAO;;QAE1E;QAEA,IAAI9B,WAAW,OAAO;YACpB,MAAM2C,QAA6B;gBACjC9C;gBACAD;gBACAgD,YAAYN,MAAMM,UAAU;gBAC5BxB;YACF;YACA,OAAO/C,KAAKsE,OAAO;QACrB;QAEA;;;;;;KAMC,GACD,MAAME,UAAU,IAAIC;QACpB,MAAMC,OAAO;QACb,IAAIC,SAAS;QACb,IAAIC,SAAS;QACb,MAAMC,SAAS,IAAIC,eAA2B;YAC5CC,MAAKC,UAAU;gBACb,IAAI,CAACJ,QAAQ;oBACXA,SAAS;oBACTI,WAAWC,OAAO,CAACT,QAAQU,MAAM,CAACvF,oBAAoB0D,GAAG,CAACxE,SAASsG,IAAI,CAAC;oBACxE;gBACF;gBACA,IAAIR,SAAS5B,KAAK/B,MAAM,EAAE;oBACxB,MAAMoE,OAAOrC,KAAKhC,KAAK,CAAC4D,QAAQA,SAASD;oBACzCC,UAAUS,KAAKpE,MAAM;oBACrBgE,WAAWC,OAAO,CAChBT,QAAQU,MAAM,CAAC,CAAC,EAAE,EAAEE,KAAK/B,GAAG,CAACxD,gBAAgBsF,IAAI,CAAC,OAAO;oBAE3D;gBACF;gBACAH,WAAWC,OAAO,CAACT,QAAQU,MAAM,CAAC;gBAClCF,WAAWK,KAAK;YAClB;QACF;QAEA,oEAAoE;QACpE,qEAAqE;QACrE,KAAKhD,UACFY,UAAU,CAAC,cACXqC,GAAG,CAAC;YACHC,UAAU3D,QAAQO,GAAG;YACrBqD,QAAQ;YACRC,QAAQ,CAAC,KAAK,EAAEvE,MAAM,cAAc,CAAC;YACrCwE,QAAQ;YACRC,OAAO;gBAAEnE;gBAAOuB,MAAMA,KAAK/B,MAAM;gBAAEU,QAAQA,UAAU;YAAK;YAC1DkE,IAAInG,WAAWoG,eAAe;QAChC,GACCC,KAAK,CAAC,IAAM7E;QAEf,OAAO,IAAId,SAAS0E,QAAQ;YAC1B3E,QAAQ;YACRI,SAAS;gBACP,gBAAgB;gBAChB,uBAAuB,CAAC,+BAA+B,EAAEkB,MAAM,KAAK,CAAC;gBACrE,CAAC5B,4BAA4B,EAAEuB,OAAO4B,KAAK/B,MAAM;gBACjD,iBAAiB;YACnB;QACF;IACF,EAAE,OAAOL,OAAO;QACd,sEAAsE;QACtE,+DAA+D;QAC/D,MAAMoF,kBAAkBrG,uBAAuBiB;QAC/C,IAAIoF,iBAAiB,OAAOA;QAC5BC,QAAQrF,KAAK,CAAC,0BAA0BO,OAAOP;QAC/C,OAAOX,KAAK;YAAEW,OAAO;QAAuB,GAAG;IACjD;AACF;AAEA,SAASP,WAAW6F,GAAG,GAAE"}