@aglyn/plugins-ai 1.0.0-beta.218 → 1.0.0-beta.220

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 (311) hide show
  1. package/README.md +2 -2
  2. package/package.json +18 -18
  3. package/src/index.d.ts +1 -0
  4. package/src/index.js.map +1 -1
  5. package/src/lib/activity/ai-activity-actions.js +8 -1
  6. package/src/lib/activity/ai-activity-actions.js.map +1 -1
  7. package/src/lib/billing/ai-month-meter.d.ts +51 -0
  8. package/src/lib/billing/ai-month-meter.js +89 -0
  9. package/src/lib/billing/ai-month-meter.js.map +1 -0
  10. package/src/lib/billing/ai-overage-close.d.ts +11 -33
  11. package/src/lib/billing/ai-overage-close.js +4 -3
  12. package/src/lib/billing/ai-overage-close.js.map +1 -1
  13. package/src/lib/billing/ai-overage-cutover.d.ts +28 -12
  14. package/src/lib/billing/ai-overage-cutover.js +1 -28
  15. package/src/lib/billing/ai-overage-cutover.js.map +1 -1
  16. package/src/lib/billing/ai-overage-ledger.js +1 -1
  17. package/src/lib/billing/ai-overage-ledger.js.map +1 -1
  18. package/src/lib/billing/ai-overage-standing.js +1 -1
  19. package/src/lib/billing/ai-overage-standing.js.map +1 -1
  20. package/src/lib/components/ai-allotment-editor.component.js +1 -1
  21. package/src/lib/components/ai-allotment-editor.component.js.map +1 -1
  22. package/src/lib/components/ai-assist-provider.component.js +5 -4
  23. package/src/lib/components/ai-assist-provider.component.js.map +1 -1
  24. package/src/lib/components/ai-automation-zones.d.ts +63 -0
  25. package/src/lib/components/ai-automation-zones.js +31 -0
  26. package/src/lib/components/ai-automation-zones.js.map +1 -0
  27. package/src/lib/components/ai-brief-dialog.component.js +3 -3
  28. package/src/lib/components/ai-brief-dialog.component.js.map +1 -1
  29. package/src/lib/components/ai-describe-automation.component.d.ts +1 -1
  30. package/src/lib/components/ai-describe-automation.component.js.map +1 -1
  31. package/src/lib/components/ai-describe-button.component.d.ts +6 -3
  32. package/src/lib/components/ai-describe-button.component.js +4 -1
  33. package/src/lib/components/ai-describe-button.component.js.map +1 -1
  34. package/src/lib/components/ai-experiment-cards.component.js +1 -1
  35. package/src/lib/components/ai-experiment-cards.component.js.map +1 -1
  36. package/src/lib/components/ai-explain-automation.component.d.ts +1 -1
  37. package/src/lib/components/ai-explain-automation.component.js.map +1 -1
  38. package/src/lib/components/ai-job-plan.component.d.ts +8 -0
  39. package/src/lib/components/ai-job-plan.component.js +21 -4
  40. package/src/lib/components/ai-job-plan.component.js.map +1 -1
  41. package/src/lib/components/ai-permissions-on-host.component.d.ts +12 -2
  42. package/src/lib/components/ai-permissions-on-host.component.js +12 -3
  43. package/src/lib/components/ai-permissions-on-host.component.js.map +1 -1
  44. package/src/lib/components/ai-product-copy-card.component.d.ts +1 -1
  45. package/src/lib/components/ai-product-copy-card.component.js.map +1 -1
  46. package/src/lib/components/ai-product-import-option.component.d.ts +1 -1
  47. package/src/lib/components/ai-product-import-option.component.js.map +1 -1
  48. package/src/lib/components/ai-product-zones.d.ts +124 -0
  49. package/src/lib/components/ai-product-zones.js +32 -0
  50. package/src/lib/components/ai-product-zones.js.map +1 -0
  51. package/src/lib/components/ai-products-hub-card.component.d.ts +1 -1
  52. package/src/lib/components/ai-products-hub-card.component.js.map +1 -1
  53. package/src/lib/components/ai-products-proposals.component.d.ts +1 -1
  54. package/src/lib/components/ai-products-proposals.component.js.map +1 -1
  55. package/src/lib/components/ai-seo-audit-card.component.js +35 -92
  56. package/src/lib/components/ai-seo-audit-card.component.js.map +1 -1
  57. package/src/lib/components/ai-seo-fields-card.component.js.map +1 -1
  58. package/src/lib/components/ai-theme-proposal-card.component.js.map +1 -1
  59. package/src/lib/components/assist-jobs-drawer.component.js +21 -15
  60. package/src/lib/components/assist-jobs-drawer.component.js.map +1 -1
  61. package/src/lib/components/assist-panel.component.js +2 -2
  62. package/src/lib/components/assist-panel.component.js.map +1 -1
  63. package/src/lib/components/assist-signals-page.component.js +2 -2
  64. package/src/lib/components/assist-signals-page.component.js.map +1 -1
  65. package/src/lib/components/billing-ai-allotments.component.js +1 -1
  66. package/src/lib/components/billing-ai-allotments.component.js.map +1 -1
  67. package/src/lib/components/billing-assist-overage-card.component.js +1 -1
  68. package/src/lib/components/billing-assist-overage-card.component.js.map +1 -1
  69. package/src/lib/constants.d.ts +5 -0
  70. package/src/lib/constants.js +4 -0
  71. package/src/lib/constants.js.map +1 -1
  72. package/src/lib/declarations.js +2 -0
  73. package/src/lib/declarations.js.map +1 -1
  74. package/src/lib/declarations.server.js +24 -10
  75. package/src/lib/declarations.server.js.map +1 -1
  76. package/src/lib/insights/ai-dataset-catalog.d.ts +49 -0
  77. package/src/lib/insights/ai-dataset-catalog.js +57 -0
  78. package/src/lib/insights/ai-dataset-catalog.js.map +1 -0
  79. package/src/lib/insights/ai-figure-readers.d.ts +6 -39
  80. package/src/lib/insights/ai-figure-readers.js +2 -391
  81. package/src/lib/insights/ai-figure-readers.js.map +1 -1
  82. package/src/lib/insights/ai-insight-digest.d.ts +10 -1
  83. package/src/lib/insights/ai-insight-digest.js +16 -4
  84. package/src/lib/insights/ai-insight-digest.js.map +1 -1
  85. package/src/lib/insights/ai-insight-readers.d.ts +1 -1
  86. package/src/lib/insights/ai-insight-readers.js.map +1 -1
  87. package/src/lib/jobs/ai-email-bindings.d.ts +28 -21
  88. package/src/lib/jobs/ai-email-bindings.js +75 -42
  89. package/src/lib/jobs/ai-email-bindings.js.map +1 -1
  90. package/src/lib/jobs/ai-job-campaign-step.d.ts +0 -2
  91. package/src/lib/jobs/ai-job-campaign-step.js +5 -10
  92. package/src/lib/jobs/ai-job-campaign-step.js.map +1 -1
  93. package/src/lib/jobs/ai-job-component-step.d.ts +6 -1
  94. package/src/lib/jobs/ai-job-component-step.js +32 -9
  95. package/src/lib/jobs/ai-job-component-step.js.map +1 -1
  96. package/src/lib/jobs/ai-job-draft-ids.js +11 -0
  97. package/src/lib/jobs/ai-job-draft-ids.js.map +1 -1
  98. package/src/lib/jobs/ai-job-drafts.js +1 -1
  99. package/src/lib/jobs/ai-job-drafts.js.map +1 -1
  100. package/src/lib/jobs/ai-job-email-step.d.ts +5 -3
  101. package/src/lib/jobs/ai-job-email-step.js +11 -4
  102. package/src/lib/jobs/ai-job-email-step.js.map +1 -1
  103. package/src/lib/jobs/ai-job-experiment-step.d.ts +1 -1
  104. package/src/lib/jobs/ai-job-experiment-step.js +1 -1
  105. package/src/lib/jobs/ai-job-experiment-step.js.map +1 -1
  106. package/src/lib/jobs/ai-job-form-step.d.ts +17 -1
  107. package/src/lib/jobs/ai-job-form-step.js +60 -8
  108. package/src/lib/jobs/ai-job-form-step.js.map +1 -1
  109. package/src/lib/jobs/ai-job-generation.d.ts +22 -1
  110. package/src/lib/jobs/ai-job-generation.js +63 -3
  111. package/src/lib/jobs/ai-job-generation.js.map +1 -1
  112. package/src/lib/jobs/ai-job-insight-step.js +1 -1
  113. package/src/lib/jobs/ai-job-insight-step.js.map +1 -1
  114. package/src/lib/jobs/ai-job-layout-step.d.ts +15 -4
  115. package/src/lib/jobs/ai-job-layout-step.js +46 -13
  116. package/src/lib/jobs/ai-job-layout-step.js.map +1 -1
  117. package/src/lib/jobs/ai-job-page-sections.d.ts +4 -2
  118. package/src/lib/jobs/ai-job-page-sections.js +7 -4
  119. package/src/lib/jobs/ai-job-page-sections.js.map +1 -1
  120. package/src/lib/jobs/ai-job-page-step.js +7 -2
  121. package/src/lib/jobs/ai-job-page-step.js.map +1 -1
  122. package/src/lib/jobs/ai-job-plan-conformance.d.ts +5 -0
  123. package/src/lib/jobs/ai-job-plan-conformance.js +40 -1
  124. package/src/lib/jobs/ai-job-plan-conformance.js.map +1 -1
  125. package/src/lib/jobs/ai-job-plan-creations.d.ts +80 -0
  126. package/src/lib/jobs/ai-job-plan-creations.js +199 -0
  127. package/src/lib/jobs/ai-job-plan-creations.js.map +1 -0
  128. package/src/lib/jobs/ai-job-plan-step.d.ts +11 -2
  129. package/src/lib/jobs/ai-job-plan-step.js +49 -23
  130. package/src/lib/jobs/ai-job-plan-step.js.map +1 -1
  131. package/src/lib/jobs/ai-job-plugin-drafts.d.ts +14 -6
  132. package/src/lib/jobs/ai-job-plugin-drafts.js +12 -4
  133. package/src/lib/jobs/ai-job-plugin-drafts.js.map +1 -1
  134. package/src/lib/jobs/ai-job-products-step.d.ts +7 -0
  135. package/src/lib/jobs/ai-job-products-step.js +54 -32
  136. package/src/lib/jobs/ai-job-products-step.js.map +1 -1
  137. package/src/lib/jobs/ai-job-seo-step.d.ts +3 -24
  138. package/src/lib/jobs/ai-job-seo-step.js +35 -108
  139. package/src/lib/jobs/ai-job-seo-step.js.map +1 -1
  140. package/src/lib/jobs/ai-job-site-step.d.ts +2 -0
  141. package/src/lib/jobs/ai-job-site-step.js +6 -6
  142. package/src/lib/jobs/ai-job-site-step.js.map +1 -1
  143. package/src/lib/jobs/ai-job-template-step.d.ts +9 -6
  144. package/src/lib/jobs/ai-job-template-step.js +73 -15
  145. package/src/lib/jobs/ai-job-template-step.js.map +1 -1
  146. package/src/lib/jobs/ai-job-theme-step.d.ts +1 -1
  147. package/src/lib/jobs/ai-job-theme-step.js +1 -1
  148. package/src/lib/jobs/ai-job-theme-step.js.map +1 -1
  149. package/src/lib/jobs/ai-job-workflow-step.js +17 -9
  150. package/src/lib/jobs/ai-job-workflow-step.js.map +1 -1
  151. package/src/lib/jobs/ai-jobs.js +1 -1
  152. package/src/lib/jobs/ai-jobs.js.map +1 -1
  153. package/src/lib/jobs/ai-workflow-records.d.ts +20 -11
  154. package/src/lib/jobs/ai-workflow-records.js +80 -43
  155. package/src/lib/jobs/ai-workflow-records.js.map +1 -1
  156. package/src/lib/model/ai-allotments.d.ts +27 -6
  157. package/src/lib/model/ai-allotments.js +54 -14
  158. package/src/lib/model/ai-allotments.js.map +1 -1
  159. package/src/lib/model/ai-automation-outline.d.ts +21 -2
  160. package/src/lib/model/ai-automation-outline.js.map +1 -1
  161. package/src/lib/model/ai-build-plan.d.ts +57 -0
  162. package/src/lib/model/ai-build-plan.js +116 -7
  163. package/src/lib/model/ai-build-plan.js.map +1 -1
  164. package/src/lib/model/ai-job-creations.d.ts +55 -0
  165. package/src/lib/model/ai-job-creations.js +85 -0
  166. package/src/lib/model/ai-job-creations.js.map +1 -0
  167. package/src/lib/model/ai-page-job.d.ts +3 -2
  168. package/src/lib/model/ai-page-job.js +4 -3
  169. package/src/lib/model/ai-page-job.js.map +1 -1
  170. package/src/lib/model/ai-seo.d.ts +11 -51
  171. package/src/lib/model/ai-seo.js +0 -17
  172. package/src/lib/model/ai-seo.js.map +1 -1
  173. package/src/lib/model/ai-site-inventory.js +1 -1
  174. package/src/lib/model/ai-site-inventory.js.map +1 -1
  175. package/src/lib/model/ai-site-job.d.ts +4 -2
  176. package/src/lib/model/ai-site-job.js +8 -4
  177. package/src/lib/model/ai-site-job.js.map +1 -1
  178. package/src/lib/model/ai-template-subjects.d.ts +10 -0
  179. package/src/lib/model/ai-template-subjects.js +16 -2
  180. package/src/lib/model/ai-template-subjects.js.map +1 -1
  181. package/src/lib/model/ai-theme-proposal.d.ts +1 -1
  182. package/src/lib/model/ai-theme-proposal.js +1 -1
  183. package/src/lib/model/ai-theme-proposal.js.map +1 -1
  184. package/src/lib/model/ai-tokens.js +1 -1
  185. package/src/lib/model/ai-tokens.js.map +1 -1
  186. package/src/lib/model/ai-usage-by-user.js +1 -1
  187. package/src/lib/model/ai-usage-by-user.js.map +1 -1
  188. package/src/lib/model/ai-workflow-job.d.ts +1 -3
  189. package/src/lib/model/ai-workflow-job.js +1 -2
  190. package/src/lib/model/ai-workflow-job.js.map +1 -1
  191. package/src/lib/plan-entitlements.d.ts +149 -0
  192. package/src/lib/plan-entitlements.js +168 -0
  193. package/src/lib/plan-entitlements.js.map +1 -0
  194. package/src/lib/plugin.js +1 -1
  195. package/src/lib/plugin.js.map +1 -1
  196. package/src/lib/providers/catalog.js +1 -1
  197. package/src/lib/providers/catalog.js.map +1 -1
  198. package/src/lib/providers/model-choice.js +1 -1
  199. package/src/lib/providers/model-choice.js.map +1 -1
  200. package/src/lib/runtime/ai-device-audit.d.ts +1 -1
  201. package/src/lib/runtime/ai-device-audit.js +1 -1
  202. package/src/lib/runtime/ai-device-audit.js.map +1 -1
  203. package/src/lib/runtime/ai-doctrine-validators.d.ts +25 -4
  204. package/src/lib/runtime/ai-doctrine-validators.js +178 -21
  205. package/src/lib/runtime/ai-doctrine-validators.js.map +1 -1
  206. package/src/lib/runtime/ai-doctrine.js +5 -5
  207. package/src/lib/runtime/ai-doctrine.js.map +1 -1
  208. package/src/lib/runtime/ai-eval-live.js +30 -15
  209. package/src/lib/runtime/ai-eval-live.js.map +1 -1
  210. package/src/lib/runtime/ai-eval.d.ts +9 -2
  211. package/src/lib/runtime/ai-eval.js +29 -2
  212. package/src/lib/runtime/ai-eval.js.map +1 -1
  213. package/src/lib/runtime/ai-gate.js +1 -1
  214. package/src/lib/runtime/ai-gate.js.map +1 -1
  215. package/src/lib/runtime/ai-node-tree.js +3 -3
  216. package/src/lib/runtime/ai-node-tree.js.map +1 -1
  217. package/src/lib/runtime/ai-palette.d.ts +7 -1
  218. package/src/lib/runtime/ai-palette.generated.d.ts +1 -1
  219. package/src/lib/runtime/ai-palette.generated.js +16 -13
  220. package/src/lib/runtime/ai-palette.generated.js.map +1 -1
  221. package/src/lib/runtime/ai-palette.js +7 -1
  222. package/src/lib/runtime/ai-palette.js.map +1 -1
  223. package/src/lib/runtime/seo-audit.d.ts +13 -63
  224. package/src/lib/runtime/seo-audit.js +22 -207
  225. package/src/lib/runtime/seo-audit.js.map +1 -1
  226. package/src/lib/runtime/site-inventory.js +29 -23
  227. package/src/lib/runtime/site-inventory.js.map +1 -1
  228. package/src/lib/server/ai-admin-org.js +1 -1
  229. package/src/lib/server/ai-admin-org.js.map +1 -1
  230. package/src/lib/server/ai-admin-orgs-spend.js +1 -1
  231. package/src/lib/server/ai-admin-orgs-spend.js.map +1 -1
  232. package/src/lib/server/ai-admin-signals.js +1 -1
  233. package/src/lib/server/ai-admin-signals.js.map +1 -1
  234. package/src/lib/server/ai-allotments.js +1 -1
  235. package/src/lib/server/ai-allotments.js.map +1 -1
  236. package/src/lib/server/ai-assist-prompts.js +3 -3
  237. package/src/lib/server/ai-assist-prompts.js.map +1 -1
  238. package/src/lib/server/ai-assist.js +2 -2
  239. package/src/lib/server/ai-assist.js.map +1 -1
  240. package/src/lib/server/assist-chat.d.ts +1 -1
  241. package/src/lib/server/assist-chat.js +13 -12
  242. package/src/lib/server/assist-chat.js.map +1 -1
  243. package/src/lib/server/assist-view-context.js +23 -23
  244. package/src/lib/server/assist-view-context.js.map +1 -1
  245. package/src/lib/server/billing-credits.d.ts +5 -0
  246. package/src/lib/server/billing-credits.js +8 -2
  247. package/src/lib/server/billing-credits.js.map +1 -1
  248. package/src/lib/server/billing-overage.js +2 -2
  249. package/src/lib/server/billing-overage.js.map +1 -1
  250. package/src/lib/server.d.ts +1 -0
  251. package/src/lib/server.js.map +1 -1
  252. package/src/lib/testing/stand-in-automation-index.d.ts +20 -0
  253. package/src/lib/testing/stand-in-automation-index.js +102 -0
  254. package/src/lib/testing/stand-in-automation-index.js.map +1 -0
  255. package/src/lib/testing/stand-in-dataset-index.d.ts +20 -0
  256. package/src/lib/testing/stand-in-dataset-index.js +80 -0
  257. package/src/lib/testing/stand-in-dataset-index.js.map +1 -0
  258. package/src/lib/testing/stand-in-list-send-time.d.ts +4 -0
  259. package/src/lib/testing/stand-in-list-send-time.js +77 -0
  260. package/src/lib/testing/stand-in-list-send-time.js.map +1 -0
  261. package/src/lib/testing/stand-in-pipeline-index.d.ts +32 -0
  262. package/src/lib/testing/stand-in-pipeline-index.js +59 -0
  263. package/src/lib/testing/stand-in-pipeline-index.js.map +1 -0
  264. package/src/lib/testing/stand-in-product-index.d.ts +20 -0
  265. package/src/lib/testing/stand-in-product-index.js +105 -0
  266. package/src/lib/testing/stand-in-product-index.js.map +1 -0
  267. package/src/lib/tools/ai-component-tool.js +2 -2
  268. package/src/lib/tools/ai-component-tool.js.map +1 -1
  269. package/src/lib/tools/ai-duplicate-resource-tool.js +1 -1
  270. package/src/lib/tools/ai-duplicate-resource-tool.js.map +1 -1
  271. package/src/lib/tools/ai-seo-tool.d.ts +6 -18
  272. package/src/lib/tools/ai-seo-tool.js +7 -38
  273. package/src/lib/tools/ai-seo-tool.js.map +1 -1
  274. package/src/lib/tools/ai-workflow-tool.d.ts +1 -1
  275. package/src/lib/tools/ai-workflow-tool.js +1 -1
  276. package/src/lib/tools/ai-workflow-tool.js.map +1 -1
  277. package/src/lib/usage/ai-allotment-alerts.d.ts +10 -7
  278. package/src/lib/usage/ai-allotment-alerts.js +39 -15
  279. package/src/lib/usage/ai-allotment-alerts.js.map +1 -1
  280. package/src/lib/usage/ai-quota-checks.d.ts +37 -0
  281. package/src/lib/usage/ai-quota-checks.js +69 -0
  282. package/src/lib/usage/ai-quota-checks.js.map +1 -0
  283. package/src/lib/usage/ai-usage-alerts.js +22 -10
  284. package/src/lib/usage/ai-usage-alerts.js.map +1 -1
  285. package/src/lib/usage/ai-usage-by-user.js +1 -1
  286. package/src/lib/usage/ai-usage-by-user.js.map +1 -1
  287. package/src/lib/usage/assist-ceiling.d.ts +2 -2
  288. package/src/lib/usage/assist-ceiling.js +4 -4
  289. package/src/lib/usage/assist-ceiling.js.map +1 -1
  290. package/src/lib/usage/assist-credits.d.ts +494 -0
  291. package/src/lib/usage/assist-credits.js +524 -0
  292. package/src/lib/usage/assist-credits.js.map +1 -0
  293. package/src/lib/usage/assist-free-taste.d.ts +1 -1
  294. package/src/lib/usage/assist-free-taste.js +3 -2
  295. package/src/lib/usage/assist-free-taste.js.map +1 -1
  296. package/src/lib/usage/assist-signal-mining.js +1 -1
  297. package/src/lib/usage/assist-signal-mining.js.map +1 -1
  298. package/src/lib/usage/assist-spend-guards.d.ts +153 -0
  299. package/src/lib/usage/assist-spend-guards.js +182 -0
  300. package/src/lib/usage/assist-spend-guards.js.map +1 -0
  301. package/src/lib/usage/assist-usage.d.ts +1 -1
  302. package/src/lib/usage/assist-usage.js +1 -1
  303. package/src/lib/usage/assist-usage.js.map +1 -1
  304. package/src/lib/usage/staff-org-ai.js +1 -1
  305. package/src/lib/usage/staff-org-ai.js.map +1 -1
  306. package/src/lib/usage-axes.d.ts +49 -0
  307. package/src/lib/usage-axes.js +108 -0
  308. package/src/lib/usage-axes.js.map +1 -0
  309. package/src/lib/runtime/seo-page-facts.d.ts +0 -61
  310. package/src/lib/runtime/seo-page-facts.js +0 -150
  311. package/src/lib/runtime/seo-page-facts.js.map +0 -1
@@ -0,0 +1,182 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */ /*
17
+ * THE AI PLUGIN'S SPEND GUARDS: the staff review threshold on one
18
+ * workspace's monthly provider spend, the hard ceiling past which its
19
+ * reservations refuse, and the dedupe arithmetic the usage-alerts sweep's
20
+ * contributor announces both with. Pure over configured values and the
21
+ * sweep's guard map, so the meter that refuses and the alert that announces
22
+ * the refusal read one variable and agree on what it means.
23
+ */ /**
24
+ * The MARGIN GUARD.
25
+ *
26
+ * A customer's usage budget (`usage-budget.ts`) protects the customer. This
27
+ * protects the platform, from the one meter whose unit cost is real money
28
+ * paid to a third party and whose ceiling is a message count rather than a
29
+ * dollar figure: `assistEntitledMonthlyLimit` caps an entitled org at 1,000
30
+ * MESSAGES a month, and a thousand long, cache-cold Opus-class exchanges is
31
+ * a three-figure bill against a subscription that did not move.
32
+ *
33
+ * So one org's Assist COGS crossing this threshold notifies STAFF, not the
34
+ * customer — the customer is not being charged and has done nothing wrong.
35
+ * Returns the threshold crossed, or 0.
36
+ *
37
+ * `ASSIST_ORG_MONTHLY_COGS_ALERT_USD` overrides the default and FAILS TO THE
38
+ * DEFAULT: a blank or malformed value that disabled the guard would be
39
+ * another alert that cannot fire.
40
+ */ export const ASSIST_ORG_MONTHLY_COGS_ALERT_USD_DEFAULT = 25;
41
+ export function assistCogsAlertThresholdUsd(configured) {
42
+ const parsed = Number(String(configured != null ? configured : '').trim());
43
+ if (!Number.isFinite(parsed) || parsed <= 0) {
44
+ return ASSIST_ORG_MONTHLY_COGS_ALERT_USD_DEFAULT;
45
+ }
46
+ return parsed;
47
+ }
48
+ /**
49
+ * The repo default spend ceiling: **$40 per org per month** (AGL-2264).
50
+ *
51
+ * The number is arithmetic rather than pricing. After AGL-2441 the
52
+ * 1,000-message entitled guard bounds roughly $28/org/month of worst-case
53
+ * spend at Sonnet, and the staff margin alert already fires at $25. $40
54
+ * therefore sits ABOVE anything the message cap can produce at the current
55
+ * model, so it changes no charged amount and no plan's behaviour — it is a
56
+ * ceiling on OUR cost, not a customer price, which is why it is outside the
57
+ * Sept-1 pricing lock. It binds only when an assumption behind that
58
+ * arithmetic has moved: an `ASSIST_MODEL` swap to an Opus-class tier, a
59
+ * longer prompt, or a caller finding another way to inflate input. That is
60
+ * the failure it exists for.
61
+ *
62
+ * It ships as a DEFAULT rather than as an environment variable someone must
63
+ * remember, because an unset ceiling is the fail-open this issue was opened
64
+ * about: a fresh deployment and a self-hoster both inherit a sane bound
65
+ * without knowing the variable exists.
66
+ *
67
+ * The free tier gets no separate figure and needs none — its 10 messages a
68
+ * UTC day bound it at roughly $0.28/day, so this is a backstop it cannot
69
+ * reach rather than a cap it runs into.
70
+ *
71
+ * ⚠️ It applies only to an org whose plan sells NO assist band. Agency and
72
+ * Enterprise include more assist than $40 of spend, so the meter's
73
+ * `assistMonthlyCeilingUsd` keeps this default off every plan that sells a
74
+ * band — see there for which figure binds when.
75
+ */ export const ASSIST_ORG_MONTHLY_COGS_LIMIT_DEFAULT_USD = 40;
76
+ /**
77
+ * The per-org monthly PROVIDER-SPEND ceiling in USD — the dollar half of
78
+ * the cap (AGL-2264), from `ASSIST_ORG_MONTHLY_COGS_LIMIT_USD` as the caller
79
+ * read it. Defaults to {@link ASSIST_ORG_MONTHLY_COGS_LIMIT_DEFAULT_USD};
80
+ * `off` removes it.
81
+ *
82
+ * Pure over the configured value, like {@link assistCogsAlertThresholdUsd}:
83
+ * the meter that refuses at the ceiling and the cron that announces the
84
+ * refusal read the one variable and must agree on what it means.
85
+ *
86
+ * The meter's message caps bound spend only through an assumed cost per
87
+ * message, and that assumption is exactly what drifts: `ASSIST_MODEL` is an
88
+ * env override, prompts grow, and a client controls how much history it
89
+ * posts. The ceiling is measured against the real figure instead: the
90
+ * running `estCostUsd` on the month's assist usage document, which the meter
91
+ * increments at the SERVING model's rates. So it bounds the actual bill
92
+ * rather than a forecast of it.
93
+ *
94
+ * The refusal is deliberately the same shape as the message refusal (a
95
+ * reservation that did not move the counter), so an org at the ceiling
96
+ * spends nothing at all rather than spending less. It refuses — it does
97
+ * NOT quietly swap to a cheaper model. A silent quality drop is worse than
98
+ * an honest stop, because nobody can tell it happened.
99
+ *
100
+ * ⚠️ **Fails to the DEFAULT, never to “no ceiling”.** An empty, negative or
101
+ * unparseable value reads as unconfigured and takes the repo default, so a
102
+ * typo cannot reopen the fail-open this exists to close. It cannot become a
103
+ * ceiling of `$0` either — a value of zero is not “refuse everyone”, it is
104
+ * “not a number I will honour” — because an outage across every workspace
105
+ * would be worse than the overspend being guarded.
106
+ *
107
+ * Removing the ceiling therefore takes a WORD rather than a number:
108
+ * `ASSIST_ORG_MONTHLY_COGS_LIMIT_USD=off`. A deployment paying its own
109
+ * provider bill may genuinely want none, and that is a decision someone
110
+ * should have to write down rather than reach by mistyping a digit.
111
+ */ export function assistOrgMonthlyCostLimitUsd(configured) {
112
+ const operator = assistOperatorCeilingUsd(configured);
113
+ return operator === undefined ? ASSIST_ORG_MONTHLY_COGS_LIMIT_DEFAULT_USD : operator;
114
+ }
115
+ /**
116
+ * The operator's ceiling exactly as CONFIGURED — three states, not two:
117
+ * a number, `null` for the word `off`, and `undefined` for unset or
118
+ * unparseable.
119
+ *
120
+ * `assistOrgMonthlyCostLimitUsd` collapses `undefined` onto the repo default
121
+ * and is the reading every existing caller wants. The composition with a
122
+ * plan's own band needs the third state, because "the operator wrote a
123
+ * number" and "nobody configured anything" have to bind differently against a
124
+ * band that was sold: an operator's figure is a decision, and the repo
125
+ * default is a backstop for orgs that have no band of their own.
126
+ */ export function assistOperatorCeilingUsd(configured) {
127
+ const raw = String(configured != null ? configured : '').trim();
128
+ if (raw === '') return undefined;
129
+ if (raw.toLowerCase() === 'off') return null;
130
+ const parsed = Number(raw);
131
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : undefined;
132
+ }
133
+ /**
134
+ * Whether this org's Assist spend has newly crossed the margin threshold.
135
+ *
136
+ * Dedupes through the same guard shape and the same month semantics as the
137
+ * customer budget, under its own key, so a staff alert and a customer alert
138
+ * can never suppress one another.
139
+ */ export function assistMarginBreach(input) {
140
+ var _ref;
141
+ const { assistUsd, thresholdUsd, guard, month } = input;
142
+ if (!Number.isFinite(assistUsd) || !Number.isFinite(thresholdUsd)) return false;
143
+ if (thresholdUsd <= 0 || assistUsd < thresholdUsd) return false;
144
+ // The guard records how many WHOLE multiples of the threshold have been
145
+ // announced, so an org at 1x is announced once and an org that climbs to 2x
146
+ // is announced again — an escalating cost must not go quiet because it
147
+ // already spoke.
148
+ const multiple = Math.floor(assistUsd / thresholdUsd);
149
+ if ((guard == null ? void 0 : guard.month) === month && Number((_ref = guard == null ? void 0 : guard.threshold) != null ? _ref : 0) >= multiple) {
150
+ return false;
151
+ }
152
+ return true;
153
+ }
154
+ /**
155
+ * Whether this org has newly crossed the HARD spend ceiling — the one that
156
+ * refuses (AGL-2264), as distinct from {@link assistMarginBreach}'s review
157
+ * threshold, which only warns.
158
+ *
159
+ * It needs its own guard and its own announcement because the margin alert
160
+ * cannot carry this news. That alert speaks in WHOLE MULTIPLES of its $25
161
+ * threshold, so an org that climbs from $25 to the $40 ceiling is still at
162
+ * 1x and stays silent — staff would learn that the assistant had stopped
163
+ * answering for a customer only when someone complained. A ceiling that
164
+ * refuses quietly is the same defect as a ceiling that does not refuse.
165
+ *
166
+ * Once per org per month: crossing is a state, not an escalating figure, and
167
+ * the org is refused from here to the month boundary regardless of how far
168
+ * past it the recorded spend sits.
169
+ */ export function assistCeilingBreach(input) {
170
+ const { assistUsd, ceilingUsd, guard, month } = input;
171
+ if (ceilingUsd === null) return false;
172
+ if (!Number.isFinite(assistUsd) || !Number.isFinite(ceilingUsd)) return false;
173
+ if (ceilingUsd <= 0 || assistUsd < ceilingUsd) return false;
174
+ return (guard == null ? void 0 : guard.month) !== month;
175
+ }
176
+ /** The multiple {@link assistMarginBreach} would record. */ export function assistMarginMultiple(assistUsd, thresholdUsd) {
177
+ if (!Number.isFinite(assistUsd) || !Number.isFinite(thresholdUsd)) return 0;
178
+ if (thresholdUsd <= 0) return 0;
179
+ return Math.max(0, Math.floor(assistUsd / thresholdUsd));
180
+ }
181
+
182
+ //# sourceMappingURL=assist-spend-guards.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/usage/assist-spend-guards.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { UsageAlertGuard } from '@aglyn/aglyn/app-utils/usage-budget'\n\n/*\n * THE AI PLUGIN'S SPEND GUARDS: the staff review threshold on one\n * workspace's monthly provider spend, the hard ceiling past which its\n * reservations refuse, and the dedupe arithmetic the usage-alerts sweep's\n * contributor announces both with. Pure over configured values and the\n * sweep's guard map, so the meter that refuses and the alert that announces\n * the refusal read one variable and agree on what it means.\n */\n\n/**\n * The MARGIN GUARD.\n *\n * A customer's usage budget (`usage-budget.ts`) protects the customer. This\n * protects the platform, from the one meter whose unit cost is real money\n * paid to a third party and whose ceiling is a message count rather than a\n * dollar figure: `assistEntitledMonthlyLimit` caps an entitled org at 1,000\n * MESSAGES a month, and a thousand long, cache-cold Opus-class exchanges is\n * a three-figure bill against a subscription that did not move.\n *\n * So one org's Assist COGS crossing this threshold notifies STAFF, not the\n * customer — the customer is not being charged and has done nothing wrong.\n * Returns the threshold crossed, or 0.\n *\n * `ASSIST_ORG_MONTHLY_COGS_ALERT_USD` overrides the default and FAILS TO THE\n * DEFAULT: a blank or malformed value that disabled the guard would be\n * another alert that cannot fire.\n */\nexport const ASSIST_ORG_MONTHLY_COGS_ALERT_USD_DEFAULT = 25\n\nexport function assistCogsAlertThresholdUsd(\n configured?: string | null,\n): number {\n const parsed = Number(String(configured ?? '').trim())\n if (!Number.isFinite(parsed) || parsed <= 0) {\n return ASSIST_ORG_MONTHLY_COGS_ALERT_USD_DEFAULT\n }\n return parsed\n}\n\n/**\n * The repo default spend ceiling: **$40 per org per month** (AGL-2264).\n *\n * The number is arithmetic rather than pricing. After AGL-2441 the\n * 1,000-message entitled guard bounds roughly $28/org/month of worst-case\n * spend at Sonnet, and the staff margin alert already fires at $25. $40\n * therefore sits ABOVE anything the message cap can produce at the current\n * model, so it changes no charged amount and no plan's behaviour — it is a\n * ceiling on OUR cost, not a customer price, which is why it is outside the\n * Sept-1 pricing lock. It binds only when an assumption behind that\n * arithmetic has moved: an `ASSIST_MODEL` swap to an Opus-class tier, a\n * longer prompt, or a caller finding another way to inflate input. That is\n * the failure it exists for.\n *\n * It ships as a DEFAULT rather than as an environment variable someone must\n * remember, because an unset ceiling is the fail-open this issue was opened\n * about: a fresh deployment and a self-hoster both inherit a sane bound\n * without knowing the variable exists.\n *\n * The free tier gets no separate figure and needs none — its 10 messages a\n * UTC day bound it at roughly $0.28/day, so this is a backstop it cannot\n * reach rather than a cap it runs into.\n *\n * ⚠️ It applies only to an org whose plan sells NO assist band. Agency and\n * Enterprise include more assist than $40 of spend, so the meter's\n * `assistMonthlyCeilingUsd` keeps this default off every plan that sells a\n * band — see there for which figure binds when.\n */\nexport const ASSIST_ORG_MONTHLY_COGS_LIMIT_DEFAULT_USD = 40\n\n/**\n * The per-org monthly PROVIDER-SPEND ceiling in USD — the dollar half of\n * the cap (AGL-2264), from `ASSIST_ORG_MONTHLY_COGS_LIMIT_USD` as the caller\n * read it. Defaults to {@link ASSIST_ORG_MONTHLY_COGS_LIMIT_DEFAULT_USD};\n * `off` removes it.\n *\n * Pure over the configured value, like {@link assistCogsAlertThresholdUsd}:\n * the meter that refuses at the ceiling and the cron that announces the\n * refusal read the one variable and must agree on what it means.\n *\n * The meter's message caps bound spend only through an assumed cost per\n * message, and that assumption is exactly what drifts: `ASSIST_MODEL` is an\n * env override, prompts grow, and a client controls how much history it\n * posts. The ceiling is measured against the real figure instead: the\n * running `estCostUsd` on the month's assist usage document, which the meter\n * increments at the SERVING model's rates. So it bounds the actual bill\n * rather than a forecast of it.\n *\n * The refusal is deliberately the same shape as the message refusal (a\n * reservation that did not move the counter), so an org at the ceiling\n * spends nothing at all rather than spending less. It refuses — it does\n * NOT quietly swap to a cheaper model. A silent quality drop is worse than\n * an honest stop, because nobody can tell it happened.\n *\n * ⚠️ **Fails to the DEFAULT, never to “no ceiling”.** An empty, negative or\n * unparseable value reads as unconfigured and takes the repo default, so a\n * typo cannot reopen the fail-open this exists to close. It cannot become a\n * ceiling of `$0` either — a value of zero is not “refuse everyone”, it is\n * “not a number I will honour” — because an outage across every workspace\n * would be worse than the overspend being guarded.\n *\n * Removing the ceiling therefore takes a WORD rather than a number:\n * `ASSIST_ORG_MONTHLY_COGS_LIMIT_USD=off`. A deployment paying its own\n * provider bill may genuinely want none, and that is a decision someone\n * should have to write down rather than reach by mistyping a digit.\n */\nexport function assistOrgMonthlyCostLimitUsd(\n configured?: string | null,\n): number | null {\n const operator = assistOperatorCeilingUsd(configured)\n return operator === undefined\n ? ASSIST_ORG_MONTHLY_COGS_LIMIT_DEFAULT_USD\n : operator\n}\n\n/**\n * The operator's ceiling exactly as CONFIGURED — three states, not two:\n * a number, `null` for the word `off`, and `undefined` for unset or\n * unparseable.\n *\n * `assistOrgMonthlyCostLimitUsd` collapses `undefined` onto the repo default\n * and is the reading every existing caller wants. The composition with a\n * plan's own band needs the third state, because \"the operator wrote a\n * number\" and \"nobody configured anything\" have to bind differently against a\n * band that was sold: an operator's figure is a decision, and the repo\n * default is a backstop for orgs that have no band of their own.\n */\nexport function assistOperatorCeilingUsd(\n configured?: string | null,\n): number | null | undefined {\n const raw = String(configured ?? '').trim()\n if (raw === '') return undefined\n if (raw.toLowerCase() === 'off') return null\n const parsed = Number(raw)\n return Number.isFinite(parsed) && parsed > 0 ? parsed : undefined\n}\n\n/**\n * Whether this org's Assist spend has newly crossed the margin threshold.\n *\n * Dedupes through the same guard shape and the same month semantics as the\n * customer budget, under its own key, so a staff alert and a customer alert\n * can never suppress one another.\n */\nexport function assistMarginBreach(input: {\n assistUsd: number\n thresholdUsd: number\n guard: UsageAlertGuard | null | undefined\n month: string\n}): boolean {\n const { assistUsd, thresholdUsd, guard, month } = input\n if (!Number.isFinite(assistUsd) || !Number.isFinite(thresholdUsd)) return false\n if (thresholdUsd <= 0 || assistUsd < thresholdUsd) return false\n // The guard records how many WHOLE multiples of the threshold have been\n // announced, so an org at 1x is announced once and an org that climbs to 2x\n // is announced again — an escalating cost must not go quiet because it\n // already spoke.\n const multiple = Math.floor(assistUsd / thresholdUsd)\n if (guard?.month === month && Number(guard?.threshold ?? 0) >= multiple) {\n return false\n }\n return true\n}\n\n/**\n * Whether this org has newly crossed the HARD spend ceiling — the one that\n * refuses (AGL-2264), as distinct from {@link assistMarginBreach}'s review\n * threshold, which only warns.\n *\n * It needs its own guard and its own announcement because the margin alert\n * cannot carry this news. That alert speaks in WHOLE MULTIPLES of its $25\n * threshold, so an org that climbs from $25 to the $40 ceiling is still at\n * 1x and stays silent — staff would learn that the assistant had stopped\n * answering for a customer only when someone complained. A ceiling that\n * refuses quietly is the same defect as a ceiling that does not refuse.\n *\n * Once per org per month: crossing is a state, not an escalating figure, and\n * the org is refused from here to the month boundary regardless of how far\n * past it the recorded spend sits.\n */\nexport function assistCeilingBreach(input: {\n assistUsd: number\n ceilingUsd: number | null\n guard: UsageAlertGuard | null | undefined\n month: string\n}): boolean {\n const { assistUsd, ceilingUsd, guard, month } = input\n if (ceilingUsd === null) return false\n if (!Number.isFinite(assistUsd) || !Number.isFinite(ceilingUsd)) return false\n if (ceilingUsd <= 0 || assistUsd < ceilingUsd) return false\n return guard?.month !== month\n}\n\n/** The multiple {@link assistMarginBreach} would record. */\nexport function assistMarginMultiple(\n assistUsd: number,\n thresholdUsd: number,\n): number {\n if (!Number.isFinite(assistUsd) || !Number.isFinite(thresholdUsd)) return 0\n if (thresholdUsd <= 0) return 0\n return Math.max(0, Math.floor(assistUsd / thresholdUsd))\n}\n"],"names":["ASSIST_ORG_MONTHLY_COGS_ALERT_USD_DEFAULT","assistCogsAlertThresholdUsd","configured","parsed","Number","String","trim","isFinite","ASSIST_ORG_MONTHLY_COGS_LIMIT_DEFAULT_USD","assistOrgMonthlyCostLimitUsd","operator","assistOperatorCeilingUsd","undefined","raw","toLowerCase","assistMarginBreach","input","assistUsd","thresholdUsd","guard","month","multiple","Math","floor","threshold","assistCeilingBreach","ceilingUsd","assistMarginMultiple","max"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAID;;;;;;;CAOC,GAED;;;;;;;;;;;;;;;;;CAiBC,GACD,OAAO,MAAMA,4CAA4C,GAAE;AAE3D,OAAO,SAASC,4BACdC,UAA0B;IAE1B,MAAMC,SAASC,OAAOC,OAAOH,qBAAAA,aAAc,IAAII,IAAI;IACnD,IAAI,CAACF,OAAOG,QAAQ,CAACJ,WAAWA,UAAU,GAAG;QAC3C,OAAOH;IACT;IACA,OAAOG;AACT;AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2BC,GACD,OAAO,MAAMK,4CAA4C,GAAE;AAE3D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmCC,GACD,OAAO,SAASC,6BACdP,UAA0B;IAE1B,MAAMQ,WAAWC,yBAAyBT;IAC1C,OAAOQ,aAAaE,YAChBJ,4CACAE;AACN;AAEA;;;;;;;;;;;CAWC,GACD,OAAO,SAASC,yBACdT,UAA0B;IAE1B,MAAMW,MAAMR,OAAOH,qBAAAA,aAAc,IAAII,IAAI;IACzC,IAAIO,QAAQ,IAAI,OAAOD;IACvB,IAAIC,IAAIC,WAAW,OAAO,OAAO,OAAO;IACxC,MAAMX,SAASC,OAAOS;IACtB,OAAOT,OAAOG,QAAQ,CAACJ,WAAWA,SAAS,IAAIA,SAASS;AAC1D;AAEA;;;;;;CAMC,GACD,OAAO,SAASG,mBAAmBC,KAKlC;;IACC,MAAM,EAAEC,SAAS,EAAEC,YAAY,EAAEC,KAAK,EAAEC,KAAK,EAAE,GAAGJ;IAClD,IAAI,CAACZ,OAAOG,QAAQ,CAACU,cAAc,CAACb,OAAOG,QAAQ,CAACW,eAAe,OAAO;IAC1E,IAAIA,gBAAgB,KAAKD,YAAYC,cAAc,OAAO;IAC1D,wEAAwE;IACxE,4EAA4E;IAC5E,uEAAuE;IACvE,iBAAiB;IACjB,MAAMG,WAAWC,KAAKC,KAAK,CAACN,YAAYC;IACxC,IAAIC,CAAAA,yBAAAA,MAAOC,KAAK,MAAKA,SAAShB,eAAOe,yBAAAA,MAAOK,SAAS,mBAAI,MAAMH,UAAU;QACvE,OAAO;IACT;IACA,OAAO;AACT;AAEA;;;;;;;;;;;;;;;CAeC,GACD,OAAO,SAASI,oBAAoBT,KAKnC;IACC,MAAM,EAAEC,SAAS,EAAES,UAAU,EAAEP,KAAK,EAAEC,KAAK,EAAE,GAAGJ;IAChD,IAAIU,eAAe,MAAM,OAAO;IAChC,IAAI,CAACtB,OAAOG,QAAQ,CAACU,cAAc,CAACb,OAAOG,QAAQ,CAACmB,aAAa,OAAO;IACxE,IAAIA,cAAc,KAAKT,YAAYS,YAAY,OAAO;IACtD,OAAOP,CAAAA,yBAAAA,MAAOC,KAAK,MAAKA;AAC1B;AAEA,0DAA0D,GAC1D,OAAO,SAASO,qBACdV,SAAiB,EACjBC,YAAoB;IAEpB,IAAI,CAACd,OAAOG,QAAQ,CAACU,cAAc,CAACb,OAAOG,QAAQ,CAACW,eAAe,OAAO;IAC1E,IAAIA,gBAAgB,GAAG,OAAO;IAC9B,OAAOI,KAAKM,GAAG,CAAC,GAAGN,KAAKC,KAAK,CAACN,YAAYC;AAC5C"}
@@ -14,7 +14,7 @@
14
14
  * See the License for the specific language governing permissions and
15
15
  * limitations under the License.
16
16
  */
17
- import { type PublicAssistCredits } from '@aglyn/aglyn/app-utils/assist-credits';
17
+ import { type PublicAssistCredits } from './assist-credits';
18
18
  import { type AiOverageCapReason } from '../billing/ai-overage-gate';
19
19
  import type { AiRefusedBy } from '../model/ai-allotments';
20
20
  import { type AiAllotmentGate, type AiAllotmentRequestSubject } from './ai-allotments';
@@ -22,7 +22,7 @@ import { _ as _extends } from "@swc/helpers/_/_extends";
22
22
  * initialization (cert credential, RTDB, AppCheck) into every unit test that
23
23
  * touches a counter; `FieldValue`'s statics need no app at all.
24
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";
25
+ import { ASSIST_PROVIDER_COST_FIELD, assistBandRefuses, assistCreditsFromUsd, assistMonthOverage, assistOverageCapReached, publicAssistCredits, resolveAssistBudgetUsd, resolveAssistOverageCapUsd, resolveAssistOverageRateUsdPer1k } from "./assist-credits.js";
26
26
  import { aiOverageRefusal } from "../billing/ai-overage-gate.js";
27
27
  import { aiOverageBillsByInvoice, aiOverageGuardsApply } from "../billing/ai-overage-cutover.js";
28
28
  import { AI_BILLING_STANDING_DOC, AI_BILLING_SUBCOLLECTION, readAiOverageMonthLedger } from "../billing/ai-overage-ledger.js";