@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,239 @@
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
+ */ // Straight from the SDK, not the admin lib, for the reason `assist-usage.ts`
18
+ // gives at its head: the statics need no app, and the reservation that reads
19
+ // allotments runs in every unit test that touches a counter.
20
+ import { FieldValue } from "firebase-admin/firestore";
21
+ import { AI_ALLOTMENTS_COLLECTION, AI_ALLOTMENT_ORG_SUBJECT, aiAllotmentFrom, aiAllotmentModelsAllowed, aiAllotmentSubjectId, aiAllotmentVerdict } from "../model/ai-allotments.js";
22
+ import { aiUsageByUserMonthFrom } from "../model/ai-usage-by-user.js";
23
+ import { userAiUsageMonthRef } from "./ai-usage-by-user.js";
24
+ /**
25
+ * AI ALLOTMENTS (AGL-2942): the reads the gate takes and the writes the
26
+ * route makes. The shape and the arithmetic are `model/ai-allotments.ts`.
27
+ *
28
+ * ## What the gate reads, and where the figures come from
29
+ *
30
+ * One request by `uid`, naming `hostId` or not, is measured against every
31
+ * allotment that applies to it:
32
+ *
33
+ * member:{uid} the person's credits this month, every site —
34
+ * `aiUsageByUser/{uid}/months/{month}.credits`
35
+ * collab:{hostId}:{uid} the person's credits on that site —
36
+ * the same document's `byHost.{hostId}`
37
+ * host:{hostId} the SITE's credits, everyone on it — the org
38
+ * rollup's `assistUsage/{month}.byHost.{hostId}`
39
+ * org no credits: the model restriction
40
+ *
41
+ * The per-person figures are the AGL-2928 rollup. The site figure is a map
42
+ * the meter writes on the org's month in the same batch, because summing the
43
+ * roster's months on every request would be one read per collaborator.
44
+ *
45
+ * Read inside the reservation's transaction, after the workspace's own
46
+ * ceilings admitted the request, so a refusal at the band costs no allotment
47
+ * read at all and an allotment is only ever consulted inside the band.
48
+ *
49
+ * ## Written only here, never by a client
50
+ *
51
+ * The rules deny every client write: an allotment is a spend control, and a
52
+ * collaborator who could write their own could lift it.
53
+ */ /** The org month map a site's credits accumulate in. */ export const AI_HOST_CREDITS_FIELD = 'byHost';
54
+ export function aiAllotmentsCollection(orgRef) {
55
+ return orgRef.collection(AI_ALLOTMENTS_COLLECTION);
56
+ }
57
+ export function aiAllotmentRef(orgRef, subject) {
58
+ return aiAllotmentsCollection(orgRef).doc(subject);
59
+ }
60
+ const trimmed = (value)=>typeof value === 'string' ? value.trim() : '';
61
+ /** An allotment read by the subject the reader ADDRESSED, not the one it echoes. */ const allotmentOf = (snapshot, subject)=>(snapshot == null ? void 0 : snapshot.exists) && subject ? aiAllotmentFrom(snapshot.data(), subject) : null;
62
+ /**
63
+ * A subject id, or `null` when a segment is not an id. A request's site comes
64
+ * from its body, and a value that could never name a site names no
65
+ * allotment rather than failing the reservation it rides in.
66
+ */ function subjectIdOrNull(input) {
67
+ try {
68
+ return aiAllotmentSubjectId(input);
69
+ } catch (unused) {
70
+ return null;
71
+ }
72
+ }
73
+ /** A site's credits this month off the org rollup's month document. */ export function aiHostMonthCredits(orgMonth, hostId) {
74
+ var _ref;
75
+ const map = (orgMonth == null ? void 0 : orgMonth.exists) ? orgMonth.get(AI_HOST_CREDITS_FIELD) : null;
76
+ const value = Number((_ref = map == null ? void 0 : map[hostId]) != null ? _ref : 0);
77
+ return Number.isFinite(value) && value > 0 ? Math.floor(value) : 0;
78
+ }
79
+ /**
80
+ * Read and measure the allotments that apply to one request. `null` when
81
+ * the request names nobody — a meter that cannot say who asked meets no
82
+ * allotment, as it attributes to nobody.
83
+ *
84
+ * `orgMonth` is the org's month document when the caller already read it —
85
+ * the reservation reads it for an entitled workspace anyway — so a site
86
+ * allotment costs no second read of it.
87
+ */ export async function readAiAllotmentGate(read, orgRef, subject, month, orgMonth = null) {
88
+ var _personal_byHost_hostId, _ref;
89
+ var _allotmentOf;
90
+ const uid = trimmed(subject.uid);
91
+ const memberId = uid ? subjectIdOrNull({
92
+ scope: 'member',
93
+ uid
94
+ }) : null;
95
+ if (!uid || !memberId) return null;
96
+ const requestedHost = trimmed(subject.hostId);
97
+ const hostSubjectId = requestedHost ? subjectIdOrNull({
98
+ scope: 'host',
99
+ hostId: requestedHost
100
+ }) : null;
101
+ const hostId = hostSubjectId ? requestedHost : '';
102
+ const collabId = hostId ? subjectIdOrNull({
103
+ scope: 'collab',
104
+ hostId,
105
+ uid
106
+ }) : null;
107
+ const subjectRef = (id)=>aiAllotmentRef(orgRef, id);
108
+ const [orgDoc, memberDoc, collabDoc, hostDoc, monthDoc] = await Promise.all([
109
+ read(subjectRef(AI_ALLOTMENT_ORG_SUBJECT)),
110
+ read(subjectRef(memberId)),
111
+ collabId ? read(subjectRef(collabId)) : null,
112
+ hostSubjectId ? read(subjectRef(hostSubjectId)) : null,
113
+ read(userAiUsageMonthRef(orgRef, uid, month))
114
+ ]);
115
+ const member = allotmentOf(memberDoc, memberId);
116
+ const collab = allotmentOf(collabDoc, collabId);
117
+ const host = allotmentOf(hostDoc, hostSubjectId);
118
+ const personal = aiUsageByUserMonthFrom((monthDoc == null ? void 0 : monthDoc.exists) ? monthDoc.data() : null, uid, month);
119
+ let siteMonth = orgMonth;
120
+ if ((host == null ? void 0 : host.credits) && !siteMonth) {
121
+ siteMonth = await read(orgRef.collection('assistUsage').doc(month));
122
+ }
123
+ const standings = [];
124
+ const measure = (allotment, used)=>{
125
+ if (!allotment || allotment.credits === null || allotment.scope === 'org') return;
126
+ standings.push({
127
+ subject: allotment.subject,
128
+ scope: allotment.scope,
129
+ uid: allotment.uid,
130
+ hostId: allotment.hostId,
131
+ credits: allotment.credits,
132
+ used,
133
+ mode: allotment.mode
134
+ });
135
+ };
136
+ measure(member, personal.credits);
137
+ measure(collab, hostId ? (_personal_byHost_hostId = personal.byHost[hostId]) != null ? _personal_byHost_hostId : 0 : 0);
138
+ measure(host, hostId ? aiHostMonthCredits(siteMonth, hostId) : 0);
139
+ return _extends({}, aiAllotmentVerdict(standings), {
140
+ personalCredits: personal.credits,
141
+ standings,
142
+ models: aiAllotmentModelsAllowed([
143
+ member,
144
+ collab,
145
+ host
146
+ ]),
147
+ orgModels: (_ref = (_allotmentOf = allotmentOf(orgDoc, AI_ALLOTMENT_ORG_SUBJECT)) == null ? void 0 : _allotmentOf.models) != null ? _ref : null
148
+ });
149
+ }
150
+ /** Every allotment in an org, optionally narrowed to one person or one site. */ export async function listAiAllotments(firestore, orgId, filter = {}) {
151
+ let query = aiAllotmentsCollection(firestore.collection('orgs').doc(orgId));
152
+ // Single-field equality on fields every write stores, so neither needs a
153
+ // composite index.
154
+ if (filter.uid) query = query.where('uid', '==', filter.uid);
155
+ else if (filter.hostId) query = query.where('hostId', '==', filter.hostId);
156
+ const snapshot = await query.get();
157
+ return snapshot.docs.map((doc)=>aiAllotmentFrom(doc.data(), doc.id)).filter((allotment)=>allotment !== null);
158
+ }
159
+ /**
160
+ * Set and remove allotments in one batch. A set REPLACES the document —
161
+ * credits, mode and allowlist together — and clears the alert marker, so a
162
+ * raised allotment announces its next crossing rather than inheriting the
163
+ * last one's.
164
+ */ export async function applyAiAllotmentWrites(firestore, orgId, change, actorUid) {
165
+ const orgRef = firestore.collection('orgs').doc(orgId);
166
+ const batch = firestore.batch();
167
+ for (const write of change.set){
168
+ batch.set(aiAllotmentRef(orgRef, write.subject.id), {
169
+ subject: write.subject.id,
170
+ scope: write.subject.scope,
171
+ uid: write.subject.uid,
172
+ hostId: write.subject.hostId,
173
+ credits: write.subject.scope === 'org' ? null : write.credits,
174
+ mode: write.mode,
175
+ models: write.models,
176
+ setBy: actorUid,
177
+ updatedAt: FieldValue.serverTimestamp(),
178
+ alerted: null
179
+ });
180
+ }
181
+ for (const subject of change.remove){
182
+ batch.delete(aiAllotmentRef(orgRef, subject));
183
+ }
184
+ await batch.commit();
185
+ }
186
+ /**
187
+ * Give a site's month its credits so far, once, when an allotment on the site
188
+ * is set before the site's map has a key for it.
189
+ *
190
+ * The map is written by the meter from the day the field shipped; a month
191
+ * already in progress has spend the map never saw. The roster's own months
192
+ * carry the same figure per person (`byHost`), so the first allotment set on
193
+ * a site sums them and writes the total — inside a transaction that writes
194
+ * nothing when the key is already there, so a request metered in between is
195
+ * counted once, by the meter.
196
+ */ export async function seedAiHostMonthCredits(firestore, orgId, hostIds, month, personCredits) {
197
+ if (!hostIds.length) return;
198
+ const monthRef = firestore.collection('orgs').doc(orgId).collection('assistUsage').doc(month);
199
+ await firestore.runTransaction(async (tx)=>{
200
+ const snapshot = await tx.get(monthRef);
201
+ const map = snapshot.exists ? snapshot.get(AI_HOST_CREDITS_FIELD) : null;
202
+ const missing = hostIds.filter((hostId)=>(map == null ? void 0 : map[hostId]) === undefined);
203
+ if (!missing.length) return;
204
+ tx.set(monthRef, {
205
+ month,
206
+ [AI_HOST_CREDITS_FIELD]: Object.fromEntries(missing.map((hostId)=>[
207
+ hostId,
208
+ personCredits(hostId)
209
+ ]))
210
+ }, {
211
+ merge: true
212
+ });
213
+ });
214
+ }
215
+ /**
216
+ * Remove a person's allotments on account erasure: `member:{uid}` and every
217
+ * `collab:{hostId}:{uid}`, in each org the erasure names. By path and by a
218
+ * collection-scope equality, so neither needs an index; an org the person
219
+ * had already left keeps a configuration document that names a uid and
220
+ * nothing else, which the next write to that subject replaces.
221
+ */ export async function eraseAiAllotmentsForUser(firestore, uid, orgIds) {
222
+ let removed = 0;
223
+ for (const orgId of orgIds){
224
+ const allotments = await listAiAllotments(firestore, orgId, {
225
+ uid
226
+ });
227
+ if (!allotments.length) continue;
228
+ const orgRef = firestore.collection('orgs').doc(orgId);
229
+ const batch = firestore.batch();
230
+ for (const allotment of allotments){
231
+ batch.delete(aiAllotmentRef(orgRef, allotment.subject));
232
+ removed += 1;
233
+ }
234
+ await batch.commit();
235
+ }
236
+ return removed;
237
+ }
238
+
239
+ //# sourceMappingURL=ai-allotments.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/usage/ai-allotments.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// Straight from the SDK, not the admin lib, for the reason `assist-usage.ts`\n// gives at its head: the statics need no app, and the reservation that reads\n// allotments runs in every unit test that touches a counter.\nimport { FieldValue } from 'firebase-admin/firestore'\nimport {\n AI_ALLOTMENTS_COLLECTION,\n AI_ALLOTMENT_ORG_SUBJECT,\n aiAllotmentFrom,\n aiAllotmentModelsAllowed,\n aiAllotmentSubjectId,\n aiAllotmentVerdict,\n type AiAllotment,\n type AiAllotmentMode,\n type AiAllotmentStanding,\n type AiAllotmentSubject,\n type AiAllotmentVerdict,\n} from '../model/ai-allotments'\nimport { aiUsageByUserMonthFrom } from '../model/ai-usage-by-user'\nimport { userAiUsageMonthRef } from './ai-usage-by-user'\n\n/**\n * AI ALLOTMENTS (AGL-2942): the reads the gate takes and the writes the\n * route makes. The shape and the arithmetic are `model/ai-allotments.ts`.\n *\n * ## What the gate reads, and where the figures come from\n *\n * One request by `uid`, naming `hostId` or not, is measured against every\n * allotment that applies to it:\n *\n * member:{uid} the person's credits this month, every site —\n * `aiUsageByUser/{uid}/months/{month}.credits`\n * collab:{hostId}:{uid} the person's credits on that site —\n * the same document's `byHost.{hostId}`\n * host:{hostId} the SITE's credits, everyone on it — the org\n * rollup's `assistUsage/{month}.byHost.{hostId}`\n * org no credits: the model restriction\n *\n * The per-person figures are the AGL-2928 rollup. The site figure is a map\n * the meter writes on the org's month in the same batch, because summing the\n * roster's months on every request would be one read per collaborator.\n *\n * Read inside the reservation's transaction, after the workspace's own\n * ceilings admitted the request, so a refusal at the band costs no allotment\n * read at all and an allotment is only ever consulted inside the band.\n *\n * ## Written only here, never by a client\n *\n * The rules deny every client write: an allotment is a spend control, and a\n * collaborator who could write their own could lift it.\n */\n\n/** The org month map a site's credits accumulate in. */\nexport const AI_HOST_CREDITS_FIELD = 'byHost'\n\nexport function aiAllotmentsCollection(\n orgRef: FirebaseFirestore.DocumentReference,\n): FirebaseFirestore.CollectionReference {\n return orgRef.collection(AI_ALLOTMENTS_COLLECTION)\n}\n\nexport function aiAllotmentRef(\n orgRef: FirebaseFirestore.DocumentReference,\n subject: string,\n): FirebaseFirestore.DocumentReference {\n return aiAllotmentsCollection(orgRef).doc(subject)\n}\n\n/** Who a request is, for the allotments that apply to it. */\nexport interface AiAllotmentRequestSubject {\n /** The person asking; a request with none is measured against no allotment. */\n uid?: string | null\n /** The site the request named, when it named one. */\n hostId?: string | null\n}\n\n/** Everything the reservation learned about allotments, carried to the door. */\nexport interface AiAllotmentGate extends AiAllotmentVerdict {\n /** The caller's own credits this month, before this request. */\n personalCredits: number\n /** Every allotment of credits that applied, measured. */\n standings: AiAllotmentStanding[]\n /** The allotment allowlists that applied, intersected; `null` for none. */\n models: string[] | null\n /** The org-wide model restriction; `null` for none. */\n orgModels: string[] | null\n}\n\n/** A document read, from a transaction or a plain Firestore. */\nexport type AiAllotmentDocReader = (\n ref: FirebaseFirestore.DocumentReference,\n) => Promise<FirebaseFirestore.DocumentSnapshot>\n\nconst trimmed = (value: unknown): string =>\n typeof value === 'string' ? value.trim() : ''\n\n/** An allotment read by the subject the reader ADDRESSED, not the one it echoes. */\nconst allotmentOf = (\n snapshot: FirebaseFirestore.DocumentSnapshot | null | undefined,\n subject: string | null,\n): AiAllotment | null =>\n snapshot?.exists && subject\n ? aiAllotmentFrom(snapshot.data() as Record<string, unknown>, subject)\n : null\n\n/**\n * A subject id, or `null` when a segment is not an id. A request's site comes\n * from its body, and a value that could never name a site names no\n * allotment rather than failing the reservation it rides in.\n */\nfunction subjectIdOrNull(input: Parameters<typeof aiAllotmentSubjectId>[0]): string | null {\n try {\n return aiAllotmentSubjectId(input)\n } catch {\n return null\n }\n}\n\n/** A site's credits this month off the org rollup's month document. */\nexport function aiHostMonthCredits(\n orgMonth: FirebaseFirestore.DocumentSnapshot | null | undefined,\n hostId: string,\n): number {\n const map = (orgMonth?.exists ? orgMonth.get(AI_HOST_CREDITS_FIELD) : null) as\n | Record<string, unknown>\n | null\n | undefined\n const value = Number(map?.[hostId] ?? 0)\n return Number.isFinite(value) && value > 0 ? Math.floor(value) : 0\n}\n\n/**\n * Read and measure the allotments that apply to one request. `null` when\n * the request names nobody — a meter that cannot say who asked meets no\n * allotment, as it attributes to nobody.\n *\n * `orgMonth` is the org's month document when the caller already read it —\n * the reservation reads it for an entitled workspace anyway — so a site\n * allotment costs no second read of it.\n */\nexport async function readAiAllotmentGate(\n read: AiAllotmentDocReader,\n orgRef: FirebaseFirestore.DocumentReference,\n subject: AiAllotmentRequestSubject,\n month: string,\n orgMonth: FirebaseFirestore.DocumentSnapshot | null = null,\n): Promise<AiAllotmentGate | null> {\n const uid = trimmed(subject.uid)\n const memberId = uid ? subjectIdOrNull({ scope: 'member', uid }) : null\n if (!uid || !memberId) return null\n const requestedHost = trimmed(subject.hostId)\n const hostSubjectId = requestedHost\n ? subjectIdOrNull({ scope: 'host', hostId: requestedHost })\n : null\n const hostId = hostSubjectId ? requestedHost : ''\n const collabId = hostId ? subjectIdOrNull({ scope: 'collab', hostId, uid }) : null\n const subjectRef = (id: string) => aiAllotmentRef(orgRef, id)\n const [orgDoc, memberDoc, collabDoc, hostDoc, monthDoc] = await Promise.all([\n read(subjectRef(AI_ALLOTMENT_ORG_SUBJECT)),\n read(subjectRef(memberId)),\n collabId ? read(subjectRef(collabId)) : null,\n hostSubjectId ? read(subjectRef(hostSubjectId)) : null,\n read(userAiUsageMonthRef(orgRef, uid, month)),\n ])\n const member = allotmentOf(memberDoc, memberId)\n const collab = allotmentOf(collabDoc, collabId)\n const host = allotmentOf(hostDoc, hostSubjectId)\n const personal = aiUsageByUserMonthFrom(\n monthDoc?.exists ? (monthDoc.data() as Record<string, unknown>) : null,\n uid,\n month,\n )\n\n let siteMonth = orgMonth\n if (host?.credits && !siteMonth) {\n siteMonth = await read(orgRef.collection('assistUsage').doc(month))\n }\n\n const standings: AiAllotmentStanding[] = []\n const measure = (allotment: AiAllotment | null, used: number) => {\n if (!allotment || allotment.credits === null || allotment.scope === 'org') return\n standings.push({\n subject: allotment.subject,\n scope: allotment.scope,\n uid: allotment.uid,\n hostId: allotment.hostId,\n credits: allotment.credits,\n used,\n mode: allotment.mode,\n })\n }\n measure(member, personal.credits)\n measure(collab, hostId ? (personal.byHost[hostId] ?? 0) : 0)\n measure(host, hostId ? aiHostMonthCredits(siteMonth, hostId) : 0)\n\n return {\n ...aiAllotmentVerdict(standings),\n personalCredits: personal.credits,\n standings,\n models: aiAllotmentModelsAllowed([member, collab, host]),\n orgModels: allotmentOf(orgDoc, AI_ALLOTMENT_ORG_SUBJECT)?.models ?? null,\n }\n}\n\n/** Every allotment in an org, optionally narrowed to one person or one site. */\nexport async function listAiAllotments(\n firestore: FirebaseFirestore.Firestore,\n orgId: string,\n filter: { uid?: string; hostId?: string } = {},\n): Promise<AiAllotment[]> {\n let query: FirebaseFirestore.Query = aiAllotmentsCollection(\n firestore.collection('orgs').doc(orgId),\n )\n // Single-field equality on fields every write stores, so neither needs a\n // composite index.\n if (filter.uid) query = query.where('uid', '==', filter.uid)\n else if (filter.hostId) query = query.where('hostId', '==', filter.hostId)\n const snapshot = await query.get()\n return snapshot.docs\n .map((doc) => aiAllotmentFrom(doc.data() as Record<string, unknown>, doc.id))\n .filter((allotment): allotment is AiAllotment => allotment !== null)\n}\n\n/** One allotment a write sets. */\nexport interface AiAllotmentWrite {\n subject: AiAllotmentSubject\n credits: number | null\n mode: AiAllotmentMode\n models: string[] | null\n}\n\n/**\n * Set and remove allotments in one batch. A set REPLACES the document —\n * credits, mode and allowlist together — and clears the alert marker, so a\n * raised allotment announces its next crossing rather than inheriting the\n * last one's.\n */\nexport async function applyAiAllotmentWrites(\n firestore: FirebaseFirestore.Firestore,\n orgId: string,\n change: { set: readonly AiAllotmentWrite[]; remove: readonly string[] },\n actorUid: string,\n): Promise<void> {\n const orgRef = firestore.collection('orgs').doc(orgId)\n const batch = firestore.batch()\n for (const write of change.set) {\n batch.set(aiAllotmentRef(orgRef, write.subject.id), {\n subject: write.subject.id,\n scope: write.subject.scope,\n uid: write.subject.uid,\n hostId: write.subject.hostId,\n credits: write.subject.scope === 'org' ? null : write.credits,\n mode: write.mode,\n models: write.models,\n setBy: actorUid,\n updatedAt: FieldValue.serverTimestamp(),\n alerted: null,\n })\n }\n for (const subject of change.remove) {\n batch.delete(aiAllotmentRef(orgRef, subject))\n }\n await batch.commit()\n}\n\n/**\n * Give a site's month its credits so far, once, when an allotment on the site\n * is set before the site's map has a key for it.\n *\n * The map is written by the meter from the day the field shipped; a month\n * already in progress has spend the map never saw. The roster's own months\n * carry the same figure per person (`byHost`), so the first allotment set on\n * a site sums them and writes the total — inside a transaction that writes\n * nothing when the key is already there, so a request metered in between is\n * counted once, by the meter.\n */\nexport async function seedAiHostMonthCredits(\n firestore: FirebaseFirestore.Firestore,\n orgId: string,\n hostIds: readonly string[],\n month: string,\n personCredits: (hostId: string) => number,\n): Promise<void> {\n if (!hostIds.length) return\n const monthRef = firestore\n .collection('orgs')\n .doc(orgId)\n .collection('assistUsage')\n .doc(month)\n await firestore.runTransaction(async (tx) => {\n const snapshot = await tx.get(monthRef)\n const map = (snapshot.exists ? snapshot.get(AI_HOST_CREDITS_FIELD) : null) as\n | Record<string, unknown>\n | null\n const missing = hostIds.filter((hostId) => map?.[hostId] === undefined)\n if (!missing.length) return\n tx.set(\n monthRef,\n {\n month,\n [AI_HOST_CREDITS_FIELD]: Object.fromEntries(\n missing.map((hostId) => [hostId, personCredits(hostId)]),\n ),\n },\n { merge: true },\n )\n })\n}\n\n/**\n * Remove a person's allotments on account erasure: `member:{uid}` and every\n * `collab:{hostId}:{uid}`, in each org the erasure names. By path and by a\n * collection-scope equality, so neither needs an index; an org the person\n * had already left keeps a configuration document that names a uid and\n * nothing else, which the next write to that subject replaces.\n */\nexport async function eraseAiAllotmentsForUser(\n firestore: FirebaseFirestore.Firestore,\n uid: string,\n orgIds: readonly string[],\n): Promise<number> {\n let removed = 0\n for (const orgId of orgIds) {\n const allotments = await listAiAllotments(firestore, orgId, { uid })\n if (!allotments.length) continue\n const orgRef = firestore.collection('orgs').doc(orgId)\n const batch = firestore.batch()\n for (const allotment of allotments) {\n batch.delete(aiAllotmentRef(orgRef, allotment.subject))\n removed += 1\n }\n await batch.commit()\n }\n return removed\n}\n"],"names":["FieldValue","AI_ALLOTMENTS_COLLECTION","AI_ALLOTMENT_ORG_SUBJECT","aiAllotmentFrom","aiAllotmentModelsAllowed","aiAllotmentSubjectId","aiAllotmentVerdict","aiUsageByUserMonthFrom","userAiUsageMonthRef","AI_HOST_CREDITS_FIELD","aiAllotmentsCollection","orgRef","collection","aiAllotmentRef","subject","doc","trimmed","value","trim","allotmentOf","snapshot","exists","data","subjectIdOrNull","input","aiHostMonthCredits","orgMonth","hostId","map","get","Number","isFinite","Math","floor","readAiAllotmentGate","read","month","personal","uid","memberId","scope","requestedHost","hostSubjectId","collabId","subjectRef","id","orgDoc","memberDoc","collabDoc","hostDoc","monthDoc","Promise","all","member","collab","host","siteMonth","credits","standings","measure","allotment","used","push","mode","byHost","personalCredits","models","orgModels","listAiAllotments","firestore","orgId","filter","query","where","docs","applyAiAllotmentWrites","change","actorUid","batch","write","set","setBy","updatedAt","serverTimestamp","alerted","remove","delete","commit","seedAiHostMonthCredits","hostIds","personCredits","length","monthRef","runTransaction","tx","missing","undefined","Object","fromEntries","merge","eraseAiAllotmentsForUser","orgIds","removed","allotments"],"mappings":"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"}
@@ -0,0 +1,36 @@
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 AiStepKind } from '../providers/catalog';
18
+ import type { AiUsage } from '../providers/contract';
19
+ /**
20
+ * The workspace's own typical exchange per step kind (AGL-2942), for the
21
+ * price beside each option in the model switch.
22
+ *
23
+ * Read from `orgs/{orgId}/assistSignals` — the derived half of every metered
24
+ * turn, which carries its route, its model and its tokens and no prose and no
25
+ * uid — newest first, bounded, and only when the switch is opened. A signal
26
+ * is matched to a step kind by the route it was metered under, docs answers
27
+ * and cache hits are left out because no model ran, and the median needs
28
+ * `AI_MEASURED_MEDIAN_MIN_SAMPLES` exchanges before it replaces the nominal
29
+ * figure.
30
+ */
31
+ /** Signals one read considers. */
32
+ export declare const AI_MODEL_SAMPLE_SIGNALS = 60;
33
+ /** Whether a signal's route is the door a step kind is served through. */
34
+ export declare function signalRouteMatchesStep(route: string, kind: AiStepKind): boolean;
35
+ /** The measured median exchange for a step kind, or `null` too few. */
36
+ export declare function readMeasuredStepUsage(firestore: FirebaseFirestore.Firestore, orgId: string, kind: AiStepKind): Promise<AiUsage | null>;
@@ -0,0 +1,68 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */ import { AI_METER_SENTINELS } from "../providers/catalog.js";
17
+ import { aiMedianUsage } from "../providers/model-choice.js";
18
+ /**
19
+ * The workspace's own typical exchange per step kind (AGL-2942), for the
20
+ * price beside each option in the model switch.
21
+ *
22
+ * Read from `orgs/{orgId}/assistSignals` — the derived half of every metered
23
+ * turn, which carries its route, its model and its tokens and no prose and no
24
+ * uid — newest first, bounded, and only when the switch is opened. A signal
25
+ * is matched to a step kind by the route it was metered under, docs answers
26
+ * and cache hits are left out because no model ran, and the median needs
27
+ * `AI_MEASURED_MEDIAN_MIN_SAMPLES` exchanges before it replaces the nominal
28
+ * figure.
29
+ */ /** Signals one read considers. */ export const AI_MODEL_SAMPLE_SIGNALS = 60;
30
+ const COPY_ROUTE = '/api/ai/assist/';
31
+ const JOBS_ROUTE = 'ai/jobs';
32
+ /** Whether a signal's route is the door a step kind is served through. */ export function signalRouteMatchesStep(route, kind) {
33
+ switch(kind){
34
+ case 'copy.element':
35
+ return route === `${COPY_ROUTE}element`;
36
+ case 'copy.blog':
37
+ return route === `${COPY_ROUTE}blog`;
38
+ case 'copy.section':
39
+ case 'generate.section':
40
+ return route === `${COPY_ROUTE}section`;
41
+ case 'job.text':
42
+ return route === JOBS_ROUTE;
43
+ default:
44
+ // A chat turn is metered under the console route it was asked from.
45
+ return !route.startsWith(COPY_ROUTE) && route !== JOBS_ROUTE;
46
+ }
47
+ }
48
+ const SENTINELS = new Set(Object.values(AI_METER_SENTINELS));
49
+ /** The measured median exchange for a step kind, or `null` too few. */ export async function readMeasuredStepUsage(firestore, orgId, kind) {
50
+ const snapshot = await firestore.collection('orgs').doc(orgId).collection('assistSignals').orderBy('createdAt', 'desc').limit(AI_MODEL_SAMPLE_SIGNALS).get();
51
+ const samples = [];
52
+ for (const doc of snapshot.docs){
53
+ var _data_model, _data_route, _data_inputTokens, _data_outputTokens, _data_cacheReadTokens, _data_cacheWriteTokens;
54
+ const data = doc.data();
55
+ if (data['deflected'] === true) continue;
56
+ if (SENTINELS.has(String((_data_model = data['model']) != null ? _data_model : ''))) continue;
57
+ if (!signalRouteMatchesStep(String((_data_route = data['route']) != null ? _data_route : ''), kind)) continue;
58
+ samples.push({
59
+ inputTokens: Number((_data_inputTokens = data['inputTokens']) != null ? _data_inputTokens : 0),
60
+ outputTokens: Number((_data_outputTokens = data['outputTokens']) != null ? _data_outputTokens : 0),
61
+ cacheReadTokens: Number((_data_cacheReadTokens = data['cacheReadTokens']) != null ? _data_cacheReadTokens : 0),
62
+ cacheWriteTokens: Number((_data_cacheWriteTokens = data['cacheWriteTokens']) != null ? _data_cacheWriteTokens : 0)
63
+ });
64
+ }
65
+ return aiMedianUsage(samples);
66
+ }
67
+
68
+ //# sourceMappingURL=ai-model-sample.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/usage/ai-model-sample.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 { AI_METER_SENTINELS, type AiStepKind } from '../providers/catalog'\nimport type { AiUsage } from '../providers/contract'\nimport { aiMedianUsage } from '../providers/model-choice'\n\n/**\n * The workspace's own typical exchange per step kind (AGL-2942), for the\n * price beside each option in the model switch.\n *\n * Read from `orgs/{orgId}/assistSignals` — the derived half of every metered\n * turn, which carries its route, its model and its tokens and no prose and no\n * uid — newest first, bounded, and only when the switch is opened. A signal\n * is matched to a step kind by the route it was metered under, docs answers\n * and cache hits are left out because no model ran, and the median needs\n * `AI_MEASURED_MEDIAN_MIN_SAMPLES` exchanges before it replaces the nominal\n * figure.\n */\n\n/** Signals one read considers. */\nexport const AI_MODEL_SAMPLE_SIGNALS = 60\n\nconst COPY_ROUTE = '/api/ai/assist/'\nconst JOBS_ROUTE = 'ai/jobs'\n\n/** Whether a signal's route is the door a step kind is served through. */\nexport function signalRouteMatchesStep(route: string, kind: AiStepKind): boolean {\n switch (kind) {\n case 'copy.element':\n return route === `${COPY_ROUTE}element`\n case 'copy.blog':\n return route === `${COPY_ROUTE}blog`\n case 'copy.section':\n case 'generate.section':\n return route === `${COPY_ROUTE}section`\n case 'job.text':\n return route === JOBS_ROUTE\n default:\n // A chat turn is metered under the console route it was asked from.\n return !route.startsWith(COPY_ROUTE) && route !== JOBS_ROUTE\n }\n}\n\nconst SENTINELS = new Set<string>(Object.values(AI_METER_SENTINELS))\n\n/** The measured median exchange for a step kind, or `null` too few. */\nexport async function readMeasuredStepUsage(\n firestore: FirebaseFirestore.Firestore,\n orgId: string,\n kind: AiStepKind,\n): Promise<AiUsage | null> {\n const snapshot = await firestore\n .collection('orgs')\n .doc(orgId)\n .collection('assistSignals')\n .orderBy('createdAt', 'desc')\n .limit(AI_MODEL_SAMPLE_SIGNALS)\n .get()\n const samples: AiUsage[] = []\n for (const doc of snapshot.docs) {\n const data = doc.data() as Record<string, unknown>\n if (data['deflected'] === true) continue\n if (SENTINELS.has(String(data['model'] ?? ''))) continue\n if (!signalRouteMatchesStep(String(data['route'] ?? ''), kind)) continue\n samples.push({\n inputTokens: Number(data['inputTokens'] ?? 0),\n outputTokens: Number(data['outputTokens'] ?? 0),\n cacheReadTokens: Number(data['cacheReadTokens'] ?? 0),\n cacheWriteTokens: Number(data['cacheWriteTokens'] ?? 0),\n })\n }\n return aiMedianUsage(samples)\n}\n"],"names":["AI_METER_SENTINELS","aiMedianUsage","AI_MODEL_SAMPLE_SIGNALS","COPY_ROUTE","JOBS_ROUTE","signalRouteMatchesStep","route","kind","startsWith","SENTINELS","Set","Object","values","readMeasuredStepUsage","firestore","orgId","snapshot","collection","doc","orderBy","limit","get","samples","docs","data","has","String","push","inputTokens","Number","outputTokens","cacheReadTokens","cacheWriteTokens"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED,SAASA,kBAAkB,QAAyB,0BAAsB;AAE1E,SAASC,aAAa,QAAQ,+BAA2B;AAEzD;;;;;;;;;;;CAWC,GAED,gCAAgC,GAChC,OAAO,MAAMC,0BAA0B,GAAE;AAEzC,MAAMC,aAAa;AACnB,MAAMC,aAAa;AAEnB,wEAAwE,GACxE,OAAO,SAASC,uBAAuBC,KAAa,EAAEC,IAAgB;IACpE,OAAQA;QACN,KAAK;YACH,OAAOD,UAAU,GAAGH,WAAW,OAAO,CAAC;QACzC,KAAK;YACH,OAAOG,UAAU,GAAGH,WAAW,IAAI,CAAC;QACtC,KAAK;QACL,KAAK;YACH,OAAOG,UAAU,GAAGH,WAAW,OAAO,CAAC;QACzC,KAAK;YACH,OAAOG,UAAUF;QACnB;YACE,oEAAoE;YACpE,OAAO,CAACE,MAAME,UAAU,CAACL,eAAeG,UAAUF;IACtD;AACF;AAEA,MAAMK,YAAY,IAAIC,IAAYC,OAAOC,MAAM,CAACZ;AAEhD,qEAAqE,GACrE,OAAO,eAAea,sBACpBC,SAAsC,EACtCC,KAAa,EACbR,IAAgB;IAEhB,MAAMS,WAAW,MAAMF,UACpBG,UAAU,CAAC,QACXC,GAAG,CAACH,OACJE,UAAU,CAAC,iBACXE,OAAO,CAAC,aAAa,QACrBC,KAAK,CAAClB,yBACNmB,GAAG;IACN,MAAMC,UAAqB,EAAE;IAC7B,KAAK,MAAMJ,OAAOF,SAASO,IAAI,CAAE;YAGNC,aACUA,aAEbA,mBACCA,oBACGA,uBACCA;QAR3B,MAAMA,OAAON,IAAIM,IAAI;QACrB,IAAIA,IAAI,CAAC,YAAY,KAAK,MAAM;QAChC,IAAIf,UAAUgB,GAAG,CAACC,QAAOF,cAAAA,IAAI,CAAC,QAAQ,YAAbA,cAAiB,MAAM;QAChD,IAAI,CAACnB,uBAAuBqB,QAAOF,cAAAA,IAAI,CAAC,QAAQ,YAAbA,cAAiB,KAAKjB,OAAO;QAChEe,QAAQK,IAAI,CAAC;YACXC,aAAaC,QAAOL,oBAAAA,IAAI,CAAC,cAAc,YAAnBA,oBAAuB;YAC3CM,cAAcD,QAAOL,qBAAAA,IAAI,CAAC,eAAe,YAApBA,qBAAwB;YAC7CO,iBAAiBF,QAAOL,wBAAAA,IAAI,CAAC,kBAAkB,YAAvBA,wBAA2B;YACnDQ,kBAAkBH,QAAOL,yBAAAA,IAAI,CAAC,mBAAmB,YAAxBA,yBAA4B;QACvD;IACF;IACA,OAAOvB,cAAcqB;AACvB"}
@@ -0,0 +1,55 @@
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 { UsageAlertContext } from '@aglyn/aglyn/plugin-manager/usage-alert-contributors';
18
+ /**
19
+ * The AI plugin's staff alerts on provider spend (AGL-2984), evaluated for
20
+ * every org by the usage-alerts sweep through its usage alert contributor
21
+ * seam. Two alerts, in this order, each deduped under its own guard key:
22
+ *
23
+ * - THE MARGIN GUARD warns. The meter caps an entitled org by MESSAGE count,
24
+ * and a month of long, cache-cold exchanges on a large model is a
25
+ * three-figure provider bill against a subscription that did not move. One
26
+ * org's spend crossing the review threshold tells staff, and every further
27
+ * whole multiple of the threshold tells them again, so an escalating cost
28
+ * never goes quiet because it already spoke.
29
+ * - THE HARD CEILING reports a stop. Past the monthly spend ceiling the
30
+ * reservation refuses every assist request from the org, so its assistant
31
+ * has stopped answering, and staff are told so in those words. It cannot
32
+ * ride the margin guard: that one speaks in whole multiples of its
33
+ * threshold, so an org climbing from the threshold to the ceiling is still
34
+ * at 1x and says nothing. Announced once a month, because crossing is a
35
+ * state rather than an escalating sum.
36
+ *
37
+ * The ceiling is the one THIS org's reservations refuse at —
38
+ * `assistBackstopCeilingUsd` — not the repo default for everyone. That
39
+ * default binds only a workspace with no band of its own; a band sold past,
40
+ * a band that is a wall, and an uncapped staff comp are each measured
41
+ * against something else, and announcing a $40 stop the reservation never
42
+ * makes would send staff after an assistant that is still answering.
43
+ *
44
+ * Both are STAFF alerts. The org is not charged for this spend and has done
45
+ * nothing wrong, so mailing the customer about our cost would be alarming and
46
+ * meaningless. Both read the spend figure the sweep built, record through the
47
+ * sweep's guard and send through the sweep's senders, so the first-sweep
48
+ * seeding and the run's report apply to them exactly as to core's alerts.
49
+ */
50
+ /** The margin guard's key: the whole multiples announced this month. */
51
+ export declare const AI_MARGIN_GUARD_KEY = "assistCogs";
52
+ /** The hard ceiling's key: announced once for the month. */
53
+ export declare const AI_CEILING_GUARD_KEY = "assistCeiling";
54
+ /** Evaluates one org: the margin guard, then the hard ceiling. */
55
+ export declare function evaluateAiUsageAlerts(context: UsageAlertContext): Promise<void>;
@@ -0,0 +1,114 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */ import { resolveAssistCreditBudget } from "@aglyn/aglyn/app-utils/assist-credits";
17
+ import { aiAddonName, hasAiAddon, isUncappedPlanComp } from "@aglyn/aglyn/app-utils/plan-entitlements";
18
+ import { PLATFORM_BRAND_NAME } from "@aglyn/aglyn/app-utils/platform-brand";
19
+ import { assistCeilingBreach, assistCogsAlertThresholdUsd, assistMarginBreach, assistMarginMultiple } from "@aglyn/aglyn/app-utils/usage-budget";
20
+ import { assistBackstopCeilingUsd } from "./assist-ceiling.js";
21
+ /**
22
+ * The AI plugin's staff alerts on provider spend (AGL-2984), evaluated for
23
+ * every org by the usage-alerts sweep through its usage alert contributor
24
+ * seam. Two alerts, in this order, each deduped under its own guard key:
25
+ *
26
+ * - THE MARGIN GUARD warns. The meter caps an entitled org by MESSAGE count,
27
+ * and a month of long, cache-cold exchanges on a large model is a
28
+ * three-figure provider bill against a subscription that did not move. One
29
+ * org's spend crossing the review threshold tells staff, and every further
30
+ * whole multiple of the threshold tells them again, so an escalating cost
31
+ * never goes quiet because it already spoke.
32
+ * - THE HARD CEILING reports a stop. Past the monthly spend ceiling the
33
+ * reservation refuses every assist request from the org, so its assistant
34
+ * has stopped answering, and staff are told so in those words. It cannot
35
+ * ride the margin guard: that one speaks in whole multiples of its
36
+ * threshold, so an org climbing from the threshold to the ceiling is still
37
+ * at 1x and says nothing. Announced once a month, because crossing is a
38
+ * state rather than an escalating sum.
39
+ *
40
+ * The ceiling is the one THIS org's reservations refuse at —
41
+ * `assistBackstopCeilingUsd` — not the repo default for everyone. That
42
+ * default binds only a workspace with no band of its own; a band sold past,
43
+ * a band that is a wall, and an uncapped staff comp are each measured
44
+ * against something else, and announcing a $40 stop the reservation never
45
+ * makes would send staff after an assistant that is still answering.
46
+ *
47
+ * Both are STAFF alerts. The org is not charged for this spend and has done
48
+ * nothing wrong, so mailing the customer about our cost would be alarming and
49
+ * meaningless. Both read the spend figure the sweep built, record through the
50
+ * sweep's guard and send through the sweep's senders, so the first-sweep
51
+ * seeding and the run's report apply to them exactly as to core's alerts.
52
+ */ /** The margin guard's key: the whole multiples announced this month. */ export const AI_MARGIN_GUARD_KEY = 'assistCogs';
53
+ /** The hard ceiling's key: announced once for the month. */ export const AI_CEILING_GUARD_KEY = 'assistCeiling';
54
+ /** Both alerts send staff to the org list. */ const STAFF_ORGS_LINK = '/admin/orgs';
55
+ /** Evaluates one org: the margin guard, then the hard ceiling. */ export async function evaluateAiUsageAlerts(context) {
56
+ await alertOnMarginGuard(context);
57
+ await alertOnHardCeiling(context);
58
+ }
59
+ /** How both alerts name the org: its slug, or its id when it has none. */ function orgName({ orgSlug, orgId }) {
60
+ return orgSlug != null ? orgSlug : orgId;
61
+ }
62
+ async function alertOnMarginGuard(context) {
63
+ const { org, month, spend } = context;
64
+ const thresholdUsd = assistCogsAlertThresholdUsd(process.env.ASSIST_ORG_MONTHLY_COGS_ALERT_USD);
65
+ // The guard records the whole multiple announced, which is 0 for a zero or
66
+ // non-finite threshold — a reading the breach predicate never agrees to.
67
+ const multiple = assistMarginMultiple(spend.assistUsd, thresholdUsd);
68
+ const due = assistMarginBreach({
69
+ assistUsd: spend.assistUsd,
70
+ thresholdUsd,
71
+ guard: context.guards[AI_MARGIN_GUARD_KEY],
72
+ month
73
+ });
74
+ if (!due || !context.recordAlert(AI_MARGIN_GUARD_KEY, multiple)) return;
75
+ const title = `Assist token spend is $${spend.assistUsd.toFixed(2)} for one org this month`;
76
+ // The add-on state and the band: the same dollar figure is a finding on an
77
+ // org paying for the add-on and an incident on one that is not, and the
78
+ // reader should not have to open the console to know which.
79
+ const addonClause = hasAiAddon(org) ? `The ${aiAddonName()} add-on is on` : `The ${aiAddonName()} add-on is off`;
80
+ const bandCredits = resolveAssistCreditBudget(org);
81
+ const bandClause = bandCredits !== null ? `an AI credit band of ${bandCredits.toLocaleString()}` : isUncappedPlanComp(org) ? 'no AI credit band (an uncapped staff comp)' : 'no AI credit band';
82
+ await context.alertStaff({
83
+ quota: AI_MARGIN_GUARD_KEY,
84
+ threshold: multiple,
85
+ title,
86
+ body: `${orgName(context)} has run about ` + `$${spend.assistUsd.toFixed(2)} of ${PLATFORM_BRAND_NAME} Assist ` + `tokens in ${month}, past the $${thresholdUsd.toFixed(0)} review ` + 'threshold. Assist is a plan entitlement with no per-token ' + 'price, so this is margin, not revenue. ' + `${addonClause}, with ${bandClause}.`,
87
+ link: STAFF_ORGS_LINK,
88
+ emailContext: 'assist-margin'
89
+ });
90
+ }
91
+ async function alertOnHardCeiling(context) {
92
+ const { org, month, spend } = context;
93
+ // The same composition the reservation refuses on, for this org, so the
94
+ // figure announced and the figure enforced cannot drift apart.
95
+ const ceilingUsd = assistBackstopCeilingUsd(org);
96
+ const due = assistCeilingBreach({
97
+ assistUsd: spend.assistUsd,
98
+ ceilingUsd,
99
+ guard: context.guards[AI_CEILING_GUARD_KEY],
100
+ month
101
+ });
102
+ if (!due || !context.recordAlert(AI_CEILING_GUARD_KEY, 1)) return;
103
+ const ceiling = `$${Number(ceilingUsd).toFixed(0)}`;
104
+ await context.alertStaff({
105
+ quota: AI_CEILING_GUARD_KEY,
106
+ threshold: 1,
107
+ title: `Assist is REFUSING ${orgName(context)} — the ` + `${ceiling} monthly spend ceiling is crossed`,
108
+ body: `${orgName(context)} has run about ` + `$${spend.assistUsd.toFixed(2)} of ${PLATFORM_BRAND_NAME} Assist ` + `tokens in ${month}, past the ` + `${ceiling} ceiling. Every further ` + 'Assist request from this organization is refused until the month ' + 'rolls over — the assistant is not degraded or slowed, it is off. ' + 'The customer keeps whatever messages their plan has left, and the ' + 'refusal says so in its own words.',
109
+ link: STAFF_ORGS_LINK,
110
+ emailContext: 'assist-ceiling'
111
+ });
112
+ }
113
+
114
+ //# sourceMappingURL=ai-usage-alerts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/usage/ai-usage-alerts.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 { resolveAssistCreditBudget } from '@aglyn/aglyn/app-utils/assist-credits'\nimport {\n aiAddonName,\n hasAiAddon,\n isUncappedPlanComp,\n} from '@aglyn/aglyn/app-utils/plan-entitlements'\nimport { PLATFORM_BRAND_NAME } from '@aglyn/aglyn/app-utils/platform-brand'\nimport {\n assistCeilingBreach,\n assistCogsAlertThresholdUsd,\n assistMarginBreach,\n assistMarginMultiple,\n} from '@aglyn/aglyn/app-utils/usage-budget'\nimport type { UsageAlertContext } from '@aglyn/aglyn/plugin-manager/usage-alert-contributors'\nimport { assistBackstopCeilingUsd } from './assist-ceiling'\n\n/**\n * The AI plugin's staff alerts on provider spend (AGL-2984), evaluated for\n * every org by the usage-alerts sweep through its usage alert contributor\n * seam. Two alerts, in this order, each deduped under its own guard key:\n *\n * - THE MARGIN GUARD warns. The meter caps an entitled org by MESSAGE count,\n * and a month of long, cache-cold exchanges on a large model is a\n * three-figure provider bill against a subscription that did not move. One\n * org's spend crossing the review threshold tells staff, and every further\n * whole multiple of the threshold tells them again, so an escalating cost\n * never goes quiet because it already spoke.\n * - THE HARD CEILING reports a stop. Past the monthly spend ceiling the\n * reservation refuses every assist request from the org, so its assistant\n * has stopped answering, and staff are told so in those words. It cannot\n * ride the margin guard: that one speaks in whole multiples of its\n * threshold, so an org climbing from the threshold to the ceiling is still\n * at 1x and says nothing. Announced once a month, because crossing is a\n * state rather than an escalating sum.\n *\n * The ceiling is the one THIS org's reservations refuse at —\n * `assistBackstopCeilingUsd` — not the repo default for everyone. That\n * default binds only a workspace with no band of its own; a band sold past,\n * a band that is a wall, and an uncapped staff comp are each measured\n * against something else, and announcing a $40 stop the reservation never\n * makes would send staff after an assistant that is still answering.\n *\n * Both are STAFF alerts. The org is not charged for this spend and has done\n * nothing wrong, so mailing the customer about our cost would be alarming and\n * meaningless. Both read the spend figure the sweep built, record through the\n * sweep's guard and send through the sweep's senders, so the first-sweep\n * seeding and the run's report apply to them exactly as to core's alerts.\n */\n\n/** The margin guard's key: the whole multiples announced this month. */\nexport const AI_MARGIN_GUARD_KEY = 'assistCogs'\n\n/** The hard ceiling's key: announced once for the month. */\nexport const AI_CEILING_GUARD_KEY = 'assistCeiling'\n\n/** Both alerts send staff to the org list. */\nconst STAFF_ORGS_LINK = '/admin/orgs'\n\n/** Evaluates one org: the margin guard, then the hard ceiling. */\nexport async function evaluateAiUsageAlerts(\n context: UsageAlertContext,\n): Promise<void> {\n await alertOnMarginGuard(context)\n await alertOnHardCeiling(context)\n}\n\n/** How both alerts name the org: its slug, or its id when it has none. */\nfunction orgName({ orgSlug, orgId }: UsageAlertContext): string {\n return orgSlug ?? orgId\n}\n\nasync function alertOnMarginGuard(context: UsageAlertContext): Promise<void> {\n const { org, month, spend } = context\n const thresholdUsd = assistCogsAlertThresholdUsd(\n process.env.ASSIST_ORG_MONTHLY_COGS_ALERT_USD,\n )\n // The guard records the whole multiple announced, which is 0 for a zero or\n // non-finite threshold — a reading the breach predicate never agrees to.\n const multiple = assistMarginMultiple(spend.assistUsd, thresholdUsd)\n const due = assistMarginBreach({\n assistUsd: spend.assistUsd,\n thresholdUsd,\n guard: context.guards[AI_MARGIN_GUARD_KEY],\n month,\n })\n if (!due || !context.recordAlert(AI_MARGIN_GUARD_KEY, multiple)) return\n\n const title = `Assist token spend is $${spend.assistUsd.toFixed(2)} for one org this month`\n // The add-on state and the band: the same dollar figure is a finding on an\n // org paying for the add-on and an incident on one that is not, and the\n // reader should not have to open the console to know which.\n const addonClause = hasAiAddon(org as never)\n ? `The ${aiAddonName()} add-on is on`\n : `The ${aiAddonName()} add-on is off`\n const bandCredits = resolveAssistCreditBudget(org as never)\n const bandClause =\n bandCredits !== null\n ? `an AI credit band of ${bandCredits.toLocaleString()}`\n : isUncappedPlanComp(org as never)\n ? 'no AI credit band (an uncapped staff comp)'\n : 'no AI credit band'\n await context.alertStaff({\n quota: AI_MARGIN_GUARD_KEY,\n threshold: multiple,\n title,\n body:\n `${orgName(context)} has run about ` +\n `$${spend.assistUsd.toFixed(2)} of ${PLATFORM_BRAND_NAME} Assist ` +\n `tokens in ${month}, past the $${thresholdUsd.toFixed(0)} review ` +\n 'threshold. Assist is a plan entitlement with no per-token ' +\n 'price, so this is margin, not revenue. ' +\n `${addonClause}, with ${bandClause}.`,\n link: STAFF_ORGS_LINK,\n emailContext: 'assist-margin',\n })\n}\n\nasync function alertOnHardCeiling(context: UsageAlertContext): Promise<void> {\n const { org, month, spend } = context\n // The same composition the reservation refuses on, for this org, so the\n // figure announced and the figure enforced cannot drift apart.\n const ceilingUsd = assistBackstopCeilingUsd(org as never)\n const due = assistCeilingBreach({\n assistUsd: spend.assistUsd,\n ceilingUsd,\n guard: context.guards[AI_CEILING_GUARD_KEY],\n month,\n })\n if (!due || !context.recordAlert(AI_CEILING_GUARD_KEY, 1)) return\n\n const ceiling = `$${Number(ceilingUsd).toFixed(0)}`\n await context.alertStaff({\n quota: AI_CEILING_GUARD_KEY,\n threshold: 1,\n title:\n `Assist is REFUSING ${orgName(context)} — the ` +\n `${ceiling} monthly spend ceiling is crossed`,\n body:\n `${orgName(context)} has run about ` +\n `$${spend.assistUsd.toFixed(2)} of ${PLATFORM_BRAND_NAME} Assist ` +\n `tokens in ${month}, past the ` +\n `${ceiling} ceiling. Every further ` +\n 'Assist request from this organization is refused until the month ' +\n 'rolls over — the assistant is not degraded or slowed, it is off. ' +\n 'The customer keeps whatever messages their plan has left, and the ' +\n 'refusal says so in its own words.',\n link: STAFF_ORGS_LINK,\n emailContext: 'assist-ceiling',\n })\n}\n"],"names":["resolveAssistCreditBudget","aiAddonName","hasAiAddon","isUncappedPlanComp","PLATFORM_BRAND_NAME","assistCeilingBreach","assistCogsAlertThresholdUsd","assistMarginBreach","assistMarginMultiple","assistBackstopCeilingUsd","AI_MARGIN_GUARD_KEY","AI_CEILING_GUARD_KEY","STAFF_ORGS_LINK","evaluateAiUsageAlerts","context","alertOnMarginGuard","alertOnHardCeiling","orgName","orgSlug","orgId","org","month","spend","thresholdUsd","process","env","ASSIST_ORG_MONTHLY_COGS_ALERT_USD","multiple","assistUsd","due","guard","guards","recordAlert","title","toFixed","addonClause","bandCredits","bandClause","toLocaleString","alertStaff","quota","threshold","body","link","emailContext","ceilingUsd","ceiling","Number"],"mappings":"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"}