@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,225 @@
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
+ import { type AssistRefusedBy } from '@aglyn/aglyn/app-utils/assist-credits';
18
+ import type { AglynOrgBilling } from '@aglyn/aglyn/foundation/definitions/org-billing.types';
19
+ /**
20
+ * The Free AI taste's precautions (AGL-2925) — the half of the meter that
21
+ * exists only because the Free band has no invoice behind it.
22
+ *
23
+ * `FREE_AI_TASTE_CREDITS_PER_MONTH` gives every Free workspace 300 credits a
24
+ * month as a wall. A wall per WORKSPACE is not a bound per PERSON: one
25
+ * account may hold three free workspaces (AGL-2265), a script can mint
26
+ * accounts faster than a person can, and a refused brief costs the same
27
+ * tokens as an answered one. So the taste is metered a second time, per
28
+ * account, and bounded three more ways. Everything below is read and
29
+ * decided INSIDE `reserveAssistMessage`'s transaction, so a burst of
30
+ * concurrent requests cannot each read "under" and all proceed — the same
31
+ * property every other rung of that reservation has.
32
+ *
33
+ * ## Documents (both ABSENT from firebase-firestore.rules on purpose)
34
+ *
35
+ * users/{uid}/aiUsage/{YYYY-MM} the ACCOUNT's month:
36
+ * { month, estCostUsd, requests, days: { [YYYY-MM-DD]: { requests,
37
+ * refusals } }, updatedAt }
38
+ * platformAiFreeSpend/{YYYY-MM-DD} the PLATFORM's day of free spend:
39
+ * { day, estCostUsd, requests, refusals, alertedAt?, pausedAt?,
40
+ * updatedAt }
41
+ *
42
+ * The account document sits under `users/{uid}`, whose owner may read and
43
+ * write the user document itself. It may not touch this subcollection: the
44
+ * `users` block matches its subcollections BY NAME and carries no wildcard,
45
+ * so an unmatched name is default-deny for every client, staff included —
46
+ * the same property `assistUsage` relies on one level down. An owner who
47
+ * could write here could reset their own allowance, which is the whole
48
+ * meter. The platform document is a top-level collection alongside
49
+ * `platformCronBeats`, unmatched and therefore closed, and every reader is
50
+ * an Admin-SDK reader behind the staff gate.
51
+ *
52
+ * ## Whose account
53
+ *
54
+ * The WORKSPACE OWNER's. A member invited to someone else's free workspace
55
+ * draws from that workspace's band and from its owner's allowance, never
56
+ * from their own account: the owner is the person the free workspace is
57
+ * attributed to for the ceiling on how many they may hold, and attributing
58
+ * the spend the same way is what keeps the two bounds describing one
59
+ * person. `ownerUid` first, `createdByUid` for an org that predates
60
+ * ownership stamping — the same union the free-workspace count reads.
61
+ */
62
+ /** Where an account's month of free AI spend lives, under `users/{uid}`. */
63
+ export declare const FREE_AI_ACCOUNT_USAGE_COLLECTION = "aiUsage";
64
+ /** The top-level collection holding one document per UTC day of free spend. */
65
+ export declare const PLATFORM_AI_FREE_SPEND_COLLECTION = "platformAiFreeSpend";
66
+ /**
67
+ * Refusals a day before an account's free generation pauses. Three, not
68
+ * one: a single declined brief is a normal outcome of asking an assistant
69
+ * for things, and pausing on it would punish an ordinary afternoon. Three
70
+ * in a day is somebody probing what the model will write.
71
+ */
72
+ export declare const AI_FREE_REFUSALS_PER_DAY = 3;
73
+ /** The share of the platform ceiling at which staff are told, once a day. */
74
+ export declare const AI_FREE_PLATFORM_ALERT_SHARE = 0.8;
75
+ /** The account allowance, in USD of provider spend — the taste, per person. */
76
+ export declare const FREE_AI_ACCOUNT_BUDGET_USD: number;
77
+ /**
78
+ * Free requests one account may make a UTC day, across its workspaces
79
+ * (`AI_FREE_DAILY_REQUESTS`, default 30).
80
+ *
81
+ * A request, not a message: this counts every reservation the account's
82
+ * free workspaces take, at either door. Thirty is three times the
83
+ * per-workspace message cap, so one workspace never hits it before its own
84
+ * cap and three workspaces hit it exactly when their caps would have
85
+ * summed — it bounds the multiplier, not the ordinary day. Zero is honored
86
+ * as "no free requests", which is a decision an operator may write down;
87
+ * junk and an empty value take the default.
88
+ */
89
+ export declare function aiFreeDailyRequests(): number;
90
+ /**
91
+ * The platform-wide ceiling on ONE UTC day of free-tier provider spend
92
+ * (`AI_FREE_DAILY_PLATFORM_CEILING_USD`, default $25).
93
+ *
94
+ * Every other bound here is per something — per workspace, per account,
95
+ * per address — and a wave of new accounts clears all of them one at a
96
+ * time. This is the bound on the sum. At 80% of it staff are mailed; at
97
+ * 100% every free reservation refuses until the day rolls, paid workspaces
98
+ * untouched, and the manual `ai-generate` lockdown key remains the switch
99
+ * for anything the ceiling did not catch.
100
+ *
101
+ * Fails to the DEFAULT, never to "no ceiling", for the reason the operator
102
+ * COGS limit does: an empty, negative, zero or unparseable value is not a
103
+ * decision to run unbounded. There is deliberately no `off` word — a
104
+ * deployment that wants no ceiling sets a figure it is content to spend.
105
+ */
106
+ export declare function aiFreeDailyPlatformCeilingUsd(): number;
107
+ /** The account a free workspace's spend is attributed to. */
108
+ export interface FreeAssistAccount {
109
+ /**
110
+ * The workspace owner's uid, or `null` for an org document that names no
111
+ * owner and no creator — every org created since ownership was stamped
112
+ * names one, so `null` is the shape of a fixture or a very old record.
113
+ * The account rungs are skipped for it; the org's own band still binds.
114
+ */
115
+ accountUid: string | null;
116
+ }
117
+ /** The org fields the attribution reads, beside the billing ones. */
118
+ export type AssistMeteredOrg = Partial<AglynOrgBilling> & {
119
+ ownerUid?: string | null;
120
+ createdByUid?: string | null;
121
+ };
122
+ /**
123
+ * The account to meter a workspace's free spend against, or `null` when the
124
+ * workspace is not on the Free plan and none of this applies.
125
+ *
126
+ * `resolveEffectivePlan`, not `org.plan`: a workspace whose subscription
127
+ * died is Free again, and its spend is the taste's spend again.
128
+ */
129
+ export declare function freeAssistAccount(org: AssistMeteredOrg | null | undefined): FreeAssistAccount | null;
130
+ export declare function freeAccountUsageRef(firestore: FirebaseFirestore.Firestore, accountUid: string, month: string): FirebaseFirestore.DocumentReference;
131
+ export declare function platformFreeSpendRef(firestore: FirebaseFirestore.Firestore, day: string): FirebaseFirestore.DocumentReference;
132
+ /** What the reservation read about the account and the platform. */
133
+ export interface FreeTasteReads {
134
+ accountCostUsd: number;
135
+ accountRequestsToday: number;
136
+ accountRefusalsToday: number;
137
+ platformCostUsd: number;
138
+ platformPaused: boolean;
139
+ }
140
+ /** The two snapshots, as the transaction handed them over, into figures. */
141
+ export declare function freeTasteReadsFrom(account: FirebaseFirestore.DocumentSnapshot | null, platform: FirebaseFirestore.DocumentSnapshot | null, day: string): FreeTasteReads;
142
+ /**
143
+ * Which of the taste's own precautions refuses, or `null` when none does —
144
+ * pure, so the spec can force every rung red without a Firestore.
145
+ *
146
+ * Checked in the order the reads are cheapest to explain: the daily
147
+ * request cap and the refusal pause (both reset on a clock the customer
148
+ * can be told about), then the account's month (an upgrade is the way
149
+ * out), then the platform ceiling (nobody's doing; try again tomorrow).
150
+ * The org's own rungs — its daily message cap, its band — run before this
151
+ * in the reservation, so a workspace at its own band hears about its own
152
+ * band rather than about its owner's other workspaces.
153
+ *
154
+ * Every comparison is `>=` against a count the reservation is about to
155
+ * increment, so a cap of N admits exactly N. A paused platform refuses
156
+ * regardless of the running figure: the pause is a decision recorded on
157
+ * the document, and a ceiling raised by an operator mid-day does not undo
158
+ * it — the day rolls, or staff clear the document.
159
+ */
160
+ export declare function freeTasteRefusal(reads: FreeTasteReads, limits?: {
161
+ dailyRequests?: number;
162
+ refusalsPerDay?: number;
163
+ accountBudgetUsd?: number;
164
+ platformCeilingUsd?: number;
165
+ }): Extract<AssistRefusedBy, 'requests' | 'refusals' | 'account' | 'platform'> | null;
166
+ /**
167
+ * The account-side write one admitted free reservation owes: a request
168
+ * counted for the month and for the day. `set(…, { merge: true })` with
169
+ * nested increments, so the first request of a month conjures the document
170
+ * and a day's map entry appears the first time that day is counted.
171
+ */
172
+ export declare function freeAccountReservationWrite(month: string, day: string): Record<string, unknown>;
173
+ /**
174
+ * The two writes one metered free turn owes, beside the org's own rollup.
175
+ *
176
+ * A `refusal` stop is the one case where the meters disagree on purpose. The
177
+ * tokens were spent, so the PLATFORM document — which bounds our money —
178
+ * takes the cost and counts the refusal. The ACCOUNT's credits do not move:
179
+ * a refusal never draws credits, because a customer whose brief was
180
+ * declined has not been given anything, and because a run of declined
181
+ * briefs is answered by the refusal pause rather than by an emptied band.
182
+ * The account's day counts the refusal, which is what the pause reads.
183
+ */
184
+ export declare function freeTasteMeterWrites(input: {
185
+ estCostUsd: number;
186
+ refused: boolean;
187
+ day: string;
188
+ month: string;
189
+ }): {
190
+ account: Record<string, unknown>;
191
+ platform: Record<string, unknown>;
192
+ };
193
+ /**
194
+ * After a free turn is metered: tell staff at 80% of the day's ceiling,
195
+ * and record the pause at 100% — each ONCE per UTC day, deduplicated on
196
+ * the day document itself inside a transaction, so two turns landing
197
+ * together cannot both cross a threshold and both announce it.
198
+ *
199
+ * The refusal at the ceiling is NOT decided here; `freeTasteRefusal` reads
200
+ * the figure inside every reservation and refuses on it directly. This
201
+ * only says so out loud: the email, and an `adminAudit` row under
202
+ * `platform.aiFreeSpend.paused` so the staff audit trail shows the day the
203
+ * taste switched itself off. Both are best-effort and neither can fail the
204
+ * turn that triggered them — the turn is already paid for.
205
+ *
206
+ * Returns what it announced, for the spec and for the log.
207
+ */
208
+ export declare function announcePlatformFreeSpend(firestore: FirebaseFirestore.Firestore, day: string): Promise<{
209
+ alerted: boolean;
210
+ paused: boolean;
211
+ estCostUsd: number;
212
+ }>;
213
+ /** The staff readout of today's free spend, for the assist signals page. */
214
+ export interface PlatformFreeSpendReadout {
215
+ day: string;
216
+ estCostUsd: number;
217
+ requests: number;
218
+ refusals: number;
219
+ ceilingUsd: number;
220
+ /** True once the 80% mail went out today. */
221
+ alerted: boolean;
222
+ /** True while free generation is refused for the day. */
223
+ paused: boolean;
224
+ }
225
+ export declare function readPlatformFreeSpend(firestore: FirebaseFirestore.Firestore, day: string): Promise<PlatformFreeSpendReadout>;
@@ -0,0 +1,308 @@
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
+ */ import { FieldValue } from "firebase-admin/firestore";
18
+ import { assistUsdFromCredits } from "@aglyn/aglyn/app-utils/assist-credits";
19
+ import { FREE_AI_TASTE_CREDITS_PER_MONTH, resolveEffectivePlan } from "@aglyn/aglyn/app-utils/plan-entitlements";
20
+ import { sendStaffAlertEmail } from "@aglyn/tenant-data-admin/server/staff-alert-email";
21
+ /**
22
+ * The Free AI taste's precautions (AGL-2925) — the half of the meter that
23
+ * exists only because the Free band has no invoice behind it.
24
+ *
25
+ * `FREE_AI_TASTE_CREDITS_PER_MONTH` gives every Free workspace 300 credits a
26
+ * month as a wall. A wall per WORKSPACE is not a bound per PERSON: one
27
+ * account may hold three free workspaces (AGL-2265), a script can mint
28
+ * accounts faster than a person can, and a refused brief costs the same
29
+ * tokens as an answered one. So the taste is metered a second time, per
30
+ * account, and bounded three more ways. Everything below is read and
31
+ * decided INSIDE `reserveAssistMessage`'s transaction, so a burst of
32
+ * concurrent requests cannot each read "under" and all proceed — the same
33
+ * property every other rung of that reservation has.
34
+ *
35
+ * ## Documents (both ABSENT from firebase-firestore.rules on purpose)
36
+ *
37
+ * users/{uid}/aiUsage/{YYYY-MM} the ACCOUNT's month:
38
+ * { month, estCostUsd, requests, days: { [YYYY-MM-DD]: { requests,
39
+ * refusals } }, updatedAt }
40
+ * platformAiFreeSpend/{YYYY-MM-DD} the PLATFORM's day of free spend:
41
+ * { day, estCostUsd, requests, refusals, alertedAt?, pausedAt?,
42
+ * updatedAt }
43
+ *
44
+ * The account document sits under `users/{uid}`, whose owner may read and
45
+ * write the user document itself. It may not touch this subcollection: the
46
+ * `users` block matches its subcollections BY NAME and carries no wildcard,
47
+ * so an unmatched name is default-deny for every client, staff included —
48
+ * the same property `assistUsage` relies on one level down. An owner who
49
+ * could write here could reset their own allowance, which is the whole
50
+ * meter. The platform document is a top-level collection alongside
51
+ * `platformCronBeats`, unmatched and therefore closed, and every reader is
52
+ * an Admin-SDK reader behind the staff gate.
53
+ *
54
+ * ## Whose account
55
+ *
56
+ * The WORKSPACE OWNER's. A member invited to someone else's free workspace
57
+ * draws from that workspace's band and from its owner's allowance, never
58
+ * from their own account: the owner is the person the free workspace is
59
+ * attributed to for the ceiling on how many they may hold, and attributing
60
+ * the spend the same way is what keeps the two bounds describing one
61
+ * person. `ownerUid` first, `createdByUid` for an org that predates
62
+ * ownership stamping — the same union the free-workspace count reads.
63
+ */ /** Where an account's month of free AI spend lives, under `users/{uid}`. */ export const FREE_AI_ACCOUNT_USAGE_COLLECTION = 'aiUsage';
64
+ /** The top-level collection holding one document per UTC day of free spend. */ export const PLATFORM_AI_FREE_SPEND_COLLECTION = 'platformAiFreeSpend';
65
+ /**
66
+ * Refusals a day before an account's free generation pauses. Three, not
67
+ * one: a single declined brief is a normal outcome of asking an assistant
68
+ * for things, and pausing on it would punish an ordinary afternoon. Three
69
+ * in a day is somebody probing what the model will write.
70
+ */ export const AI_FREE_REFUSALS_PER_DAY = 3;
71
+ /** The share of the platform ceiling at which staff are told, once a day. */ export const AI_FREE_PLATFORM_ALERT_SHARE = 0.8;
72
+ /** The account allowance, in USD of provider spend — the taste, per person. */ export const FREE_AI_ACCOUNT_BUDGET_USD = assistUsdFromCredits(FREE_AI_TASTE_CREDITS_PER_MONTH);
73
+ /**
74
+ * Free requests one account may make a UTC day, across its workspaces
75
+ * (`AI_FREE_DAILY_REQUESTS`, default 30).
76
+ *
77
+ * A request, not a message: this counts every reservation the account's
78
+ * free workspaces take, at either door. Thirty is three times the
79
+ * per-workspace message cap, so one workspace never hits it before its own
80
+ * cap and three workspaces hit it exactly when their caps would have
81
+ * summed — it bounds the multiplier, not the ordinary day. Zero is honored
82
+ * as "no free requests", which is a decision an operator may write down;
83
+ * junk and an empty value take the default.
84
+ */ export function aiFreeDailyRequests() {
85
+ const raw = process.env.AI_FREE_DAILY_REQUESTS;
86
+ const parsed = raw ? Number(raw) : Number.NaN;
87
+ return Number.isFinite(parsed) && parsed >= 0 ? Math.floor(parsed) : 30;
88
+ }
89
+ /**
90
+ * The platform-wide ceiling on ONE UTC day of free-tier provider spend
91
+ * (`AI_FREE_DAILY_PLATFORM_CEILING_USD`, default $25).
92
+ *
93
+ * Every other bound here is per something — per workspace, per account,
94
+ * per address — and a wave of new accounts clears all of them one at a
95
+ * time. This is the bound on the sum. At 80% of it staff are mailed; at
96
+ * 100% every free reservation refuses until the day rolls, paid workspaces
97
+ * untouched, and the manual `ai-generate` lockdown key remains the switch
98
+ * for anything the ceiling did not catch.
99
+ *
100
+ * Fails to the DEFAULT, never to "no ceiling", for the reason the operator
101
+ * COGS limit does: an empty, negative, zero or unparseable value is not a
102
+ * decision to run unbounded. There is deliberately no `off` word — a
103
+ * deployment that wants no ceiling sets a figure it is content to spend.
104
+ */ export function aiFreeDailyPlatformCeilingUsd() {
105
+ var _process_env_AI_FREE_DAILY_PLATFORM_CEILING_USD;
106
+ const raw = String((_process_env_AI_FREE_DAILY_PLATFORM_CEILING_USD = process.env.AI_FREE_DAILY_PLATFORM_CEILING_USD) != null ? _process_env_AI_FREE_DAILY_PLATFORM_CEILING_USD : '').trim();
107
+ const parsed = raw ? Number(raw) : Number.NaN;
108
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : 25;
109
+ }
110
+ /**
111
+ * The account to meter a workspace's free spend against, or `null` when the
112
+ * workspace is not on the Free plan and none of this applies.
113
+ *
114
+ * `resolveEffectivePlan`, not `org.plan`: a workspace whose subscription
115
+ * died is Free again, and its spend is the taste's spend again.
116
+ */ export function freeAssistAccount(org) {
117
+ var _ref, _ref1;
118
+ if (resolveEffectivePlan(org) !== 'free') return null;
119
+ const owner = String((_ref = org == null ? void 0 : org.ownerUid) != null ? _ref : '').trim();
120
+ const creator = String((_ref1 = org == null ? void 0 : org.createdByUid) != null ? _ref1 : '').trim();
121
+ return {
122
+ accountUid: owner || creator || null
123
+ };
124
+ }
125
+ export function freeAccountUsageRef(firestore, accountUid, month) {
126
+ return firestore.collection('users').doc(accountUid).collection(FREE_AI_ACCOUNT_USAGE_COLLECTION).doc(month);
127
+ }
128
+ export function platformFreeSpendRef(firestore, day) {
129
+ return firestore.collection(PLATFORM_AI_FREE_SPEND_COLLECTION).doc(day);
130
+ }
131
+ /** The two snapshots, as the transaction handed them over, into figures. */ export function freeTasteReadsFrom(account, platform, day) {
132
+ var _ref, _days_day, _ref1, _today_requests, _today_refusals, _ref2;
133
+ const days = (_ref = account == null ? void 0 : account.get('days')) != null ? _ref : {};
134
+ const today = (_days_day = days[day]) != null ? _days_day : {};
135
+ return {
136
+ accountCostUsd: Number((_ref1 = account == null ? void 0 : account.get('estCostUsd')) != null ? _ref1 : 0),
137
+ accountRequestsToday: Number((_today_requests = today.requests) != null ? _today_requests : 0),
138
+ accountRefusalsToday: Number((_today_refusals = today.refusals) != null ? _today_refusals : 0),
139
+ platformCostUsd: Number((_ref2 = platform == null ? void 0 : platform.get('estCostUsd')) != null ? _ref2 : 0),
140
+ platformPaused: Boolean(platform == null ? void 0 : platform.get('pausedAt'))
141
+ };
142
+ }
143
+ /**
144
+ * Which of the taste's own precautions refuses, or `null` when none does —
145
+ * pure, so the spec can force every rung red without a Firestore.
146
+ *
147
+ * Checked in the order the reads are cheapest to explain: the daily
148
+ * request cap and the refusal pause (both reset on a clock the customer
149
+ * can be told about), then the account's month (an upgrade is the way
150
+ * out), then the platform ceiling (nobody's doing; try again tomorrow).
151
+ * The org's own rungs — its daily message cap, its band — run before this
152
+ * in the reservation, so a workspace at its own band hears about its own
153
+ * band rather than about its owner's other workspaces.
154
+ *
155
+ * Every comparison is `>=` against a count the reservation is about to
156
+ * increment, so a cap of N admits exactly N. A paused platform refuses
157
+ * regardless of the running figure: the pause is a decision recorded on
158
+ * the document, and a ceiling raised by an operator mid-day does not undo
159
+ * it — the day rolls, or staff clear the document.
160
+ */ export function freeTasteRefusal(reads, limits = {}) {
161
+ var _limits_dailyRequests, _limits_refusalsPerDay, _limits_accountBudgetUsd, _limits_platformCeilingUsd;
162
+ const dailyRequests = (_limits_dailyRequests = limits.dailyRequests) != null ? _limits_dailyRequests : aiFreeDailyRequests();
163
+ const refusalsPerDay = (_limits_refusalsPerDay = limits.refusalsPerDay) != null ? _limits_refusalsPerDay : AI_FREE_REFUSALS_PER_DAY;
164
+ const accountBudgetUsd = (_limits_accountBudgetUsd = limits.accountBudgetUsd) != null ? _limits_accountBudgetUsd : FREE_AI_ACCOUNT_BUDGET_USD;
165
+ const platformCeilingUsd = (_limits_platformCeilingUsd = limits.platformCeilingUsd) != null ? _limits_platformCeilingUsd : aiFreeDailyPlatformCeilingUsd();
166
+ if (reads.accountRequestsToday >= dailyRequests) return 'requests';
167
+ if (reads.accountRefusalsToday >= refusalsPerDay) return 'refusals';
168
+ if (reads.accountCostUsd >= accountBudgetUsd) return 'account';
169
+ if (reads.platformPaused || reads.platformCostUsd >= platformCeilingUsd) {
170
+ return 'platform';
171
+ }
172
+ return null;
173
+ }
174
+ /**
175
+ * The account-side write one admitted free reservation owes: a request
176
+ * counted for the month and for the day. `set(…, { merge: true })` with
177
+ * nested increments, so the first request of a month conjures the document
178
+ * and a day's map entry appears the first time that day is counted.
179
+ */ export function freeAccountReservationWrite(month, day) {
180
+ const increment = FieldValue.increment;
181
+ return {
182
+ month,
183
+ requests: increment(1),
184
+ days: {
185
+ [day]: {
186
+ requests: increment(1)
187
+ }
188
+ },
189
+ updatedAt: FieldValue.serverTimestamp()
190
+ };
191
+ }
192
+ /**
193
+ * The two writes one metered free turn owes, beside the org's own rollup.
194
+ *
195
+ * A `refusal` stop is the one case where the meters disagree on purpose. The
196
+ * tokens were spent, so the PLATFORM document — which bounds our money —
197
+ * takes the cost and counts the refusal. The ACCOUNT's credits do not move:
198
+ * a refusal never draws credits, because a customer whose brief was
199
+ * declined has not been given anything, and because a run of declined
200
+ * briefs is answered by the refusal pause rather than by an emptied band.
201
+ * The account's day counts the refusal, which is what the pause reads.
202
+ */ export function freeTasteMeterWrites(input) {
203
+ const increment = FieldValue.increment;
204
+ const serverTimestamp = FieldValue.serverTimestamp;
205
+ const { estCostUsd, refused, day, month } = input;
206
+ return {
207
+ account: refused ? {
208
+ month,
209
+ days: {
210
+ [day]: {
211
+ refusals: increment(1)
212
+ }
213
+ },
214
+ updatedAt: serverTimestamp()
215
+ } : {
216
+ month,
217
+ estCostUsd: increment(estCostUsd),
218
+ updatedAt: serverTimestamp()
219
+ },
220
+ platform: {
221
+ day,
222
+ estCostUsd: increment(estCostUsd),
223
+ requests: increment(1),
224
+ refusals: increment(refused ? 1 : 0),
225
+ updatedAt: serverTimestamp()
226
+ }
227
+ };
228
+ }
229
+ /**
230
+ * After a free turn is metered: tell staff at 80% of the day's ceiling,
231
+ * and record the pause at 100% — each ONCE per UTC day, deduplicated on
232
+ * the day document itself inside a transaction, so two turns landing
233
+ * together cannot both cross a threshold and both announce it.
234
+ *
235
+ * The refusal at the ceiling is NOT decided here; `freeTasteRefusal` reads
236
+ * the figure inside every reservation and refuses on it directly. This
237
+ * only says so out loud: the email, and an `adminAudit` row under
238
+ * `platform.aiFreeSpend.paused` so the staff audit trail shows the day the
239
+ * taste switched itself off. Both are best-effort and neither can fail the
240
+ * turn that triggered them — the turn is already paid for.
241
+ *
242
+ * Returns what it announced, for the spec and for the log.
243
+ */ export async function announcePlatformFreeSpend(firestore, day) {
244
+ const ceilingUsd = aiFreeDailyPlatformCeilingUsd();
245
+ const ref = platformFreeSpendRef(firestore, day);
246
+ const crossed = await firestore.runTransaction(async (tx)=>{
247
+ var _snapshot_get;
248
+ const snapshot = await tx.get(ref);
249
+ const estCostUsd = Number((_snapshot_get = snapshot.get('estCostUsd')) != null ? _snapshot_get : 0);
250
+ const alert = !snapshot.get('alertedAt') && estCostUsd >= ceilingUsd * AI_FREE_PLATFORM_ALERT_SHARE;
251
+ const pause = !snapshot.get('pausedAt') && estCostUsd >= ceilingUsd;
252
+ if (alert || pause) {
253
+ tx.set(ref, _extends({}, alert ? {
254
+ alertedAt: FieldValue.serverTimestamp()
255
+ } : {}, pause ? {
256
+ pausedAt: FieldValue.serverTimestamp()
257
+ } : {}), {
258
+ merge: true
259
+ });
260
+ }
261
+ return {
262
+ alerted: alert,
263
+ paused: pause,
264
+ estCostUsd
265
+ };
266
+ });
267
+ if (!crossed.alerted && !crossed.paused) return crossed;
268
+ const figure = `$${crossed.estCostUsd.toFixed(2)} of the $${ceilingUsd.toFixed(2)} ceiling`;
269
+ if (crossed.paused) {
270
+ await firestore.collection('adminAudit').add({
271
+ actorUid: 'system:ai-free-spend',
272
+ action: 'platform.aiFreeSpend.paused',
273
+ target: `${PLATFORM_AI_FREE_SPEND_COLLECTION}/${day}`,
274
+ after: {
275
+ day,
276
+ estCostUsd: crossed.estCostUsd,
277
+ ceilingUsd
278
+ },
279
+ at: FieldValue.serverTimestamp()
280
+ }).catch((error)=>console.error('[ai-free-spend] audit row failed', error));
281
+ }
282
+ await sendStaffAlertEmail({
283
+ subject: crossed.paused ? `Free AI generation paused for ${day}: ${figure}` : `Free AI spend at 80% of today's ceiling (${day}): ${figure}`,
284
+ text: crossed.paused ? `Free-tier AI spend for ${day} (UTC) reached ${figure} ` + '(AI_FREE_DAILY_PLATFORM_CEILING_USD). Every Free workspace is ' + 'refused AI generation until the UTC day rolls; paid workspaces are ' + 'unaffected. If this is an abuse wave rather than organic use, the ' + '`ai-generate` feature lock on Staff → Lockdown stops generation ' + 'for everyone, and the assist signals page shows which workspaces ' + 'spent it.' : `Free-tier AI spend for ${day} (UTC) is at ${figure} ` + '(AI_FREE_DAILY_PLATFORM_CEILING_USD). At 100% every Free ' + 'workspace is refused AI generation until the day rolls. The ' + 'assist signals page shows the day so far; the `ai-generate` ' + 'feature lock on Staff → Lockdown is the manual stop.',
285
+ context: 'ai-free-spend'
286
+ });
287
+ return crossed;
288
+ }
289
+ export async function readPlatformFreeSpend(firestore, day) {
290
+ var _snapshot_get, _snapshot_get1, _snapshot_get2;
291
+ const snapshot = await platformFreeSpendRef(firestore, day).get();
292
+ const ceilingUsd = aiFreeDailyPlatformCeilingUsd();
293
+ const estCostUsd = Number((_snapshot_get = snapshot.get('estCostUsd')) != null ? _snapshot_get : 0);
294
+ return {
295
+ day,
296
+ estCostUsd,
297
+ requests: Number((_snapshot_get1 = snapshot.get('requests')) != null ? _snapshot_get1 : 0),
298
+ refusals: Number((_snapshot_get2 = snapshot.get('refusals')) != null ? _snapshot_get2 : 0),
299
+ ceilingUsd,
300
+ alerted: Boolean(snapshot.get('alertedAt')),
301
+ // The pause is the recorded decision OR the live figure: a day that
302
+ // crossed the ceiling before anything announced it is paused all the
303
+ // same, because the reservation refuses on the figure.
304
+ paused: Boolean(snapshot.get('pausedAt')) || estCostUsd >= ceilingUsd
305
+ };
306
+ }
307
+
308
+ //# sourceMappingURL=assist-free-taste.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/usage/assist-free-taste.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 { FieldValue } from 'firebase-admin/firestore'\nimport {\n assistUsdFromCredits,\n type AssistRefusedBy,\n} from '@aglyn/aglyn/app-utils/assist-credits'\nimport {\n FREE_AI_TASTE_CREDITS_PER_MONTH,\n resolveEffectivePlan,\n} from '@aglyn/aglyn/app-utils/plan-entitlements'\nimport type { AglynOrgBilling } from '@aglyn/aglyn/foundation/definitions/org-billing.types'\nimport { sendStaffAlertEmail } from '@aglyn/tenant-data-admin/server/staff-alert-email'\n\n/**\n * The Free AI taste's precautions (AGL-2925) — the half of the meter that\n * exists only because the Free band has no invoice behind it.\n *\n * `FREE_AI_TASTE_CREDITS_PER_MONTH` gives every Free workspace 300 credits a\n * month as a wall. A wall per WORKSPACE is not a bound per PERSON: one\n * account may hold three free workspaces (AGL-2265), a script can mint\n * accounts faster than a person can, and a refused brief costs the same\n * tokens as an answered one. So the taste is metered a second time, per\n * account, and bounded three more ways. Everything below is read and\n * decided INSIDE `reserveAssistMessage`'s transaction, so a burst of\n * concurrent requests cannot each read \"under\" and all proceed — the same\n * property every other rung of that reservation has.\n *\n * ## Documents (both ABSENT from firebase-firestore.rules on purpose)\n *\n * users/{uid}/aiUsage/{YYYY-MM} the ACCOUNT's month:\n * { month, estCostUsd, requests, days: { [YYYY-MM-DD]: { requests,\n * refusals } }, updatedAt }\n * platformAiFreeSpend/{YYYY-MM-DD} the PLATFORM's day of free spend:\n * { day, estCostUsd, requests, refusals, alertedAt?, pausedAt?,\n * updatedAt }\n *\n * The account document sits under `users/{uid}`, whose owner may read and\n * write the user document itself. It may not touch this subcollection: the\n * `users` block matches its subcollections BY NAME and carries no wildcard,\n * so an unmatched name is default-deny for every client, staff included —\n * the same property `assistUsage` relies on one level down. An owner who\n * could write here could reset their own allowance, which is the whole\n * meter. The platform document is a top-level collection alongside\n * `platformCronBeats`, unmatched and therefore closed, and every reader is\n * an Admin-SDK reader behind the staff gate.\n *\n * ## Whose account\n *\n * The WORKSPACE OWNER's. A member invited to someone else's free workspace\n * draws from that workspace's band and from its owner's allowance, never\n * from their own account: the owner is the person the free workspace is\n * attributed to for the ceiling on how many they may hold, and attributing\n * the spend the same way is what keeps the two bounds describing one\n * person. `ownerUid` first, `createdByUid` for an org that predates\n * ownership stamping — the same union the free-workspace count reads.\n */\n\n/** Where an account's month of free AI spend lives, under `users/{uid}`. */\nexport const FREE_AI_ACCOUNT_USAGE_COLLECTION = 'aiUsage'\n\n/** The top-level collection holding one document per UTC day of free spend. */\nexport const PLATFORM_AI_FREE_SPEND_COLLECTION = 'platformAiFreeSpend'\n\n/**\n * Refusals a day before an account's free generation pauses. Three, not\n * one: a single declined brief is a normal outcome of asking an assistant\n * for things, and pausing on it would punish an ordinary afternoon. Three\n * in a day is somebody probing what the model will write.\n */\nexport const AI_FREE_REFUSALS_PER_DAY = 3\n\n/** The share of the platform ceiling at which staff are told, once a day. */\nexport const AI_FREE_PLATFORM_ALERT_SHARE = 0.8\n\n/** The account allowance, in USD of provider spend — the taste, per person. */\nexport const FREE_AI_ACCOUNT_BUDGET_USD = assistUsdFromCredits(\n FREE_AI_TASTE_CREDITS_PER_MONTH,\n)\n\n/**\n * Free requests one account may make a UTC day, across its workspaces\n * (`AI_FREE_DAILY_REQUESTS`, default 30).\n *\n * A request, not a message: this counts every reservation the account's\n * free workspaces take, at either door. Thirty is three times the\n * per-workspace message cap, so one workspace never hits it before its own\n * cap and three workspaces hit it exactly when their caps would have\n * summed — it bounds the multiplier, not the ordinary day. Zero is honored\n * as \"no free requests\", which is a decision an operator may write down;\n * junk and an empty value take the default.\n */\nexport function aiFreeDailyRequests(): number {\n const raw = process.env.AI_FREE_DAILY_REQUESTS\n const parsed = raw ? Number(raw) : Number.NaN\n return Number.isFinite(parsed) && parsed >= 0 ? Math.floor(parsed) : 30\n}\n\n/**\n * The platform-wide ceiling on ONE UTC day of free-tier provider spend\n * (`AI_FREE_DAILY_PLATFORM_CEILING_USD`, default $25).\n *\n * Every other bound here is per something — per workspace, per account,\n * per address — and a wave of new accounts clears all of them one at a\n * time. This is the bound on the sum. At 80% of it staff are mailed; at\n * 100% every free reservation refuses until the day rolls, paid workspaces\n * untouched, and the manual `ai-generate` lockdown key remains the switch\n * for anything the ceiling did not catch.\n *\n * Fails to the DEFAULT, never to \"no ceiling\", for the reason the operator\n * COGS limit does: an empty, negative, zero or unparseable value is not a\n * decision to run unbounded. There is deliberately no `off` word — a\n * deployment that wants no ceiling sets a figure it is content to spend.\n */\nexport function aiFreeDailyPlatformCeilingUsd(): number {\n const raw = String(process.env.AI_FREE_DAILY_PLATFORM_CEILING_USD ?? '').trim()\n const parsed = raw ? Number(raw) : Number.NaN\n return Number.isFinite(parsed) && parsed > 0 ? parsed : 25\n}\n\n/** The account a free workspace's spend is attributed to. */\nexport interface FreeAssistAccount {\n /**\n * The workspace owner's uid, or `null` for an org document that names no\n * owner and no creator — every org created since ownership was stamped\n * names one, so `null` is the shape of a fixture or a very old record.\n * The account rungs are skipped for it; the org's own band still binds.\n */\n accountUid: string | null\n}\n\n/** The org fields the attribution reads, beside the billing ones. */\nexport type AssistMeteredOrg = Partial<AglynOrgBilling> & {\n ownerUid?: string | null\n createdByUid?: string | null\n}\n\n/**\n * The account to meter a workspace's free spend against, or `null` when the\n * workspace is not on the Free plan and none of this applies.\n *\n * `resolveEffectivePlan`, not `org.plan`: a workspace whose subscription\n * died is Free again, and its spend is the taste's spend again.\n */\nexport function freeAssistAccount(\n org: AssistMeteredOrg | null | undefined,\n): FreeAssistAccount | null {\n if (resolveEffectivePlan(org) !== 'free') return null\n const owner = String(org?.ownerUid ?? '').trim()\n const creator = String(org?.createdByUid ?? '').trim()\n return { accountUid: owner || creator || null }\n}\n\nexport function freeAccountUsageRef(\n firestore: FirebaseFirestore.Firestore,\n accountUid: string,\n month: string,\n): FirebaseFirestore.DocumentReference {\n return firestore\n .collection('users')\n .doc(accountUid)\n .collection(FREE_AI_ACCOUNT_USAGE_COLLECTION)\n .doc(month)\n}\n\nexport function platformFreeSpendRef(\n firestore: FirebaseFirestore.Firestore,\n day: string,\n): FirebaseFirestore.DocumentReference {\n return firestore.collection(PLATFORM_AI_FREE_SPEND_COLLECTION).doc(day)\n}\n\n/** What the reservation read about the account and the platform. */\nexport interface FreeTasteReads {\n accountCostUsd: number\n accountRequestsToday: number\n accountRefusalsToday: number\n platformCostUsd: number\n platformPaused: boolean\n}\n\n/** The two snapshots, as the transaction handed them over, into figures. */\nexport function freeTasteReadsFrom(\n account: FirebaseFirestore.DocumentSnapshot | null,\n platform: FirebaseFirestore.DocumentSnapshot | null,\n day: string,\n): FreeTasteReads {\n const days = (account?.get('days') ?? {}) as Record<\n string,\n { requests?: unknown; refusals?: unknown } | undefined\n >\n const today = days[day] ?? {}\n return {\n accountCostUsd: Number(account?.get('estCostUsd') ?? 0),\n accountRequestsToday: Number(today.requests ?? 0),\n accountRefusalsToday: Number(today.refusals ?? 0),\n platformCostUsd: Number(platform?.get('estCostUsd') ?? 0),\n platformPaused: Boolean(platform?.get('pausedAt')),\n }\n}\n\n/**\n * Which of the taste's own precautions refuses, or `null` when none does —\n * pure, so the spec can force every rung red without a Firestore.\n *\n * Checked in the order the reads are cheapest to explain: the daily\n * request cap and the refusal pause (both reset on a clock the customer\n * can be told about), then the account's month (an upgrade is the way\n * out), then the platform ceiling (nobody's doing; try again tomorrow).\n * The org's own rungs — its daily message cap, its band — run before this\n * in the reservation, so a workspace at its own band hears about its own\n * band rather than about its owner's other workspaces.\n *\n * Every comparison is `>=` against a count the reservation is about to\n * increment, so a cap of N admits exactly N. A paused platform refuses\n * regardless of the running figure: the pause is a decision recorded on\n * the document, and a ceiling raised by an operator mid-day does not undo\n * it — the day rolls, or staff clear the document.\n */\nexport function freeTasteRefusal(\n reads: FreeTasteReads,\n limits: {\n dailyRequests?: number\n refusalsPerDay?: number\n accountBudgetUsd?: number\n platformCeilingUsd?: number\n } = {},\n): Extract<AssistRefusedBy, 'requests' | 'refusals' | 'account' | 'platform'> | null {\n const dailyRequests = limits.dailyRequests ?? aiFreeDailyRequests()\n const refusalsPerDay = limits.refusalsPerDay ?? AI_FREE_REFUSALS_PER_DAY\n const accountBudgetUsd = limits.accountBudgetUsd ?? FREE_AI_ACCOUNT_BUDGET_USD\n const platformCeilingUsd =\n limits.platformCeilingUsd ?? aiFreeDailyPlatformCeilingUsd()\n if (reads.accountRequestsToday >= dailyRequests) return 'requests'\n if (reads.accountRefusalsToday >= refusalsPerDay) return 'refusals'\n if (reads.accountCostUsd >= accountBudgetUsd) return 'account'\n if (reads.platformPaused || reads.platformCostUsd >= platformCeilingUsd) {\n return 'platform'\n }\n return null\n}\n\n/**\n * The account-side write one admitted free reservation owes: a request\n * counted for the month and for the day. `set(…, { merge: true })` with\n * nested increments, so the first request of a month conjures the document\n * and a day's map entry appears the first time that day is counted.\n */\nexport function freeAccountReservationWrite(\n month: string,\n day: string,\n): Record<string, unknown> {\n const increment = FieldValue.increment\n return {\n month,\n requests: increment(1),\n days: { [day]: { requests: increment(1) } },\n updatedAt: FieldValue.serverTimestamp(),\n }\n}\n\n/**\n * The two writes one metered free turn owes, beside the org's own rollup.\n *\n * A `refusal` stop is the one case where the meters disagree on purpose. The\n * tokens were spent, so the PLATFORM document — which bounds our money —\n * takes the cost and counts the refusal. The ACCOUNT's credits do not move:\n * a refusal never draws credits, because a customer whose brief was\n * declined has not been given anything, and because a run of declined\n * briefs is answered by the refusal pause rather than by an emptied band.\n * The account's day counts the refusal, which is what the pause reads.\n */\nexport function freeTasteMeterWrites(input: {\n estCostUsd: number\n refused: boolean\n day: string\n month: string\n}): { account: Record<string, unknown>; platform: Record<string, unknown> } {\n const increment = FieldValue.increment\n const serverTimestamp = FieldValue.serverTimestamp\n const { estCostUsd, refused, day, month } = input\n return {\n account: refused\n ? {\n month,\n days: { [day]: { refusals: increment(1) } },\n updatedAt: serverTimestamp(),\n }\n : { month, estCostUsd: increment(estCostUsd), updatedAt: serverTimestamp() },\n platform: {\n day,\n estCostUsd: increment(estCostUsd),\n requests: increment(1),\n refusals: increment(refused ? 1 : 0),\n updatedAt: serverTimestamp(),\n },\n }\n}\n\n/**\n * After a free turn is metered: tell staff at 80% of the day's ceiling,\n * and record the pause at 100% — each ONCE per UTC day, deduplicated on\n * the day document itself inside a transaction, so two turns landing\n * together cannot both cross a threshold and both announce it.\n *\n * The refusal at the ceiling is NOT decided here; `freeTasteRefusal` reads\n * the figure inside every reservation and refuses on it directly. This\n * only says so out loud: the email, and an `adminAudit` row under\n * `platform.aiFreeSpend.paused` so the staff audit trail shows the day the\n * taste switched itself off. Both are best-effort and neither can fail the\n * turn that triggered them — the turn is already paid for.\n *\n * Returns what it announced, for the spec and for the log.\n */\nexport async function announcePlatformFreeSpend(\n firestore: FirebaseFirestore.Firestore,\n day: string,\n): Promise<{ alerted: boolean; paused: boolean; estCostUsd: number }> {\n const ceilingUsd = aiFreeDailyPlatformCeilingUsd()\n const ref = platformFreeSpendRef(firestore, day)\n const crossed = await firestore.runTransaction(async (tx) => {\n const snapshot = await tx.get(ref)\n const estCostUsd = Number(snapshot.get('estCostUsd') ?? 0)\n const alert =\n !snapshot.get('alertedAt') &&\n estCostUsd >= ceilingUsd * AI_FREE_PLATFORM_ALERT_SHARE\n const pause = !snapshot.get('pausedAt') && estCostUsd >= ceilingUsd\n if (alert || pause) {\n tx.set(\n ref,\n {\n ...(alert ? { alertedAt: FieldValue.serverTimestamp() } : {}),\n ...(pause ? { pausedAt: FieldValue.serverTimestamp() } : {}),\n },\n { merge: true },\n )\n }\n return { alerted: alert, paused: pause, estCostUsd }\n })\n if (!crossed.alerted && !crossed.paused) return crossed\n\n const figure = `$${crossed.estCostUsd.toFixed(2)} of the $${ceilingUsd.toFixed(2)} ceiling`\n if (crossed.paused) {\n await firestore\n .collection('adminAudit')\n .add({\n actorUid: 'system:ai-free-spend',\n action: 'platform.aiFreeSpend.paused',\n target: `${PLATFORM_AI_FREE_SPEND_COLLECTION}/${day}`,\n after: { day, estCostUsd: crossed.estCostUsd, ceilingUsd },\n at: FieldValue.serverTimestamp(),\n })\n .catch((error) =>\n console.error('[ai-free-spend] audit row failed', error),\n )\n }\n await sendStaffAlertEmail({\n subject: crossed.paused\n ? `Free AI generation paused for ${day}: ${figure}`\n : `Free AI spend at 80% of today's ceiling (${day}): ${figure}`,\n text: crossed.paused\n ? `Free-tier AI spend for ${day} (UTC) reached ${figure} ` +\n '(AI_FREE_DAILY_PLATFORM_CEILING_USD). Every Free workspace is ' +\n 'refused AI generation until the UTC day rolls; paid workspaces are ' +\n 'unaffected. If this is an abuse wave rather than organic use, the ' +\n '`ai-generate` feature lock on Staff → Lockdown stops generation ' +\n 'for everyone, and the assist signals page shows which workspaces ' +\n 'spent it.'\n : `Free-tier AI spend for ${day} (UTC) is at ${figure} ` +\n '(AI_FREE_DAILY_PLATFORM_CEILING_USD). At 100% every Free ' +\n 'workspace is refused AI generation until the day rolls. The ' +\n 'assist signals page shows the day so far; the `ai-generate` ' +\n 'feature lock on Staff → Lockdown is the manual stop.',\n context: 'ai-free-spend',\n })\n return crossed\n}\n\n/** The staff readout of today's free spend, for the assist signals page. */\nexport interface PlatformFreeSpendReadout {\n day: string\n estCostUsd: number\n requests: number\n refusals: number\n ceilingUsd: number\n /** True once the 80% mail went out today. */\n alerted: boolean\n /** True while free generation is refused for the day. */\n paused: boolean\n}\n\nexport async function readPlatformFreeSpend(\n firestore: FirebaseFirestore.Firestore,\n day: string,\n): Promise<PlatformFreeSpendReadout> {\n const snapshot = await platformFreeSpendRef(firestore, day).get()\n const ceilingUsd = aiFreeDailyPlatformCeilingUsd()\n const estCostUsd = Number(snapshot.get('estCostUsd') ?? 0)\n return {\n day,\n estCostUsd,\n requests: Number(snapshot.get('requests') ?? 0),\n refusals: Number(snapshot.get('refusals') ?? 0),\n ceilingUsd,\n alerted: Boolean(snapshot.get('alertedAt')),\n // The pause is the recorded decision OR the live figure: a day that\n // crossed the ceiling before anything announced it is paused all the\n // same, because the reservation refuses on the figure.\n paused: Boolean(snapshot.get('pausedAt')) || estCostUsd >= ceilingUsd,\n }\n}\n"],"names":["FieldValue","assistUsdFromCredits","FREE_AI_TASTE_CREDITS_PER_MONTH","resolveEffectivePlan","sendStaffAlertEmail","FREE_AI_ACCOUNT_USAGE_COLLECTION","PLATFORM_AI_FREE_SPEND_COLLECTION","AI_FREE_REFUSALS_PER_DAY","AI_FREE_PLATFORM_ALERT_SHARE","FREE_AI_ACCOUNT_BUDGET_USD","aiFreeDailyRequests","raw","process","env","AI_FREE_DAILY_REQUESTS","parsed","Number","NaN","isFinite","Math","floor","aiFreeDailyPlatformCeilingUsd","String","AI_FREE_DAILY_PLATFORM_CEILING_USD","trim","freeAssistAccount","org","owner","ownerUid","creator","createdByUid","accountUid","freeAccountUsageRef","firestore","month","collection","doc","platformFreeSpendRef","day","freeTasteReadsFrom","account","platform","days","today","get","accountCostUsd","accountRequestsToday","requests","accountRefusalsToday","refusals","platformCostUsd","platformPaused","Boolean","freeTasteRefusal","reads","limits","dailyRequests","refusalsPerDay","accountBudgetUsd","platformCeilingUsd","freeAccountReservationWrite","increment","updatedAt","serverTimestamp","freeTasteMeterWrites","input","estCostUsd","refused","announcePlatformFreeSpend","ceilingUsd","ref","crossed","runTransaction","tx","snapshot","alert","pause","set","alertedAt","pausedAt","merge","alerted","paused","figure","toFixed","add","actorUid","action","target","after","at","catch","error","console","subject","text","context","readPlatformFreeSpend"],"mappings":"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"}
@@ -0,0 +1,69 @@
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
+ import type { AiRefusedBy } from '../model/ai-allotments';
18
+ /**
19
+ * THE PER-ORG REFUSAL COUNTER (AGL-2930).
20
+ *
21
+ * `reserveAssistMessage` refuses for four reasons and, until now, recorded
22
+ * none of them: a refusal moved no counter by design, so the month document
23
+ * could say how much an org spent and nothing about how often it was turned
24
+ * away. Staff monitoring needs the second figure — a workspace refused at its
25
+ * band forty times this month is a sales conversation, and one refused at the
26
+ * operator's backstop is an incident — and neither is derivable from spend.
27
+ *
28
+ * The count lives on the SAME document the spend does, as a map:
29
+ *
30
+ * orgs/{orgId}/assistUsage/{YYYY-MM}.refusals.{reason}
31
+ *
32
+ * with `reason` one of the four `AssistRefusedBy` values. A map rather than
33
+ * four top-level fields so a reader can take the whole thing in one `get`,
34
+ * and so a fifth reason lands without a schema change.
35
+ *
36
+ * ## Fire-and-forget, and never throws
37
+ *
38
+ * The write is deliberately OUTSIDE the reservation transaction and off its
39
+ * await path. A refusal is the cheap, no-token exit of the gate, and a
40
+ * counter that could fail the refusal — or slow it, or retry the transaction
41
+ * it was called from — would make the observation more expensive than the
42
+ * thing observed. So this returns synchronously, swallows every error
43
+ * including a double that has no `set`, and the only cost of a lost increment
44
+ * is an undercount on a staff card.
45
+ */
46
+ /** A reason that actually refused — the `null` (admitted) case has no count. */
47
+ export type AssistRefusalReason = NonNullable<AiRefusedBy>;
48
+ /**
49
+ * Every reason, in the order the card and the leaderboard list them: the
50
+ * workspace's own four first, then an allotment a manager set (AGL-2942),
51
+ * then the Free taste's (AGL-2925), which only a Free workspace can be
52
+ * refused by.
53
+ */
54
+ export declare const ASSIST_REFUSAL_REASONS: readonly AssistRefusalReason[];
55
+ export declare function recordAssistRefusal(firestore: FirebaseFirestore.Firestore, orgId: string, month: string, reason: AssistRefusalReason): void;
56
+ /** Every reason's count, zero-filled, as the card and the leaderboard read them. */
57
+ export type AssistRefusalCounts = Record<AssistRefusalReason, number> & {
58
+ total: number;
59
+ };
60
+ /**
61
+ * The `refusals` map off a month document as a complete, zero-filled record.
62
+ *
63
+ * Zero-filled rather than sparse because the readers render every reason:
64
+ * "band 0" beside "cap 12" is the finding, and a sparse map would make the
65
+ * reader guess whether an absent key meant none or not yet counted. A
66
+ * non-numeric or negative value reads as 0 — the counter is only ever
67
+ * incremented, so anything else is a hand edit.
68
+ */
69
+ export declare function assistRefusalCounts(raw: unknown): AssistRefusalCounts;