@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,978 @@
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
+ */ /**
18
+ * `FieldValue` comes straight from the SDK rather than through the admin
19
+ * barrel (AGL-2073). This module serves every metered AI door — the chat
20
+ * door, the besigner copy assistant and the generation jobs — and importing
21
+ * the admin lib's `firebase-admin` module would drag the default-app
22
+ * initialization (cert credential, RTDB, AppCheck) into every unit test that
23
+ * touches a counter; `FieldValue`'s statics need no app at all.
24
+ */ import { FieldValue } from "firebase-admin/firestore";
25
+ import { ASSIST_PROVIDER_COST_FIELD, assistBandRefuses, assistCreditsFromUsd, assistMonthOverage, assistOverageCapReached, publicAssistCredits, resolveAssistBudgetUsd, resolveAssistOverageCapUsd, resolveAssistOverageRateUsdPer1k } from "@aglyn/aglyn/app-utils/assist-credits";
26
+ import { aiOverageRefusal } from "../billing/ai-overage-gate.js";
27
+ import { aiOverageBillsByInvoice, aiOverageGuardsApply } from "../billing/ai-overage-cutover.js";
28
+ import { AI_BILLING_STANDING_DOC, AI_BILLING_SUBCOLLECTION, readAiOverageMonthLedger } from "../billing/ai-overage-ledger.js";
29
+ import { readAiOverageStanding } from "../billing/ai-overage-standing.js";
30
+ import { AI_HOST_CREDITS_FIELD, readAiAllotmentGate } from "./ai-allotments.js";
31
+ import { isUncappedPlanComp } from "@aglyn/aglyn/app-utils/plan-entitlements";
32
+ import { assistMonthlyCeilingUsd } from "./assist-ceiling.js";
33
+ import { estimateAiBilledUsd, estimateAiProviderCostUsd } from "../providers/catalog.js";
34
+ import { recordAssistRefusal } from "./assist-refusals.js";
35
+ import { announcePlatformFreeSpend, freeAccountReservationWrite, freeAccountUsageRef, freeAssistAccount, freeTasteMeterWrites, freeTasteReadsFrom, freeTasteRefusal, platformFreeSpendRef } from "./assist-free-taste.js";
36
+ import { aiTokenIncrements, recordUserAiUsage } from "./ai-usage-by-user.js";
37
+ import { AI_USAGE_MONTH_KINDS_FIELD, AI_USAGE_TOKENS_FIELD } from "../model/ai-tokens.js";
38
+ import { aiUsageKindFromRoute } from "../model/ai-usage-by-user.js";
39
+ // The ceiling composition lives beside the one other reader it has, the staff
40
+ // refusal alert, in a module that writes nothing; the reservation's importers
41
+ // keep reaching it here.
42
+ export { assistMonthlyCeilingUsd } from "./assist-ceiling.js";
43
+ /**
44
+ * Aglyn Assist metering + the data loop (AGL-1860, phase 1).
45
+ *
46
+ * Collections (org-scoped, ABSENT from firebase-firestore.rules on purpose —
47
+ * default-deny, the forumThreads precedent: every read/write passes the
48
+ * assist API route via the Admin SDK):
49
+ *
50
+ * orgs/{orgId}/assistUsage/{YYYY-MM} per-org monthly cost telemetry:
51
+ * { month, messages, inputTokens, outputTokens, cacheReadTokens,
52
+ * cacheWriteTokens, estCostUsd, byHost: { hostId: credits },
53
+ * kinds: { kind: { requests, estCostUsd, tokens } }, updatedAt }
54
+ * (`byHost` is each site's credits, which a site's AI allotment is
55
+ * measured against — AGL-2942; `kinds` splits the tokens and the
56
+ * measured spend by what each model request was for — AGL-2937)
57
+ * orgs/{orgId}/counters/assistMessagesDaily
58
+ * fields keyed YYYY-MM-DD → integer (the free-tier daily cap counter;
59
+ * same field-per-period shape as the other `counters/*` docs)
60
+ * orgs/{orgId}/assistExchanges/{id} the VERBATIM half of one exchange:
61
+ * { uid, question, answer, hostId, createdAt, expiresAt }
62
+ * orgs/{orgId}/assistSignals/{id} the DERIVED half, same id:
63
+ * { route, hostId, model, tier, kind, inputTokens, outputTokens,
64
+ * cacheReadTokens, cacheWriteTokens, estCostUsd, docsPaths,
65
+ * stopReason, feedback: 'up'|'down'|null, createdAt }
66
+ *
67
+ * The Free taste (AGL-2925) adds two more, one under the workspace OWNER's
68
+ * user document and one platform-wide, both documented and both closed to
69
+ * clients in `assist-free-taste.ts`.
70
+ *
71
+ * Costs are OUR cost estimates at list rates (pricing-tunable telemetry),
72
+ * mirrored after ORG_COGS_UNIT_RATES_USD's posture: cost visibility per org
73
+ * from day one so the paid gate and caps can be tuned with data — the * "must not eat margins" constraint.
74
+ *
75
+ * ── Why the exchange is split in two (AGL-1972) ────────────────────────────
76
+ *
77
+ * One document carrying both halves forces one retention period onto two
78
+ * kinds of data with opposite needs. The prose is what a person typed; the
79
+ * data loop is what it cited and what it cost. Keeping them together means
80
+ * either the prose is retained forever so the loop keeps its corpus, or the
81
+ * loop's corpus is destroyed so the prose can expire. Neither is the answer,
82
+ * and picking one number for both is how that false choice gets made.
83
+ *
84
+ * So: `assistExchanges` holds the question, the answer and the asking `uid`,
85
+ * and carries `expiresAt` — a TTL policy reaps it after
86
+ * ASSIST_EXCHANGE_RETENTION_DAYS. `assistSignals` holds no prose and NO uid,
87
+ * carries no expiry, and is what the docs-gap view, the thumbs loop and the
88
+ * cost meters actually read. The corpus the loop needs outlives the words
89
+ * that produced it, because the corpus was never the words.
90
+ *
91
+ * Both subcollections sit under the org, so `recursiveDelete(orgRef)` still
92
+ * takes them and an erasure still clears everything with no extra sweep. And
93
+ * both are ABSENT from firebase-firestore.rules deliberately: the org block
94
+ * matches its subcollections BY NAME and has no wildcard, so an unmatched
95
+ * name is default-deny for every client (verified against the live ruleset —
96
+ * the `{subcollection}/{document=**}` catch-all is under `hosts/{hostId}`,
97
+ * not here).
98
+ *
99
+ * ⚠️ The TTL policy is MANUAL gcloud configuration, not repo state. It is
100
+ * documented in `docs/FIRESTORE_MANUAL_CONFIG.md` and declared as a
101
+ * `fieldOverrides` entry in `cloud/firebase-firestore.indexes.json` — the
102
+ * declaration is not decoration, it is what stops the next unrelated index
103
+ * deploy from DELETING the policy. `apps/console/specs/retention-ttl-config.spec.ts`
104
+ * fails the build if either half goes missing.
105
+ */ /** Current billing month key, `YYYY-MM`, matching the usage rollup. */ export function assistUsageMonth(now = new Date()) {
106
+ return now.toISOString().slice(0, 7);
107
+ }
108
+ /** Current day key, `YYYY-MM-DD` (UTC — same clock as the month key). */ export function assistUsageDay(now = new Date()) {
109
+ return now.toISOString().slice(0, 10);
110
+ }
111
+ /**
112
+ * How long the VERBATIM half of an exchange is kept — the question, the
113
+ * answer and the asking uid (AGL-1972).
114
+ *
115
+ * 180 days, and the number is chosen against what actually reads this data
116
+ * rather than against a round figure:
117
+ *
118
+ * - The docs-gap loop mines `docsPaths` and the thumbs rating. Both live on
119
+ * the signal document, which has no expiry, so shortening this period
120
+ * costs the loop nothing. That separation is what makes 180 affordable;
121
+ * without it the honest answer would have been "forever".
122
+ * - Two full quarters is long enough to read a quarter's questions LATE, and
123
+ * long enough to diff what people asked before and after a docs rewrite —
124
+ * the one analysis that genuinely needs the prose and not the citations.
125
+ * - It is short enough that a workspace open for years is not an indefinite
126
+ * archive of what its people typed into a text box.
127
+ *
128
+ * ⚠️ TTL deletion is best-effort within ~72h of expiry, so nothing may treat
129
+ * an exchange's absence OR its presence as exact at the boundary. Nothing
130
+ * does: the only reader addresses an exchange by id and tolerates a miss.
131
+ */ export const ASSIST_EXCHANGE_RETENTION_DAYS = 180;
132
+ const DAY_MS = 24 * 60 * 60 * 1000;
133
+ /**
134
+ * When an exchange written at `now` expires. A `Date` rather than a number:
135
+ * a TTL policy keys on a Firestore **Timestamp** and silently governs
136
+ * nothing when the field is a number (`bookings.expiresAtMs` is the
137
+ * documented non-target for exactly this reason). The Admin SDK converts a
138
+ * JS `Date` to a Timestamp on write, which is how `cspViolationDaily` does
139
+ * it and is why this module needs no firebase-admin type here.
140
+ */ export function assistExchangeExpiry(now = new Date()) {
141
+ return new Date(now.getTime() + ASSIST_EXCHANGE_RETENTION_DAYS * DAY_MS);
142
+ }
143
+ /**
144
+ * Free-tier daily message cap (level-1 answers only). Env-tunable without a
145
+ * deploy of new code paths.
146
+ *
147
+ * What ten messages actually cost: about **$0.28 a day** at Sonnet list
148
+ * rates, taking the worst case the clamps allow (see
149
+ * `ASSIST_ORG_MONTHLY_COGS_LIMIT_DEFAULT_USD` for the same arithmetic
150
+ * carried to the monthly ceiling). A typical question costs a fraction of
151
+ * that, because the worst case assumes a full 8,000-character history and a
152
+ * 4,000-character question on every one of the ten.
153
+ *
154
+ * This docstring used to claim "well under a cent a day", which was the
155
+ * pre-AGL-2441 figure and wrong by ~28x once the history clamp was measured
156
+ * rather than assumed. It is restated here because it is the stated
157
+ * justification for the size of this cap, and a justification that is off by
158
+ * that much is how a cap ends up set by a number nobody re-derived.
159
+ */ export function assistFreeDailyLimit() {
160
+ const raw = process.env.ASSIST_FREE_DAILY_LIMIT;
161
+ // `Number('')` is 0, so an unset/empty var must fall through to the
162
+ // default rather than silently zeroing the free tier.
163
+ const parsed = raw ? Number(raw) : Number.NaN;
164
+ return Number.isFinite(parsed) && parsed >= 0 ? Math.floor(parsed) : 10;
165
+ }
166
+ /**
167
+ * Entitled (Pro+/aiAssist) monthly message cap — a runaway guard, not a
168
+ * product limit: high enough that no real user hits it, low enough that a
169
+ * scripted client cannot turn one subscription into unbounded token spend.
170
+ */ export function assistEntitledMonthlyLimit() {
171
+ const raw = process.env.ASSIST_ENTITLED_MONTHLY_LIMIT;
172
+ const parsed = raw ? Number(raw) : Number.NaN;
173
+ return Number.isFinite(parsed) && parsed > 0 ? Math.floor(parsed) : 1000;
174
+ }
175
+ /**
176
+ * What one exchange DRAWS FROM THE CUSTOMER, at the serving model's billed
177
+ * rates, rounded to 6dp — the figure `assistCreditsFromUsd` turns into
178
+ * credits and the one the band, the cap and the invoice are measured in.
179
+ *
180
+ * The rates are the model catalog's (AGL-2939), keyed by model rather than
181
+ * fixed at one model's because `ASSIST_MODEL` is an env override: a
182
+ * one-line incident swap to a dearer model would otherwise keep reporting
183
+ * the cheaper money, and per-org cost would read as roughly right — the
184
+ * failure mode this whole meter exists to prevent. An unknown id is priced
185
+ * at the dearest known tier on purpose, because an estimate that errs low is
186
+ * worse than one that errs high, and a docs-only answer is metered under a
187
+ * zero-priced sentinel (`AI_METER_SENTINELS`) so it lands in the same rollup
188
+ * as a served one.
189
+ *
190
+ * NOT A COST (AGL-3015). A model may be billed above what its provider
191
+ * charges, so this overstates what the exchange cost us by exactly that
192
+ * markup. `estimateAssistProviderCostUsd` is the figure a margin or a spend
193
+ * meter takes.
194
+ */ export function estimateAssistCostUsd(usage, model) {
195
+ return estimateAiBilledUsd(usage, model);
196
+ }
197
+ /**
198
+ * What one exchange COST US, at the serving model's provider rates, rounded
199
+ * to 6dp — real money, recorded beside the billed figure so a margin is
200
+ * taken against a bill we actually pay rather than against a price we
201
+ * charge.
202
+ *
203
+ * At or below `estimateAssistCostUsd` for the same tokens, and equal to it
204
+ * on every model billed at its provider's list.
205
+ */ export function estimateAssistProviderCostUsd(usage, model) {
206
+ return estimateAiProviderCostUsd(usage, model);
207
+ }
208
+ /**
209
+ * Reserve one assist message BEFORE the model is called (AGL-2057).
210
+ *
211
+ * This replaces `checkAssistQuota` on the request path, and the difference is
212
+ * the whole point. `checkAssistQuota` READ the counter and let the request
213
+ * through; the counter only moved in `recordAssistExchange`, at stream
214
+ * COMPLETION. Two ways out of the cap followed, both of which spend real
215
+ * provider tokens for an org that has no invoice to put them on:
216
+ *
217
+ * 1. **Concurrency.** N in-flight requests each read `used < limit` before any
218
+ * of them recorded. The per-uid rate limiter (20/min) was the only bound.
219
+ * 2. **Abandoned streams.** Recording ran in the stream's completion handler,
220
+ * so a client that opened a request and dropped it never counted at all.
221
+ * Looped, that is UNBOUNDED spend on a free workspace — the cap simply
222
+ * never advanced. This is the fail-open that costs money silently.
223
+ *
224
+ * So the count moves to the front, inside a transaction: read and increment
225
+ * are one atomic step, and a refused request never reaches the provider. The
226
+ * lesson is AGL's own — fix WHEN the quota is evaluated, not how the counting
227
+ * is done.
228
+ *
229
+ * Both counters move here (the daily one AND monthly `messages`) so message
230
+ * counting has exactly one home. `recordAssistExchange` therefore records the
231
+ * exchange, its tokens and its cost, and counts NO messages; calling it after
232
+ * a reservation must not double-count.
233
+ *
234
+ * A plan-less org resolves as free upstream, so an unknown org gets the
235
+ * SMALLER cap. That direction is deliberate.
236
+ *
237
+ * ## The spend gate is the one that matters now
238
+ *
239
+ * The message caps above are a runaway guard. The gate that decides what a
240
+ * paying workspace gets is the SPEND ceiling, because assist actions differ
241
+ * in cost by up to two orders of magnitude: a question is a few thousand
242
+ * tokens and generating a screen carries a node tree, a component catalog and
243
+ * theme tokens in and structured markup out. Counting both as one message
244
+ * would let ten screen builds outspend a thousand questions while both read
245
+ * as being within allowance.
246
+ *
247
+ * `org` is the billing document the caller already resolved `entitled` from.
248
+ * It is optional and defaults to no org, which resolves as free — a band of
249
+ * none, and therefore exactly the operator-backstop behaviour that predates
250
+ * plan bands. Passing it is what makes a plan's own band bind.
251
+ *
252
+ * ## Refusal is legitimate here, unlike the transactional email carve-out
253
+ *
254
+ * A campaign send is refusable at its band and transactional mail is not,
255
+ * because a blocked password reset locks somebody out of their own account.
256
+ * Nothing assist does is that. It is help, not a person's data and not their
257
+ * access: a refused question means the answer is not given, and a refused
258
+ * build means the screen is built by hand in a besigner that still works. So
259
+ * assist refuses at the band with no carve-out.
260
+ *
261
+ * What is never refused is what costs nothing. A docs-deflected answer and a
262
+ * cache hit spend no tokens and take NO RESERVATION AT ALL — they return
263
+ * before this function is reached — so a workspace at its band keeps getting
264
+ * every answer the docs index can give it. That is not a carve-out inside
265
+ * this gate; it is the reason those paths are ahead of it.
266
+ *
267
+ * ## The band is sold past by default (AGL-2653)
268
+ *
269
+ * Refusing at the band is legitimate; it is no longer the default. A plan
270
+ * with an `extraAssistCreditsUsdPer1k` keeps reserving past its band and
271
+ * `report-usage` bills the excess at that rate, unless the org's own
272
+ * `assistOverage.hardCap` asks for the wall — `assistBandRefuses` is the one
273
+ * place that rule lives. The ceiling below is composed from that answer, and
274
+ * `refusedBy: 'band'` is how a refusal the switch caused is told apart from
275
+ * one the operator's figure caused.
276
+ *
277
+ * ## The Free taste is metered twice (AGL-2925)
278
+ *
279
+ * A Free workspace's band is a wall, and a wall per workspace is not a
280
+ * bound per person. So when `org` resolves to the Free plan the SAME
281
+ * transaction also reads the workspace owner's account document and the
282
+ * platform's day of free spend, and refuses on the account's daily request
283
+ * cap, its refusal pause, its monthly allowance and the platform ceiling —
284
+ * see `assist-free-taste.ts` for each. An admitted free reservation counts
285
+ * the request on the account beside the org's own counters, so the release
286
+ * path hands both back together.
287
+ *
288
+ * ## Allotments sit inside the band (AGL-2942)
289
+ *
290
+ * `subject` names the person asking and the site the request named. Once
291
+ * the workspace's own ceilings — the message cap, the band or budget, the
292
+ * overage cap — have admitted the request, the SAME transaction reads the
293
+ * allotments that apply to that person and site and refuses as `allotment`
294
+ * when a hard one is spent. After the workspace's rungs, so a workspace at
295
+ * its band hears about its band and an allotment can never admit what the
296
+ * band refused; before the Free taste's, which are precautions about the
297
+ * account rather than decisions a manager made. Refusing moves no counter,
298
+ * like every refusal above it. A soft allotment at 80% or 100% admits the
299
+ * request and is announced once the transaction has committed.
300
+ */ export async function reserveAssistMessage(firestore, orgId, entitled, now = new Date(), org = null, subject = null) {
301
+ var _reservation_allotment;
302
+ const reservation = await reserveInTransaction(firestore, orgId, entitled, now, org, subject);
303
+ if ((_reservation_allotment = reservation.allotment) == null ? void 0 : _reservation_allotment.alerts.length) {
304
+ announceAllotmentAlerts(firestore, orgId, org, reservation);
305
+ }
306
+ return reservation;
307
+ }
308
+ /**
309
+ * A soft allotment's crossing, told through the alert pipeline — off the
310
+ * reservation's await path and never failing it: the request was admitted,
311
+ * and a notification is not a reason to take that back. Loaded when the
312
+ * first crossing arrives, so the modules that write notifications and send
313
+ * mail are not part of every metered request.
314
+ */ function announceAllotmentAlerts(firestore, orgId, org, reservation) {
315
+ var _ref;
316
+ var _reservation_allotment;
317
+ const alerts = (_ref = (_reservation_allotment = reservation.allotment) == null ? void 0 : _reservation_allotment.alerts) != null ? _ref : [];
318
+ void import("./ai-allotment-alerts.js").then(({ announceAiAllotmentAlerts })=>announceAiAllotmentAlerts(firestore, {
319
+ orgId,
320
+ orgSlug: typeof (org == null ? void 0 : org.slug) === 'string' ? String(org.slug) : null,
321
+ month: reservation.monthKey,
322
+ alerts
323
+ })).catch((error)=>console.error('[ai-allotments] alert failed', orgId, error));
324
+ }
325
+ /**
326
+ * The charge this turn may have earned (AGL-3011).
327
+ *
328
+ * Off the await path and never able to fail the turn: the tokens are already
329
+ * spent, and making the answer wait on a Stripe round trip — or losing it to
330
+ * one — would turn a billing problem into a product one. Loaded when the
331
+ * first chargeable turn arrives, so the modules that read org billing and
332
+ * call Stripe are not part of every metered request.
333
+ *
334
+ * Returns before loading anything at all while `AI_OVERAGE_INVOICED_FROM`
335
+ * names no month, which is how this ships: AI overage bills through the
336
+ * monthly meter exactly as it does today, and this costs one string compare.
337
+ *
338
+ * A turn whose process ends before this finishes is covered three ways: the
339
+ * next turn tries again, the reconcile sweep finishes a half-made charge,
340
+ * and the gate refuses at the unpaid limit regardless.
341
+ */ function chargeAccruedOverage(firestore, orgId, month, now) {
342
+ if (!aiOverageBillsByInvoice(month)) return;
343
+ void import("../billing/ai-overage-trigger.js").then(({ chargeAccruedAiOverage })=>chargeAccruedAiOverage(firestore, orgId, month, now)).catch((error)=>console.error('[ai-overage] charge failed', orgId, error));
344
+ }
345
+ async function reserveInTransaction(firestore, orgId, entitled, now, org, subject) {
346
+ const increment = FieldValue.increment;
347
+ const serverTimestamp = FieldValue.serverTimestamp;
348
+ const orgRef = firestore.collection('orgs').doc(orgId);
349
+ const day = assistUsageDay(now);
350
+ const month = assistUsageMonth(now);
351
+ const dailyRef = orgRef.collection('counters').doc('assistMessagesDaily');
352
+ const monthlyRef = orgRef.collection('assistUsage').doc(month);
353
+ const limit = entitled ? assistEntitledMonthlyLimit() : assistFreeDailyLimit();
354
+ const period = entitled ? 'month' : 'day';
355
+ const gateRef = entitled ? monthlyRef : dailyRef;
356
+ const gateField = entitled ? 'messages' : day;
357
+ // The Free taste's attribution, resolved once and carried on every
358
+ // answer below: `null` for any paid plan, and for the paths that never
359
+ // consult it.
360
+ const free = freeAssistAccount(org);
361
+ const accountRef = (free == null ? void 0 : free.accountUid) ? freeAccountUsageRef(firestore, free.accountUid, month) : null;
362
+ // The plan's band first, then whether it refuses at all, then whatever the
363
+ // operator did about it. Resolved OUTSIDE the transaction: it is pure
364
+ // arithmetic over a document the caller already holds, and a transaction
365
+ // that retries must not re-derive a ceiling that could have moved between
366
+ // attempts.
367
+ const budgetUsd = resolveAssistBudgetUsd(org);
368
+ const bandRefuses = assistBandRefuses(org);
369
+ // An uncapped staff comp has no band and no backstop default (AGL-3049).
370
+ const costLimitUsd = assistMonthlyCeilingUsd(budgetUsd, bandRefuses, isUncappedPlanComp(org));
371
+ // The ceiling IS the band when the band refuses and nothing lower undercut
372
+ // it. That is the refusal the surface has to attribute to the org's own
373
+ // switch (or to a plan that sells no overage); a lower operator figure is
374
+ // the operator's decision and keeps the operator's word.
375
+ const ceilingIsBand = bandRefuses && budgetUsd !== null && costLimitUsd === budgetUsd;
376
+ // The org's own ceiling on the overage it buys (AGL-2898). Only a band
377
+ // that is SOLD past has an overage to cap, so a band that refuses leaves
378
+ // no ceiling to consult: past a wall there is nothing to be over.
379
+ const overageCapUsd = bandRefuses ? null : resolveAssistOverageCapUsd(org);
380
+ // AGLYN'S OWN GUARDS ON THE OVERAGE IT EXTENDS (AGL-3011), resolved here
381
+ // for the same reason the ceilings above are: pure arithmetic over a
382
+ // document the caller already holds, and a transaction that retries must
383
+ // not re-derive them.
384
+ //
385
+ // They apply only where there IS overage to guard — a band that is sold
386
+ // past, at a rate — and only from the month the platform bills that
387
+ // overage by invoice. Before that month nothing charges, so nothing is
388
+ // ever paid for, so an unpaid-balance guard would refuse every workspace
389
+ // with no invoice to pay. See `ai-overage-cutover.ts`.
390
+ const guardsOverage = !bandRefuses && budgetUsd !== null && resolveAssistOverageRateUsdPer1k(org) !== null && aiOverageGuardsApply(month);
391
+ return firestore.runTransaction(async (tx)=>{
392
+ var _snapshot_get, _monthlySnapshot_get, _ref, _standingSnapshot_data;
393
+ // Every read before any write — Firestore requires that ordering, and it
394
+ // is also what makes check-and-increment a single atomic step.
395
+ const snapshot = await tx.get(gateRef);
396
+ // The spend ceiling reads the SAME monthly document the entitled gate
397
+ // already read, so an entitled reservation costs no extra read at all
398
+ // and a free one costs a second read only when a ceiling is configured.
399
+ const monthlySnapshot = entitled ? snapshot : costLimitUsd === null ? null : await tx.get(monthlyRef);
400
+ // The taste's two extra reads, only for a Free workspace: the owner's
401
+ // account month (when the org names an owner) and the platform's day.
402
+ // Inside the transaction with everything else, so the rungs they feed
403
+ // are decided against the same snapshot the counters move under.
404
+ // The workspace's overage standing (AGL-3011): one document, read only
405
+ // where the guards apply, beside the reads the gate already makes. The
406
+ // allotment gate reads a plugin document in this transaction the same
407
+ // way, and for the same reason — a guard decided against a snapshot the
408
+ // transaction did not take is a guard a concurrent burst walks past.
409
+ const standingSnapshot = guardsOverage ? await tx.get(orgRef.collection(AI_BILLING_SUBCOLLECTION).doc(AI_BILLING_STANDING_DOC)) : null;
410
+ const accountSnapshot = accountRef ? await tx.get(accountRef) : null;
411
+ const platformSnapshot = free ? await tx.get(platformFreeSpendRef(firestore, day)) : null;
412
+ const used = Number((_snapshot_get = snapshot.get(gateField)) != null ? _snapshot_get : 0);
413
+ const costUsd = monthlySnapshot ? Number((_monthlySnapshot_get = monthlySnapshot.get('estCostUsd')) != null ? _monthlySnapshot_get : 0) : null;
414
+ if (!(used < limit)) {
415
+ recordAssistRefusal(firestore, orgId, month, 'messages');
416
+ return {
417
+ allowed: false,
418
+ refusedBy: 'messages',
419
+ period,
420
+ dayKey: day,
421
+ monthKey: month,
422
+ used,
423
+ limit,
424
+ remaining: 0,
425
+ costUsd,
426
+ costLimitUsd,
427
+ budgetUsd,
428
+ free
429
+ };
430
+ }
431
+ // The dollar ceiling, checked AFTER the message cap so the cheaper and
432
+ // more explicable refusal wins when both apply. Refusing here leaves both
433
+ // counters untouched, exactly like the message refusal above: the point
434
+ // of a spend ceiling is that the org above it spends nothing more.
435
+ if (costLimitUsd !== null && costUsd !== null && !(costUsd < costLimitUsd)) {
436
+ recordAssistRefusal(firestore, orgId, month, ceilingIsBand ? 'band' : 'budget');
437
+ return {
438
+ allowed: false,
439
+ refusedBy: ceilingIsBand ? 'band' : 'budget',
440
+ period,
441
+ dayKey: day,
442
+ monthKey: month,
443
+ used,
444
+ limit,
445
+ remaining: Math.max(0, limit - used),
446
+ costUsd,
447
+ costLimitUsd,
448
+ budgetUsd,
449
+ free
450
+ };
451
+ }
452
+ // The org's ceiling on its OVERAGE (AGL-2898), checked after the band
453
+ // because it only exists on a band that is sold past. Same shape as the
454
+ // refusals above — inside the transaction, against the spend the
455
+ // transaction read, moving no counter — so a burst of concurrent
456
+ // requests at the ceiling cannot each read "under" and all proceed.
457
+ // `assistOverageCapReached` prices the month's overage the way the
458
+ // invoice will, so the figure that stops here is the figure that would
459
+ // have been billed.
460
+ if (overageCapUsd !== null && costUsd !== null && assistOverageCapReached(org, costUsd)) {
461
+ recordAssistRefusal(firestore, orgId, month, 'cap');
462
+ return {
463
+ allowed: false,
464
+ refusedBy: 'cap',
465
+ // Whose ceiling, for the doors (AGL-3011). This one is the
466
+ // workspace's own, and it keeps the sentence and the 402 it has had
467
+ // since AGL-2898 — the four below are Aglyn's and have their own.
468
+ capReason: 'customer',
469
+ period,
470
+ dayKey: day,
471
+ monthKey: month,
472
+ used,
473
+ limit,
474
+ remaining: Math.max(0, limit - used),
475
+ costUsd,
476
+ costLimitUsd,
477
+ budgetUsd,
478
+ free
479
+ };
480
+ }
481
+ // AGLYN'S OWN OVERAGE GUARDS (AGL-3011), after the workspace's own
482
+ // ceiling so a workspace that set a limit is told about ITS limit.
483
+ //
484
+ // Four refusals, all `refusedBy: 'cap'` with a `capReason`: no card on
485
+ // file, accrual paused, this month's ceiling reached, and the unpaid
486
+ // balance at its limit. The last is the one that makes the bound a
487
+ // bound — it compares what the month accrued against what it PAID, so
488
+ // overage stops at the unpaid limit whether or not any charge ever ran.
489
+ //
490
+ // Inside the transaction, against the figures the transaction read,
491
+ // moving no counter: a burst of concurrent requests at the limit cannot
492
+ // each read "under" and all proceed.
493
+ const overageGuard = guardsOverage && costUsd !== null && budgetUsd !== null && costUsd >= budgetUsd ? aiOverageRefusal({
494
+ // Priced the way the invoice prices it, so the figure that
495
+ // stops here is the figure that would have been charged.
496
+ overageUsd: assistMonthOverage(org, costUsd).overageMonthlyUsd,
497
+ paidUsd: readAiOverageMonthLedger((_ref = monthlySnapshot == null ? void 0 : monthlySnapshot.data()) != null ? _ref : null).paidUsd,
498
+ standing: readAiOverageStanding((standingSnapshot == null ? void 0 : standingSnapshot.exists) ? (_standingSnapshot_data = standingSnapshot.data()) != null ? _standingSnapshot_data : null : null),
499
+ now
500
+ }) : null;
501
+ if (overageGuard) {
502
+ recordAssistRefusal(firestore, orgId, month, 'cap');
503
+ return {
504
+ allowed: false,
505
+ refusedBy: 'cap',
506
+ capReason: overageGuard.capReason,
507
+ overageLimitUsd: overageGuard.limitUsd,
508
+ overageUnpaidUsd: overageGuard.unpaidUsd,
509
+ period,
510
+ dayKey: day,
511
+ monthKey: month,
512
+ used,
513
+ limit,
514
+ remaining: Math.max(0, limit - used),
515
+ costUsd,
516
+ costLimitUsd,
517
+ budgetUsd,
518
+ free
519
+ };
520
+ }
521
+ // The allotments that apply to the person asking (AGL-2942): read only
522
+ // now that the workspace's own ceilings admitted the request, so an
523
+ // allotment is decided inside the band and a refusal at the band costs
524
+ // no allotment read. Reads, still — every write waits below.
525
+ const allotment = subject ? await readAiAllotmentGate((ref)=>tx.get(ref), orgRef, subject, month, monthlySnapshot) : null;
526
+ if (allotment == null ? void 0 : allotment.refusal) {
527
+ recordAssistRefusal(firestore, orgId, month, 'allotment');
528
+ return {
529
+ allowed: false,
530
+ refusedBy: 'allotment',
531
+ period,
532
+ dayKey: day,
533
+ monthKey: month,
534
+ used,
535
+ limit,
536
+ remaining: Math.max(0, limit - used),
537
+ costUsd,
538
+ costLimitUsd,
539
+ budgetUsd,
540
+ free,
541
+ allotment
542
+ };
543
+ }
544
+ // The Free taste's own rungs (AGL-2925), AFTER the workspace's, so a
545
+ // workspace at its own band is told about its own band. Same shape:
546
+ // decided inside the transaction, against what it read, moving nothing.
547
+ const tasteRefusal = free ? freeTasteRefusal(freeTasteReadsFrom(accountSnapshot, platformSnapshot, day)) : null;
548
+ if (tasteRefusal) {
549
+ recordAssistRefusal(firestore, orgId, month, tasteRefusal);
550
+ return {
551
+ allowed: false,
552
+ refusedBy: tasteRefusal,
553
+ period,
554
+ dayKey: day,
555
+ monthKey: month,
556
+ used,
557
+ limit,
558
+ remaining: Math.max(0, limit - used),
559
+ costUsd,
560
+ costLimitUsd,
561
+ budgetUsd,
562
+ free,
563
+ allotment
564
+ };
565
+ }
566
+ // `set(…, { merge: true })` and never `update()`: the counter document
567
+ // does not exist before an org's first message, and `update()` throws
568
+ // NOT_FOUND on a missing doc where a merging set conjures it.
569
+ tx.set(dailyRef, {
570
+ [day]: increment(1)
571
+ }, {
572
+ merge: true
573
+ });
574
+ tx.set(monthlyRef, {
575
+ month,
576
+ messages: increment(1),
577
+ updatedAt: serverTimestamp()
578
+ }, {
579
+ merge: true
580
+ });
581
+ // The account's request, counted in the same commit as the org's
582
+ // message — one atomic step, or the daily request cap has the same
583
+ // read-then-write hole the message cap was moved here to close.
584
+ if (accountRef) {
585
+ tx.set(accountRef, freeAccountReservationWrite(month, day), {
586
+ merge: true
587
+ });
588
+ }
589
+ return {
590
+ allowed: true,
591
+ refusedBy: null,
592
+ period,
593
+ dayKey: day,
594
+ monthKey: month,
595
+ used: used + 1,
596
+ limit,
597
+ remaining: Math.max(0, limit - (used + 1)),
598
+ costUsd,
599
+ costLimitUsd,
600
+ budgetUsd,
601
+ free,
602
+ allotment
603
+ };
604
+ });
605
+ }
606
+ /**
607
+ * The reservation as a CUSTOMER may see it.
608
+ *
609
+ * `AssistReservation` carries `costUsd`, `costLimitUsd` and `budgetUsd`, and
610
+ * all three are our provider bill at the serving model's list rates. Handing
611
+ * the reservation itself to a browser publishes our model costs, and they
612
+ * would move under customers on every model swap. Assist is surfaced in
613
+ * CREDITS, whose meaning is fixed, and this is the one function that crosses
614
+ * that boundary — every route returning quota to a client returns this.
615
+ *
616
+ * `limit` and `remaining` stay MESSAGES, unchanged: the free tier's daily
617
+ * message cap is a real, separately-worded limit that the panel already
618
+ * renders, and folding it into credits would make "10 messages a day"
619
+ * unsayable.
620
+ *
621
+ * The credit view reads against the LOWER of the plan band and the effective
622
+ * ceiling. The band, because it is the quantity the org was sold and the line
623
+ * `report-usage` bills past — an org buying overage (AGL-2653) has no ceiling
624
+ * at all, and reading against `null` would blank its standing at "used 900 of
625
+ * nothing". The ceiling, because an org whose band was undercut by an
626
+ * operator's figure must not be told it has credits left while being refused.
627
+ * `remaining` clamps at zero, so a workspace past its band reads as spent
628
+ * rather than as owed.
629
+ */ export function publicAssistQuota(reservation) {
630
+ const { budgetUsd, costLimitUsd, costUsd } = reservation;
631
+ const ceilingUsd = budgetUsd === null ? null : costLimitUsd === null ? budgetUsd : Math.min(budgetUsd, costLimitUsd);
632
+ return {
633
+ allowed: reservation.allowed,
634
+ period: reservation.period,
635
+ used: reservation.used,
636
+ limit: reservation.limit,
637
+ remaining: reservation.remaining,
638
+ refusedBy: reservation.refusedBy,
639
+ credits: ceilingUsd === null ? null : publicAssistCredits(costUsd, ceilingUsd)
640
+ };
641
+ }
642
+ /**
643
+ * Hand a reservation back when the provider was never reached (AGL-2057): an
644
+ * upstream 502 spent no tokens, so it must not spend one of a free
645
+ * workspace's ten messages a day either.
646
+ *
647
+ * Released against the keys the RESERVATION recorded — see
648
+ * `AssistReservation`. Each counter is read first so neither can be driven
649
+ * below zero, even if the same reservation were released twice: a negative
650
+ * counter is extra capacity, and the release path must not become the
651
+ * laundering route the reservation was added to close.
652
+ */ export async function releaseAssistMessage(firestore, orgId, reservation) {
653
+ var _reservation_free;
654
+ if (!reservation.allowed) return;
655
+ const increment = FieldValue.increment;
656
+ const orgRef = firestore.collection('orgs').doc(orgId);
657
+ const dailyRef = orgRef.collection('counters').doc('assistMessagesDaily');
658
+ const monthlyRef = orgRef.collection('assistUsage').doc(reservation.monthKey);
659
+ // The account's request goes back with the org's message (AGL-2925) —
660
+ // against the same keys, read first for the same reason.
661
+ const accountRef = ((_reservation_free = reservation.free) == null ? void 0 : _reservation_free.accountUid) ? freeAccountUsageRef(firestore, reservation.free.accountUid, reservation.monthKey) : null;
662
+ await firestore.runTransaction(async (tx)=>{
663
+ var _dailySnapshot_get, _monthlySnapshot_get;
664
+ const dailySnapshot = await tx.get(dailyRef);
665
+ const monthlySnapshot = await tx.get(monthlyRef);
666
+ const accountSnapshot = accountRef ? await tx.get(accountRef) : null;
667
+ if (Number((_dailySnapshot_get = dailySnapshot.get(reservation.dayKey)) != null ? _dailySnapshot_get : 0) > 0) {
668
+ tx.set(dailyRef, {
669
+ [reservation.dayKey]: increment(-1)
670
+ }, {
671
+ merge: true
672
+ });
673
+ }
674
+ if (Number((_monthlySnapshot_get = monthlySnapshot.get('messages')) != null ? _monthlySnapshot_get : 0) > 0) {
675
+ tx.set(monthlyRef, {
676
+ messages: increment(-1)
677
+ }, {
678
+ merge: true
679
+ });
680
+ }
681
+ if (accountRef && accountSnapshot) {
682
+ var _accountSnapshot_get, _ref, _accountSnapshot_get1;
683
+ var _days_reservation_dayKey;
684
+ const days = (_accountSnapshot_get = accountSnapshot.get('days')) != null ? _accountSnapshot_get : {};
685
+ const today = Number((_ref = (_days_reservation_dayKey = days[reservation.dayKey]) == null ? void 0 : _days_reservation_dayKey.requests) != null ? _ref : 0);
686
+ const month = Number((_accountSnapshot_get1 = accountSnapshot.get('requests')) != null ? _accountSnapshot_get1 : 0);
687
+ if (today > 0 || month > 0) {
688
+ tx.set(accountRef, _extends({}, month > 0 ? {
689
+ requests: increment(-1)
690
+ } : {}, today > 0 ? {
691
+ days: {
692
+ [reservation.dayKey]: {
693
+ requests: increment(-1)
694
+ }
695
+ }
696
+ } : {}), {
697
+ merge: true
698
+ });
699
+ }
700
+ }
701
+ });
702
+ }
703
+ /**
704
+ * READ-ONLY view of where an org stands against its cap.
705
+ *
706
+ * ⚠️ NOT the enforcement path any more (AGL-2057) — `reserveAssistMessage` is.
707
+ * A read that is followed by a separate write is exactly the shape that let
708
+ * concurrent requests and abandoned streams past the cap; this function is
709
+ * kept for reporting and for tests that want the standing without consuming a
710
+ * message. **Anything that decides whether to call the model must reserve.**
711
+ *
712
+ * Free orgs meter per UTC day; entitled orgs carry the monthly runaway guard.
713
+ */ export async function checkAssistQuota(firestore, orgId, entitled, now = new Date()) {
714
+ var _snapshot_get;
715
+ if (entitled) {
716
+ var _snapshot_get1;
717
+ const limit = assistEntitledMonthlyLimit();
718
+ const month = assistUsageMonth(now);
719
+ const snapshot = await firestore.collection('orgs').doc(orgId).collection('assistUsage').doc(month).get();
720
+ const used = Number((_snapshot_get1 = snapshot.get('messages')) != null ? _snapshot_get1 : 0);
721
+ return {
722
+ allowed: used < limit,
723
+ period: 'month',
724
+ used,
725
+ limit,
726
+ remaining: Math.max(0, limit - used)
727
+ };
728
+ }
729
+ const limit = assistFreeDailyLimit();
730
+ const day = assistUsageDay(now);
731
+ const snapshot = await firestore.collection('orgs').doc(orgId).collection('counters').doc('assistMessagesDaily').get();
732
+ const used = Number((_snapshot_get = snapshot.get(day)) != null ? _snapshot_get : 0);
733
+ return {
734
+ allowed: used < limit,
735
+ period: 'day',
736
+ used,
737
+ limit,
738
+ remaining: Math.max(0, limit - used)
739
+ };
740
+ }
741
+ /**
742
+ * The signal document and the monthly cost rollup — the two writes every
743
+ * assist turn owes regardless of whether its prose is kept. Shared by
744
+ * `recordAssistExchange` and `recordAssistCost` so the meter has exactly one
745
+ * writer and the two entrypoints can never drift into reporting different
746
+ * money for the same tokens.
747
+ */ function writeSignalAndRollup(firestore, batch, orgRef, signalRef, record, now, /** What the request was for, as the caller's own rollup names it. */ kind) {
748
+ var _record_free, _record_hostId;
749
+ const increment = FieldValue.increment;
750
+ const serverTimestamp = FieldValue.serverTimestamp;
751
+ const estCostUsd = estimateAssistCostUsd(record.usage, record.model);
752
+ // What the same tokens COST US (AGL-3015). Recorded beside the billed
753
+ // figure rather than derived from it later: a month is a sum over models
754
+ // and a markup lives on the model, so once the exchanges are added up the
755
+ // mix is gone and the two can no longer be told apart.
756
+ const providerCostUsd = estimateAssistProviderCostUsd(record.usage, record.model);
757
+ const deflected = record.deflected === true;
758
+ const free = (_record_free = record.free) != null ? _record_free : null;
759
+ // On the Free taste a `refusal` stop draws no credits (AGL-2925): the
760
+ // org's band and the account's allowance stay where they were, and the
761
+ // cost goes to the platform's day instead, where it is still our money.
762
+ // Everywhere else the tokens are metered as they always were.
763
+ const refusedFree = free !== null && record.stopReason === 'refusal';
764
+ // The site's credits for its allotment (AGL-2942), rounded as the person's
765
+ // own `byHost` rounds them, so a site's month equals the sum of its
766
+ // people's months on it. Not zeroed for a declined Free turn, for the same
767
+ // reason the person's month is not: the site did spend it.
768
+ const hostId = String((_record_hostId = record.hostId) != null ? _record_hostId : '').trim();
769
+ const hostCredits = hostId ? assistCreditsFromUsd(estCostUsd) : 0;
770
+ // The analytic half. No prose and NO uid — deliberately, because a signal
771
+ // row that names the asker is just the exchange with the words removed,
772
+ // and would re-create as an access-request obligation exactly what the
773
+ // expiry was meant to retire. What survives answers "which docs gaps, at
774
+ // what cost, rated how", which is the whole of the data loop.
775
+ batch.set(signalRef, _extends({
776
+ route: record.route,
777
+ hostId: record.hostId,
778
+ model: record.model,
779
+ tier: record.tier,
780
+ kind,
781
+ inputTokens: record.usage.inputTokens,
782
+ outputTokens: record.usage.outputTokens,
783
+ cacheReadTokens: record.usage.cacheReadTokens,
784
+ cacheWriteTokens: record.usage.cacheWriteTokens,
785
+ estCostUsd,
786
+ [ASSIST_PROVIDER_COST_FIELD]: providerCostUsd,
787
+ docsPaths: record.docsPaths,
788
+ stopReason: record.stopReason,
789
+ deflected,
790
+ feedback: null
791
+ }, record.editOps && record.editOps > 0 ? {
792
+ editOps: Math.floor(record.editOps)
793
+ } : {}, {
794
+ createdAt: serverTimestamp()
795
+ }));
796
+ // NO message counting here (AGL-2057). Both message counters are moved by
797
+ // `reserveAssistMessage`, BEFORE the provider is called — which is what
798
+ // makes the cap a cap. Counting again here would double every message, and
799
+ // more importantly would restore the belief that this is where the cap
800
+ // advances: it is not, and an exchange that never reaches this function
801
+ // (an abandoned stream) has already been counted.
802
+ batch.set(orgRef.collection('assistUsage').doc(assistUsageMonth(now)), _extends({
803
+ month: assistUsageMonth(now),
804
+ // The free half of the month, counted where the paid half already is
805
+ // (AGL-2486). `messages` counts what the RESERVATION moved — model
806
+ // turns — and a deflected turn takes no reservation because it spends
807
+ // nothing, so without this counter the questions Assist answered for
808
+ // free are invisible and the deflection rate can only be guessed at.
809
+ // Total questions asked is `messages + deflected`; neither field alone
810
+ // is that number, and reading `messages` as it would understate usage
811
+ // by exactly the amount this work was done to create.
812
+ deflected: increment(deflected ? 1 : 0),
813
+ inputTokens: increment(record.usage.inputTokens),
814
+ outputTokens: increment(record.usage.outputTokens),
815
+ cacheReadTokens: increment(record.usage.cacheReadTokens),
816
+ cacheWriteTokens: increment(record.usage.cacheWriteTokens),
817
+ estCostUsd: increment(refusedFree ? 0 : estCostUsd),
818
+ // Our bill for the same turns, credited and refused alike on the same
819
+ // rule as `estCostUsd` above, so the month's two dollar figures always
820
+ // describe the same set of exchanges and a margin taken across them is
821
+ // a margin over one period.
822
+ [ASSIST_PROVIDER_COST_FIELD]: increment(refusedFree ? 0 : providerCostUsd),
823
+ // The refused half of a Free month, kept beside the credited half so
824
+ // the rollup still says what the month cost us in total. Its own field
825
+ // name (AGL-2986): `refusals` on this document is the gate's map of
826
+ // refusal counts by reason (`recordAssistRefusal`), and an increment
827
+ // over a map replaces the map with the operand.
828
+ refusedTurns: increment(refusedFree ? 1 : 0),
829
+ refusedCostUsd: increment(refusedFree ? estCostUsd : 0)
830
+ }, deflected ? {} : {
831
+ [AI_USAGE_MONTH_KINDS_FIELD]: {
832
+ [kind]: {
833
+ requests: increment(1),
834
+ estCostUsd: increment(estCostUsd),
835
+ [ASSIST_PROVIDER_COST_FIELD]: increment(providerCostUsd),
836
+ [AI_USAGE_TOKENS_FIELD]: aiTokenIncrements(record.usage)
837
+ }
838
+ }
839
+ }, hostCredits > 0 ? {
840
+ [AI_HOST_CREDITS_FIELD]: {
841
+ [hostId]: increment(hostCredits)
842
+ }
843
+ } : {}, {
844
+ updatedAt: serverTimestamp()
845
+ }), {
846
+ merge: true
847
+ });
848
+ if (free) {
849
+ const day = assistUsageDay(now);
850
+ const writes = freeTasteMeterWrites({
851
+ estCostUsd,
852
+ refused: refusedFree,
853
+ day,
854
+ month: assistUsageMonth(now)
855
+ });
856
+ batch.set(platformFreeSpendRef(firestore, day), writes.platform, {
857
+ merge: true
858
+ });
859
+ if (free.accountUid) {
860
+ batch.set(freeAccountUsageRef(firestore, free.accountUid, assistUsageMonth(now)), writes.account, {
861
+ merge: true
862
+ });
863
+ }
864
+ }
865
+ }
866
+ /**
867
+ * After a Free turn's batch commits: the ceiling's announcements, which
868
+ * need the figure the batch just moved and must never fail the turn.
869
+ */ async function announceFreeTurn(firestore, record, now) {
870
+ if (!record.free) return;
871
+ await announcePlatformFreeSpend(firestore, assistUsageDay(now)).catch((error)=>console.error('[ai-free-spend] announcement failed', error));
872
+ }
873
+ /**
874
+ * Meter one assist turn that keeps NO verbatim record (AGL-2073) — the
875
+ * besigner copy assistant at `/api/ai/assist`.
876
+ *
877
+ * Writes the signal and folds tokens/cost into the monthly rollup, and writes
878
+ * nothing to `assistExchanges`. Same reason the console route splits the two:
879
+ * the loop's corpus was never the words. Here there is no loop to feed and no
880
+ * thumbs to collect, so the words are simply not taken.
881
+ *
882
+ * Like `recordAssistExchange` it counts NO message — the reservation did that
883
+ * before the tokens were spent. Callers should not let a metering failure fail
884
+ * the request: the tokens are already spent either way, and refusing the
885
+ * answer the customer paid for would make an accounting problem a product one.
886
+ */ export async function recordAssistCost(firestore, orgId, record, now = new Date()) {
887
+ var _record_kind;
888
+ const orgRef = firestore.collection('orgs').doc(orgId);
889
+ const signalRef = orgRef.collection('assistSignals').doc();
890
+ const batch = firestore.batch();
891
+ const kind = (_record_kind = record.kind) != null ? _record_kind : aiUsageKindFromRoute(record.route);
892
+ writeSignalAndRollup(firestore, batch, orgRef, signalRef, record, now, kind);
893
+ // The person's month, on the SAME batch as the org's (AGL-2928), so the
894
+ // two rollups commit together or not at all.
895
+ recordUserAiUsage(batch, orgRef, {
896
+ uid: record.uid,
897
+ month: assistUsageMonth(now),
898
+ estCostUsd: estimateAssistCostUsd(record.usage, record.model),
899
+ hostId: record.hostId,
900
+ kind,
901
+ usage: record.usage
902
+ });
903
+ await batch.commit();
904
+ chargeAccruedOverage(firestore, orgId, assistUsageMonth(now), now);
905
+ await announceFreeTurn(firestore, record, now);
906
+ return signalRef.id;
907
+ }
908
+ /**
909
+ * The data loop + meters, one batch: writes the two halves of the exchange
910
+ * and folds tokens/cost into the monthly usage doc. It does NOT count the
911
+ * message — `reserveAssistMessage` already did, before the tokens were spent.
912
+ * Returns the shared id (the feedback route addresses it later). Callers
913
+ * `await` this — an exchange that fails to record should surface in logs,
914
+ * but the batch is one round trip so it does not add meaningful latency.
915
+ *
916
+ * The two halves share one id ON PURPOSE. It is what lets the feedback route
917
+ * keep its single-id signature, and it is what makes an exchange and its
918
+ * signal joinable for as long as both exist — without storing a second
919
+ * pointer that could rot.
920
+ */ export async function recordAssistExchange(firestore, orgId, record, now = new Date()) {
921
+ var _record_kind;
922
+ const serverTimestamp = FieldValue.serverTimestamp;
923
+ const orgRef = firestore.collection('orgs').doc(orgId);
924
+ const exchangeRef = orgRef.collection('assistExchanges').doc();
925
+ const signalRef = orgRef.collection('assistSignals').doc(exchangeRef.id);
926
+ const batch = firestore.batch();
927
+ // The personal half. Everything a person typed, everything we said back,
928
+ // and who asked — and nothing else. Expires.
929
+ batch.set(exchangeRef, {
930
+ uid: record.uid,
931
+ question: record.question,
932
+ answer: record.answer,
933
+ hostId: record.hostId,
934
+ createdAt: serverTimestamp(),
935
+ expiresAt: assistExchangeExpiry(now)
936
+ });
937
+ // A chat turn is an `assist` request whatever console route it was asked
938
+ // from — on the signal, the org's month and the asker's month alike.
939
+ const kind = (_record_kind = record.kind) != null ? _record_kind : 'assist';
940
+ // The analytic half plus the meters — the same writer `recordAssistCost`
941
+ // uses, so the two assist entrypoints can never report different money for
942
+ // the same tokens.
943
+ writeSignalAndRollup(firestore, batch, orgRef, signalRef, record, now, kind);
944
+ // And the asker's month, on the same batch (AGL-2928).
945
+ recordUserAiUsage(batch, orgRef, {
946
+ uid: record.uid,
947
+ month: assistUsageMonth(now),
948
+ estCostUsd: estimateAssistCostUsd(record.usage, record.model),
949
+ hostId: record.hostId,
950
+ kind,
951
+ usage: record.usage
952
+ });
953
+ await batch.commit();
954
+ chargeAccruedOverage(firestore, orgId, assistUsageMonth(now), now);
955
+ await announceFreeTurn(firestore, record, now);
956
+ return exchangeRef.id;
957
+ }
958
+ /**
959
+ * Record explicit thumbs feedback on an exchange. Only the exchange's own
960
+ * org path is addressable, and only the two literal values are accepted —
961
+ * the route validates membership before calling this.
962
+ *
963
+ * The rating lands on the SIGNAL document, not the exchange (AGL-1972). A
964
+ * thumbs-down is the single most valuable row in the data loop and it is not
965
+ * personal content, so it must not be reaped along with the prose that
966
+ * earned it. Existence is checked on the signal too: it is the document
967
+ * being written, and after the exchange expires it is the only one left.
968
+ */ export async function recordAssistFeedback(firestore, orgId, exchangeId, feedback) {
969
+ const ref = firestore.collection('orgs').doc(orgId).collection('assistSignals').doc(exchangeId);
970
+ const snapshot = await ref.get();
971
+ if (!snapshot.exists) return false;
972
+ await ref.update({
973
+ feedback
974
+ });
975
+ return true;
976
+ }
977
+
978
+ //# sourceMappingURL=assist-usage.js.map