@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 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/components/use-ai-products-jobs.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'use client'\n\nimport { lockdownRefusalText, parseLockdownRefusal } from '@aglyn/aglyn'\nimport { authorizedFetch } from '@aglyn/shared-util-http/authorized-token'\nimport { useHostOrgId, useUser } from '@aglyn/tenant-feature-instance'\nimport { useCallback, useEffect, useRef, useState } from 'react'\nimport { AI_JOB_TERMINAL_STATUSES, type AiJobSummary } from '../model/ai-jobs.types'\nimport { readEventFrames } from './assist-jobs-drawer.component'\n\n/**\n * The jobs route, as a commerce card asks it (AGL-2916): whether the feature\n * is this workspace's at all, the site's recent `products` jobs, starting one,\n * and following each until it settles.\n *\n * The shell has already decided the plan and the member's permission before a\n * card mounts; the release flag is the route's, so a 404 or 403 from the list\n * is the card staying absent. A card follows more than one job at a time — a\n * bulk copy job and a catalog, say — so each job has its own watch: every job\n * it starts, and of the jobs it finds already moving, the ones `follows`\n * names as its own.\n */\n\n/** How many recent jobs a card reads to find this site's products jobs. */\nexport const AI_PRODUCTS_RECENT_JOBS_READ = 20\n\nexport type AiProductsJobsVerdict = 'checking' | 'ready' | 'hidden'\n\nexport interface AiProductsJobs {\n /** The org the jobs are metered against: the zone's, or the site's. */\n orgId: string | undefined\n verdict: AiProductsJobsVerdict\n /** The site's recent `products` jobs, newest first, kept current while followed. */\n jobs: AiJobSummary[]\n notice: string | null\n setNotice: (notice: string | null) => void\n /** Starts a job and follows it; resolves with the job as created, or `null` with a notice. */\n start: (brief: string, inputs: Record<string, string>) => Promise<AiJobSummary | null>\n}\n\nexport const isAiJobSettled = (job: AiJobSummary | null | undefined): boolean =>\n Boolean(job && AI_JOB_TERMINAL_STATUSES.includes(job.status))\n\n/** Whether a job is moving now: queued or running, rather than settled or waiting for a person. */\nexport const isAiJobMoving = (job: AiJobSummary | null | undefined): boolean =>\n job?.status === 'queued' || job?.status === 'running'\n\nconst START_FAILED_COPY = 'The AI job could not be started. Try again.'\nconst LIST_FAILED_COPY = 'Recent AI proposals could not be loaded.'\n\nexport function useAiProductsJobs(input: {\n hostId: string\n orgId: string | undefined\n /** Which of the site's moving jobs this card shows, and so follows; none when absent. */\n follows?: (job: AiJobSummary) => boolean\n}): AiProductsJobs {\n const { hostId } = input\n // Read through a ref: a card passes a fresh function each render, and the\n // list is read once for who is signed in, not once for each.\n const followsRef = useRef(input.follows)\n followsRef.current = input.follows\n // A plugin-hosted zone may not know the org; the site does.\n const hostOrgId = useHostOrgId(input.orgId ? undefined : hostId)\n const orgId = input.orgId ?? hostOrgId ?? undefined\n const { data: user } = useUser()\n // Held in a ref so the reads key on WHO is signed in, never on the identity\n // of the object that says so.\n const userRef = useRef(user)\n userRef.current = user\n const uid = user?.uid ?? null\n\n const [verdict, setVerdict] = useState<AiProductsJobsVerdict>('checking')\n const [jobs, setJobs] = useState<AiJobSummary[]>([])\n const [notice, setNotice] = useState<string | null>(null)\n const watches = useRef(new Map<string, AbortController>())\n\n useEffect(() => {\n const open = watches.current\n return () => {\n for (const controller of open.values()) controller.abort()\n open.clear()\n }\n }, [])\n\n const put = useCallback((job: AiJobSummary) => {\n setJobs((current) => [job, ...current.filter((entry) => entry.id !== job.id)].sort((a, b) =>\n b.createdAt.localeCompare(a.createdAt),\n ))\n }, [])\n\n /** Follows one job through the events route until it settles. */\n const follow = useCallback(\n async (job: AiJobSummary, org: string) => {\n if (!isAiJobMoving(job) || watches.current.has(job.id)) return\n const controller = new AbortController()\n watches.current.set(job.id, controller)\n try {\n let again = true\n while (again && !controller.signal.aborted) {\n again = false\n const response = await authorizedFetch(\n userRef.current,\n `/api/ai/jobs/${encodeURIComponent(job.id)}/events?orgId=${encodeURIComponent(org)}`,\n { signal: controller.signal },\n )\n if (!response.ok || !response.body) return\n await readEventFrames(response.body, (event) => {\n if (event['type'] === 'state') put(event['job'] as AiJobSummary)\n else if (event['type'] === 'reconnect') again = true\n })\n }\n } catch {\n // An aborted or dropped watch leaves the last state shown.\n } finally {\n watches.current.delete(job.id)\n }\n },\n [put],\n )\n\n useEffect(() => {\n if (!orgId || !hostId || !uid) return\n let active = true\n setVerdict('checking')\n void (async () => {\n try {\n const response = await authorizedFetch(\n userRef.current,\n `/api/ai/jobs?orgId=${encodeURIComponent(orgId)}&limit=${AI_PRODUCTS_RECENT_JOBS_READ}`,\n )\n if (!active) return\n // The flag off (404) and the plan without generation (403): the\n // feature is not this workspace's, so the card is not here at all.\n if (response.status === 404 || response.status === 403) {\n setVerdict('hidden')\n return\n }\n const payload = await response.json().catch(() => null)\n if (!active) return\n if (!response.ok) {\n const locked = parseLockdownRefusal(response.status, payload)\n setNotice(locked ? lockdownRefusalText(locked) : String(payload?.error ?? LIST_FAILED_COPY))\n } else {\n const recent = ((payload?.jobs ?? []) as AiJobSummary[]).filter(\n (entry) => entry.kind === 'products' && entry.hostId === hostId,\n )\n setJobs(recent)\n for (const job of recent) {\n if (followsRef.current?.(job)) void follow(job, orgId)\n }\n }\n setVerdict('ready')\n } catch {\n if (!active) return\n setNotice(LIST_FAILED_COPY)\n setVerdict('ready')\n }\n })()\n return () => {\n active = false\n }\n }, [orgId, hostId, uid, follow])\n\n const start = useCallback(\n async (brief: string, inputs: Record<string, string>) => {\n if (!orgId) return null\n setNotice(null)\n try {\n const response = await authorizedFetch(userRef.current, '/api/ai/jobs', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ orgId, hostId, kind: 'products', brief, inputs }),\n })\n const payload = await response.json().catch(() => null)\n if (!response.ok) {\n const locked = parseLockdownRefusal(response.status, payload)\n setNotice(locked ? lockdownRefusalText(locked) : String(payload?.error ?? START_FAILED_COPY))\n return null\n }\n const job = payload?.job as AiJobSummary | undefined\n if (!job) return null\n put(job)\n void follow(job, orgId)\n return job\n } catch {\n setNotice(START_FAILED_COPY)\n return null\n }\n },\n [orgId, hostId, put, follow],\n )\n\n return { orgId, verdict, jobs, notice, setNotice, start }\n}\n"],"names":["lockdownRefusalText","parseLockdownRefusal","authorizedFetch","useHostOrgId","useUser","useCallback","useEffect","useRef","useState","AI_JOB_TERMINAL_STATUSES","readEventFrames","AI_PRODUCTS_RECENT_JOBS_READ","isAiJobSettled","job","Boolean","includes","status","isAiJobMoving","START_FAILED_COPY","LIST_FAILED_COPY","useAiProductsJobs","input","hostId","followsRef","follows","current","hostOrgId","orgId","undefined","data","user","userRef","uid","verdict","setVerdict","jobs","setJobs","notice","setNotice","watches","Map","open","controller","values","abort","clear","put","filter","entry","id","sort","a","b","createdAt","localeCompare","follow","org","has","AbortController","set","again","signal","aborted","response","encodeURIComponent","ok","body","event","delete","active","payload","json","catch","locked","String","error","recent","kind","start","brief","inputs","method","headers","JSON","stringify"],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { AiUsageMeterWire } from '../usage/ai-usage-wire';
2
+ /** Whether a value is an envelope a strip can render. */
3
+ export declare function isAiUsageMeterWire(value: unknown): value is AiUsageMeterWire;
4
+ /** Hand a door's envelope to every strip for this reader and workspace. */
5
+ export declare function publishAiUsageMeter(uid: string | null | undefined, orgId: string | null | undefined, meter: unknown): void;
6
+ /** Forget every envelope; specs start each case from nothing. */
7
+ export declare function resetAiUsageMetersForTests(): void;
8
+ /** The latest envelope for the signed-in reader in one workspace. */
9
+ export declare function useAiUsageMeter(orgId: string | null | undefined): AiUsageMeterWire | null;
10
+ /** A stable publisher bound to the signed-in reader and one workspace. */
11
+ export declare function usePublishAiUsageMeter(orgId: string | null | undefined): (meter: unknown) => void;
@@ -0,0 +1,96 @@
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
+ */ 'use client';
17
+ import { useUser } from "@aglyn/tenant-feature-instance";
18
+ import { useCallback, useEffect, useState } from "react";
19
+ const meters = new Map();
20
+ const listeners = new Map();
21
+ const keyOf = (uid, orgId)=>`${uid}\x00${orgId}`;
22
+ const storageKey = (uid, orgId)=>`aglyn-ai-meter:${uid}:${orgId}`;
23
+ const monthNow = ()=>new Date().toISOString().slice(0, 7);
24
+ /** Whether a value is an envelope a strip can render. */ export function isAiUsageMeterWire(value) {
25
+ var _meter_pool, _meter_mine;
26
+ const meter = value;
27
+ return Boolean(meter && typeof meter === 'object' && typeof meter.month === 'string' && typeof ((_meter_pool = meter.pool) == null ? void 0 : _meter_pool.used) === 'number' && typeof ((_meter_mine = meter.mine) == null ? void 0 : _meter_mine.used) === 'number' && typeof meter.state === 'string');
28
+ }
29
+ function hydrate(uid, orgId) {
30
+ try {
31
+ var _globalThis_localStorage;
32
+ const raw = (_globalThis_localStorage = globalThis.localStorage) == null ? void 0 : _globalThis_localStorage.getItem(storageKey(uid, orgId));
33
+ const parsed = raw ? JSON.parse(raw) : null;
34
+ return isAiUsageMeterWire(parsed) && parsed.month === monthNow() ? parsed : null;
35
+ } catch (unused) {
36
+ return null;
37
+ }
38
+ }
39
+ /** Hand a door's envelope to every strip for this reader and workspace. */ export function publishAiUsageMeter(uid, orgId, meter) {
40
+ var _listeners_get;
41
+ if (!uid || !orgId || !isAiUsageMeterWire(meter)) return;
42
+ const key = keyOf(uid, orgId);
43
+ meters.set(key, meter);
44
+ try {
45
+ var _globalThis_localStorage;
46
+ (_globalThis_localStorage = globalThis.localStorage) == null ? void 0 : _globalThis_localStorage.setItem(storageKey(uid, orgId), JSON.stringify(meter));
47
+ } catch (unused) {
48
+ // Full or blocked storage keeps the strip for this page only.
49
+ }
50
+ for (const listener of (_listeners_get = listeners.get(key)) != null ? _listeners_get : [])listener(meter);
51
+ }
52
+ /** Forget every envelope; specs start each case from nothing. */ export function resetAiUsageMetersForTests() {
53
+ meters.clear();
54
+ listeners.clear();
55
+ }
56
+ /** The latest envelope for the signed-in reader in one workspace. */ export function useAiUsageMeter(orgId) {
57
+ var _ref;
58
+ const { data: user } = useUser();
59
+ const uid = (_ref = user == null ? void 0 : user.uid) != null ? _ref : null;
60
+ const key = uid && orgId ? keyOf(uid, orgId) : null;
61
+ const [meter, setMeter] = useState(()=>{
62
+ var _meters_get;
63
+ return key ? (_meters_get = meters.get(key)) != null ? _meters_get : null : null;
64
+ });
65
+ useEffect(()=>{
66
+ var _meters_get, _listeners_get;
67
+ if (!key || !uid || !orgId) {
68
+ setMeter(null);
69
+ return undefined;
70
+ }
71
+ if (!meters.has(key)) meters.set(key, hydrate(uid, orgId));
72
+ setMeter((_meters_get = meters.get(key)) != null ? _meters_get : null);
73
+ const subscribed = (_listeners_get = listeners.get(key)) != null ? _listeners_get : new Set();
74
+ listeners.set(key, subscribed);
75
+ subscribed.add(setMeter);
76
+ return ()=>{
77
+ subscribed.delete(setMeter);
78
+ };
79
+ }, [
80
+ key,
81
+ uid,
82
+ orgId
83
+ ]);
84
+ return meter;
85
+ }
86
+ /** A stable publisher bound to the signed-in reader and one workspace. */ export function usePublishAiUsageMeter(orgId) {
87
+ var _ref;
88
+ const { data: user } = useUser();
89
+ const uid = (_ref = user == null ? void 0 : user.uid) != null ? _ref : null;
90
+ return useCallback((meter)=>publishAiUsageMeter(uid, orgId, meter), [
91
+ uid,
92
+ orgId
93
+ ]);
94
+ }
95
+
96
+ //# sourceMappingURL=use-ai-usage-meter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/components/use-ai-usage-meter.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'use client'\n\nimport { useUser } from '@aglyn/tenant-feature-instance'\nimport { useCallback, useEffect, useState } from 'react'\nimport type { AiUsageMeterWire } from '../usage/ai-usage-wire'\n\n/**\n * THE USAGE STRIP'S STORE (AGL-2942).\n *\n * Every AI door answers with a `meter` envelope — the chat door's `done`\n * event, the copy assistant's JSON, each refusal — and the surface that sent\n * the request hands it here. Every strip mounted for the same person and the\n * same workspace — the panel's, a dialog's — reads the latest one, so a\n * rewrite in the besigner moves the panel's strip too, and no strip ever\n * reads anything itself.\n *\n * The last envelope is kept in the browser for the rest of its month, so a\n * reload shows where the reader stood at their last request rather than an\n * empty strip until the next one. It is labeled as of that request by\n * construction: nothing refreshes it but a door's answer.\n *\n * Keyed on WHO is signed in, never on the user object, whose identity a\n * provider may hand back fresh on every render.\n */\n\ntype Listener = (meter: AiUsageMeterWire | null) => void\n\nconst meters = new Map<string, AiUsageMeterWire | null>()\nconst listeners = new Map<string, Set<Listener>>()\n\nconst keyOf = (uid: string, orgId: string): string => `${uid}\\x00${orgId}`\nconst storageKey = (uid: string, orgId: string): string => `aglyn-ai-meter:${uid}:${orgId}`\nconst monthNow = (): string => new Date().toISOString().slice(0, 7)\n\n/** Whether a value is an envelope a strip can render. */\nexport function isAiUsageMeterWire(value: unknown): value is AiUsageMeterWire {\n const meter = value as Partial<AiUsageMeterWire> | null\n return Boolean(\n meter &&\n typeof meter === 'object' &&\n typeof meter.month === 'string' &&\n typeof meter.pool?.used === 'number' &&\n typeof meter.mine?.used === 'number' &&\n typeof meter.state === 'string',\n )\n}\n\nfunction hydrate(uid: string, orgId: string): AiUsageMeterWire | null {\n try {\n const raw = globalThis.localStorage?.getItem(storageKey(uid, orgId))\n const parsed: unknown = raw ? JSON.parse(raw) : null\n return isAiUsageMeterWire(parsed) && parsed.month === monthNow() ? parsed : null\n } catch {\n return null\n }\n}\n\n/** Hand a door's envelope to every strip for this reader and workspace. */\nexport function publishAiUsageMeter(\n uid: string | null | undefined,\n orgId: string | null | undefined,\n meter: unknown,\n): void {\n if (!uid || !orgId || !isAiUsageMeterWire(meter)) return\n const key = keyOf(uid, orgId)\n meters.set(key, meter)\n try {\n globalThis.localStorage?.setItem(storageKey(uid, orgId), JSON.stringify(meter))\n } catch {\n // Full or blocked storage keeps the strip for this page only.\n }\n for (const listener of listeners.get(key) ?? []) listener(meter)\n}\n\n/** Forget every envelope; specs start each case from nothing. */\nexport function resetAiUsageMetersForTests(): void {\n meters.clear()\n listeners.clear()\n}\n\n/** The latest envelope for the signed-in reader in one workspace. */\nexport function useAiUsageMeter(orgId: string | null | undefined): AiUsageMeterWire | null {\n const { data: user } = useUser()\n const uid = user?.uid ?? null\n const key = uid && orgId ? keyOf(uid, orgId) : null\n const [meter, setMeter] = useState<AiUsageMeterWire | null>(() =>\n key ? (meters.get(key) ?? null) : null,\n )\n useEffect(() => {\n if (!key || !uid || !orgId) {\n setMeter(null)\n return undefined\n }\n if (!meters.has(key)) meters.set(key, hydrate(uid, orgId))\n setMeter(meters.get(key) ?? null)\n const subscribed = listeners.get(key) ?? new Set<Listener>()\n listeners.set(key, subscribed)\n subscribed.add(setMeter)\n return () => {\n subscribed.delete(setMeter)\n }\n }, [key, uid, orgId])\n return meter\n}\n\n/** A stable publisher bound to the signed-in reader and one workspace. */\nexport function usePublishAiUsageMeter(\n orgId: string | null | undefined,\n): (meter: unknown) => void {\n const { data: user } = useUser()\n const uid = user?.uid ?? null\n return useCallback((meter: unknown) => publishAiUsageMeter(uid, orgId, meter), [uid, orgId])\n}\n"],"names":["useUser","useCallback","useEffect","useState","meters","Map","listeners","keyOf","uid","orgId","storageKey","monthNow","Date","toISOString","slice","isAiUsageMeterWire","value","meter","Boolean","month","pool","used","mine","state","hydrate","globalThis","raw","localStorage","getItem","parsed","JSON","parse","publishAiUsageMeter","key","set","setItem","stringify","listener","get","resetAiUsageMetersForTests","clear","useAiUsageMeter","data","user","setMeter","undefined","has","subscribed","Set","add","delete","usePublishAiUsageMeter"],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ import type { OrgAiUsageTableWire } from '../usage/ai-usage-wire';
2
+ /**
3
+ * Loading, answered, refused, or failed — four states, never three
4
+ * (AGL-2928).
5
+ *
6
+ * `refused` is its own state because three surfaces read this and only one
7
+ * of them is gated on the permission the route checks: the roster and the
8
+ * site collaborators card are open to a member who manages people and may
9
+ * not see billing, and for them a 403 is the ordinary answer — the column
10
+ * renders a dash, not an error. Folding it into `error` would paint a
11
+ * warning on every team page whose admin lacks `billing.view`.
12
+ */
13
+ export type OrgAiUsageStatus = 'loading' | 'ready' | 'refused' | 'error';
14
+ export interface OrgAiUsageState {
15
+ status: OrgAiUsageStatus;
16
+ data: OrgAiUsageTableWire | null;
17
+ /** The month the table describes, whether or not it has answered yet. */
18
+ month: string;
19
+ /** The months a reader may pick, newest first. */
20
+ months: string[];
21
+ /** Credits by uid for the month — the roster column's join. */
22
+ creditsByUid: Map<string, number>;
23
+ /** Credits on the named site by uid, when a site was named. */
24
+ hostCreditsByUid: Map<string, number>;
25
+ /** Reads the month again, for every mount sharing it. */
26
+ reload: () => void;
27
+ }
28
+ /** Forget every shared read; specs start each case from nothing. */
29
+ export declare function resetOrgAiUsageReadsForTests(): void;
30
+ /**
31
+ * One month of the per-user rollup for one org, through `/api/ai/usage`.
32
+ *
33
+ * Pass `hostId` to have each row carry its credits on that site. Pass
34
+ * `enabled: false` to hold the read — a card that is not yet sure of its
35
+ * org id, or a viewer the gate has already refused.
36
+ */
37
+ export declare function useOrgAiUsage(orgId: string | null | undefined, options?: {
38
+ month?: string;
39
+ hostId?: string;
40
+ enabled?: boolean;
41
+ }): OrgAiUsageState;
42
+ export default useOrgAiUsage;
@@ -0,0 +1,181 @@
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
+ */ 'use client';
17
+ import { aiUsageMonthKeys } from "../model/ai-usage-by-user.js";
18
+ import { authorizedFetch } from "@aglyn/shared-util-http/authorized-token";
19
+ import { useUser } from "@aglyn/tenant-feature-instance";
20
+ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
21
+ const LOADING = {
22
+ status: 'loading',
23
+ data: null
24
+ };
25
+ const sharedReads = new Map();
26
+ /** Forget every shared read; specs start each case from nothing. */ export function resetOrgAiUsageReadsForTests() {
27
+ sharedReads.clear();
28
+ }
29
+ function publish(entry, read) {
30
+ entry.read = read;
31
+ for (const listener of entry.listeners)listener(read);
32
+ }
33
+ async function readInto(entry, user, query) {
34
+ entry.generation += 1;
35
+ const generation = entry.generation;
36
+ publish(entry, {
37
+ status: 'loading',
38
+ data: entry.read.data
39
+ });
40
+ try {
41
+ const response = await authorizedFetch(user, `/api/ai/usage?${query}`);
42
+ if (generation !== entry.generation) return;
43
+ if (response.status === 403) {
44
+ publish(entry, {
45
+ status: 'refused',
46
+ data: null
47
+ });
48
+ return;
49
+ }
50
+ const payload = await response.json().catch(()=>null);
51
+ if (generation !== entry.generation) return;
52
+ if (!response.ok || !payload) {
53
+ publish(entry, {
54
+ status: 'error',
55
+ data: null
56
+ });
57
+ return;
58
+ }
59
+ publish(entry, {
60
+ status: 'ready',
61
+ data: payload
62
+ });
63
+ } catch (unused) {
64
+ if (generation === entry.generation) publish(entry, {
65
+ status: 'error',
66
+ data: null
67
+ });
68
+ }
69
+ }
70
+ /**
71
+ * One month of the per-user rollup for one org, through `/api/ai/usage`.
72
+ *
73
+ * Pass `hostId` to have each row carry its credits on that site. Pass
74
+ * `enabled: false` to hold the read — a card that is not yet sure of its
75
+ * org id, or a viewer the gate has already refused.
76
+ */ export function useOrgAiUsage(orgId, options = {}) {
77
+ var _ref, _options_month, _options_hostId, _ref1;
78
+ var _read_data;
79
+ const { data: user } = useUser();
80
+ // The read is keyed on WHO is signed in, not on the user object's identity:
81
+ // a provider (or a test double) that hands back a fresh object per render
82
+ // would otherwise re-run the effect on every paint and never settle.
83
+ const uid = (_ref = user == null ? void 0 : user.uid) != null ? _ref : null;
84
+ const userRef = useRef(user);
85
+ userRef.current = user;
86
+ const fallbackMonths = useMemo(()=>aiUsageMonthKeys(), []);
87
+ const month = (_options_month = options.month) != null ? _options_month : fallbackMonths[0];
88
+ const hostId = (_options_hostId = options.hostId) != null ? _options_hostId : '';
89
+ const enabled = options.enabled !== false;
90
+ const key = orgId && uid && enabled ? [
91
+ uid,
92
+ orgId,
93
+ month,
94
+ hostId
95
+ ].join('\x00') : null;
96
+ const query = useMemo(()=>{
97
+ if (!orgId) return '';
98
+ const params = new URLSearchParams({
99
+ orgId,
100
+ month
101
+ });
102
+ if (hostId) params.set('hostId', hostId);
103
+ return params.toString();
104
+ }, [
105
+ orgId,
106
+ month,
107
+ hostId
108
+ ]);
109
+ const [read, setRead] = useState(()=>{
110
+ var _ref;
111
+ var _sharedReads_get;
112
+ return (_ref = key ? (_sharedReads_get = sharedReads.get(key)) == null ? void 0 : _sharedReads_get.read : undefined) != null ? _ref : LOADING;
113
+ });
114
+ useEffect(()=>{
115
+ const signedIn = userRef.current;
116
+ if (!key || !signedIn) return undefined;
117
+ let entry = sharedReads.get(key);
118
+ if (!entry) {
119
+ entry = {
120
+ read: LOADING,
121
+ listeners: new Set(),
122
+ generation: 0
123
+ };
124
+ sharedReads.set(key, entry);
125
+ }
126
+ const shared = entry;
127
+ const first = shared.listeners.size === 0;
128
+ shared.listeners.add(setRead);
129
+ setRead(shared.read);
130
+ if (first) void readInto(shared, signedIn, query);
131
+ return ()=>{
132
+ shared.listeners.delete(setRead);
133
+ };
134
+ }, [
135
+ key,
136
+ query
137
+ ]);
138
+ const reload = useCallback(()=>{
139
+ const signedIn = userRef.current;
140
+ const entry = key ? sharedReads.get(key) : undefined;
141
+ if (entry && signedIn) void readInto(entry, signedIn, query);
142
+ }, [
143
+ key,
144
+ query
145
+ ]);
146
+ const creditsByUid = useMemo(()=>{
147
+ var _ref;
148
+ var _read_data;
149
+ return new Map(((_ref = (_read_data = read.data) == null ? void 0 : _read_data.rows) != null ? _ref : []).map((row)=>[
150
+ row.uid,
151
+ row.credits
152
+ ]));
153
+ }, [
154
+ read.data
155
+ ]);
156
+ const hostCreditsByUid = useMemo(()=>{
157
+ var _ref;
158
+ var _read_data;
159
+ return new Map(((_ref = (_read_data = read.data) == null ? void 0 : _read_data.rows) != null ? _ref : []).map((row)=>{
160
+ var _row_hostCredits;
161
+ return [
162
+ row.uid,
163
+ (_row_hostCredits = row.hostCredits) != null ? _row_hostCredits : 0
164
+ ];
165
+ }));
166
+ }, [
167
+ read.data
168
+ ]);
169
+ return {
170
+ status: key ? read.status : 'loading',
171
+ data: key ? read.data : null,
172
+ month,
173
+ months: (_ref1 = (_read_data = read.data) == null ? void 0 : _read_data.months) != null ? _ref1 : fallbackMonths,
174
+ creditsByUid,
175
+ hostCreditsByUid,
176
+ reload
177
+ };
178
+ }
179
+ export default useOrgAiUsage;
180
+
181
+ //# sourceMappingURL=use-org-ai-usage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/components/use-org-ai-usage.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport { aiUsageMonthKeys } from '../model/ai-usage-by-user'\nimport { authorizedFetch } from '@aglyn/shared-util-http/authorized-token'\nimport { useUser } from '@aglyn/tenant-feature-instance'\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport type { OrgAiUsageTableWire } from '../usage/ai-usage-wire'\n\n/**\n * Loading, answered, refused, or failed — four states, never three\n * (AGL-2928).\n *\n * `refused` is its own state because three surfaces read this and only one\n * of them is gated on the permission the route checks: the roster and the\n * site collaborators card are open to a member who manages people and may\n * not see billing, and for them a 403 is the ordinary answer — the column\n * renders a dash, not an error. Folding it into `error` would paint a\n * warning on every team page whose admin lacks `billing.view`.\n */\nexport type OrgAiUsageStatus = 'loading' | 'ready' | 'refused' | 'error'\n\nexport interface OrgAiUsageState {\n status: OrgAiUsageStatus\n data: OrgAiUsageTableWire | null\n /** The month the table describes, whether or not it has answered yet. */\n month: string\n /** The months a reader may pick, newest first. */\n months: string[]\n /** Credits by uid for the month — the roster column's join. */\n creditsByUid: Map<string, number>\n /** Credits on the named site by uid, when a site was named. */\n hostCreditsByUid: Map<string, number>\n /** Reads the month again, for every mount sharing it. */\n reload: () => void\n}\n\ninterface OrgAiUsageRead {\n status: OrgAiUsageStatus\n data: OrgAiUsageTableWire | null\n}\n\n/**\n * One read of one month, shared by every mount that asks for it.\n *\n * A roster column is mounted once per ROW, so a read per mount would send\n * one request per member for the same table. Mounts of the same reader, org,\n * month and site subscribe to one entry instead: the first subscriber reads,\n * the rest take its answer, and `reload` reads again for all of them. An\n * answer that arrives after a newer read has started is dropped.\n */\ninterface SharedRead {\n read: OrgAiUsageRead\n listeners: Set<(read: OrgAiUsageRead) => void>\n generation: number\n}\n\nconst LOADING: OrgAiUsageRead = { status: 'loading', data: null }\n\nconst sharedReads = new Map<string, SharedRead>()\n\n/** Forget every shared read; specs start each case from nothing. */\nexport function resetOrgAiUsageReadsForTests(): void {\n sharedReads.clear()\n}\n\nfunction publish(entry: SharedRead, read: OrgAiUsageRead): void {\n entry.read = read\n for (const listener of entry.listeners) listener(read)\n}\n\nasync function readInto(\n entry: SharedRead,\n user: Parameters<typeof authorizedFetch>[0],\n query: string,\n): Promise<void> {\n entry.generation += 1\n const generation = entry.generation\n publish(entry, { status: 'loading', data: entry.read.data })\n try {\n const response = await authorizedFetch(user, `/api/ai/usage?${query}`)\n if (generation !== entry.generation) return\n if (response.status === 403) {\n publish(entry, { status: 'refused', data: null })\n return\n }\n const payload = await response.json().catch(() => null)\n if (generation !== entry.generation) return\n if (!response.ok || !payload) {\n publish(entry, { status: 'error', data: null })\n return\n }\n publish(entry, { status: 'ready', data: payload as OrgAiUsageTableWire })\n } catch {\n if (generation === entry.generation) publish(entry, { status: 'error', data: null })\n }\n}\n\n/**\n * One month of the per-user rollup for one org, through `/api/ai/usage`.\n *\n * Pass `hostId` to have each row carry its credits on that site. Pass\n * `enabled: false` to hold the read — a card that is not yet sure of its\n * org id, or a viewer the gate has already refused.\n */\nexport function useOrgAiUsage(\n orgId: string | null | undefined,\n options: { month?: string; hostId?: string; enabled?: boolean } = {},\n): OrgAiUsageState {\n const { data: user } = useUser()\n // The read is keyed on WHO is signed in, not on the user object's identity:\n // a provider (or a test double) that hands back a fresh object per render\n // would otherwise re-run the effect on every paint and never settle.\n const uid = user?.uid ?? null\n const userRef = useRef(user)\n userRef.current = user\n const fallbackMonths = useMemo(() => aiUsageMonthKeys(), [])\n const month = options.month ?? fallbackMonths[0]\n const hostId = options.hostId ?? ''\n const enabled = options.enabled !== false\n const key = orgId && uid && enabled ? [uid, orgId, month, hostId].join('\\x00') : null\n const query = useMemo(() => {\n if (!orgId) return ''\n const params = new URLSearchParams({ orgId, month })\n if (hostId) params.set('hostId', hostId)\n return params.toString()\n }, [orgId, month, hostId])\n const [read, setRead] = useState<OrgAiUsageRead>(\n () => (key ? sharedReads.get(key)?.read : undefined) ?? LOADING,\n )\n\n useEffect(() => {\n const signedIn = userRef.current\n if (!key || !signedIn) return undefined\n let entry = sharedReads.get(key)\n if (!entry) {\n entry = { read: LOADING, listeners: new Set(), generation: 0 }\n sharedReads.set(key, entry)\n }\n const shared = entry\n const first = shared.listeners.size === 0\n shared.listeners.add(setRead)\n setRead(shared.read)\n if (first) void readInto(shared, signedIn, query)\n return () => {\n shared.listeners.delete(setRead)\n }\n }, [key, query])\n\n const reload = useCallback(() => {\n const signedIn = userRef.current\n const entry = key ? sharedReads.get(key) : undefined\n if (entry && signedIn) void readInto(entry, signedIn, query)\n }, [key, query])\n\n const creditsByUid = useMemo(\n () => new Map((read.data?.rows ?? []).map((row) => [row.uid, row.credits])),\n [read.data],\n )\n const hostCreditsByUid = useMemo(\n () =>\n new Map(\n (read.data?.rows ?? []).map((row) => [row.uid, row.hostCredits ?? 0]),\n ),\n [read.data],\n )\n\n return {\n status: key ? read.status : 'loading',\n data: key ? read.data : null,\n month,\n months: read.data?.months ?? fallbackMonths,\n creditsByUid,\n hostCreditsByUid,\n reload,\n }\n}\n\nexport default useOrgAiUsage\n"],"names":["aiUsageMonthKeys","authorizedFetch","useUser","useCallback","useEffect","useMemo","useRef","useState","LOADING","status","data","sharedReads","Map","resetOrgAiUsageReadsForTests","clear","publish","entry","read","listener","listeners","readInto","user","query","generation","response","payload","json","catch","ok","useOrgAiUsage","orgId","options","uid","userRef","current","fallbackMonths","month","hostId","enabled","key","join","params","URLSearchParams","set","toString","setRead","get","undefined","signedIn","Set","shared","first","size","add","delete","reload","creditsByUid","rows","map","row","credits","hostCreditsByUid","hostCredits","months"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GACD;AAEA,SAASA,gBAAgB,QAAQ,+BAA2B;AAC5D,SAASC,eAAe,QAAQ,2CAA0C;AAC1E,SAASC,OAAO,QAAQ,iCAAgC;AACxD,SAASC,WAAW,EAAEC,SAAS,EAAEC,OAAO,EAAEC,MAAM,EAAEC,QAAQ,QAAQ,QAAO;AAmDzE,MAAMC,UAA0B;IAAEC,QAAQ;IAAWC,MAAM;AAAK;AAEhE,MAAMC,cAAc,IAAIC;AAExB,kEAAkE,GAClE,OAAO,SAASC;IACdF,YAAYG,KAAK;AACnB;AAEA,SAASC,QAAQC,KAAiB,EAAEC,IAAoB;IACtDD,MAAMC,IAAI,GAAGA;IACb,KAAK,MAAMC,YAAYF,MAAMG,SAAS,CAAED,SAASD;AACnD;AAEA,eAAeG,SACbJ,KAAiB,EACjBK,IAA2C,EAC3CC,KAAa;IAEbN,MAAMO,UAAU,IAAI;IACpB,MAAMA,aAAaP,MAAMO,UAAU;IACnCR,QAAQC,OAAO;QAAEP,QAAQ;QAAWC,MAAMM,MAAMC,IAAI,CAACP,IAAI;IAAC;IAC1D,IAAI;QACF,MAAMc,WAAW,MAAMvB,gBAAgBoB,MAAM,CAAC,cAAc,EAAEC,OAAO;QACrE,IAAIC,eAAeP,MAAMO,UAAU,EAAE;QACrC,IAAIC,SAASf,MAAM,KAAK,KAAK;YAC3BM,QAAQC,OAAO;gBAAEP,QAAQ;gBAAWC,MAAM;YAAK;YAC/C;QACF;QACA,MAAMe,UAAU,MAAMD,SAASE,IAAI,GAAGC,KAAK,CAAC,IAAM;QAClD,IAAIJ,eAAeP,MAAMO,UAAU,EAAE;QACrC,IAAI,CAACC,SAASI,EAAE,IAAI,CAACH,SAAS;YAC5BV,QAAQC,OAAO;gBAAEP,QAAQ;gBAASC,MAAM;YAAK;YAC7C;QACF;QACAK,QAAQC,OAAO;YAAEP,QAAQ;YAASC,MAAMe;QAA+B;IACzE,EAAE,eAAM;QACN,IAAIF,eAAeP,MAAMO,UAAU,EAAER,QAAQC,OAAO;YAAEP,QAAQ;YAASC,MAAM;QAAK;IACpF;AACF;AAEA;;;;;;CAMC,GACD,OAAO,SAASmB,cACdC,KAAgC,EAChCC,UAAkE,CAAC,CAAC;cAUtDA,gBACCA;QAqDLd;IA9DV,MAAM,EAAEP,MAAMW,IAAI,EAAE,GAAGnB;IACvB,4EAA4E;IAC5E,0EAA0E;IAC1E,qEAAqE;IACrE,MAAM8B,cAAMX,wBAAAA,KAAMW,GAAG,mBAAI;IACzB,MAAMC,UAAU3B,OAAOe;IACvBY,QAAQC,OAAO,GAAGb;IAClB,MAAMc,iBAAiB9B,QAAQ,IAAML,oBAAoB,EAAE;IAC3D,MAAMoC,SAAQL,iBAAAA,QAAQK,KAAK,YAAbL,iBAAiBI,cAAc,CAAC,EAAE;IAChD,MAAME,UAASN,kBAAAA,QAAQM,MAAM,YAAdN,kBAAkB;IACjC,MAAMO,UAAUP,QAAQO,OAAO,KAAK;IACpC,MAAMC,MAAMT,SAASE,OAAOM,UAAU;QAACN;QAAKF;QAAOM;QAAOC;KAAO,CAACG,IAAI,CAAC,UAAU;IACjF,MAAMlB,QAAQjB,QAAQ;QACpB,IAAI,CAACyB,OAAO,OAAO;QACnB,MAAMW,SAAS,IAAIC,gBAAgB;YAAEZ;YAAOM;QAAM;QAClD,IAAIC,QAAQI,OAAOE,GAAG,CAAC,UAAUN;QACjC,OAAOI,OAAOG,QAAQ;IACxB,GAAG;QAACd;QAAOM;QAAOC;KAAO;IACzB,MAAM,CAACpB,MAAM4B,QAAQ,GAAGtC,SACtB;YAAOgC;YAAM5B;gBAAN4B,OAAAA,OAAM5B,mBAAAA,YAAYmC,GAAG,CAACP,yBAAhB5B,iBAAsBM,IAAI,GAAG8B,qBAAnCR,OAAiD/B;;IAG1DJ,UAAU;QACR,MAAM4C,WAAWf,QAAQC,OAAO;QAChC,IAAI,CAACK,OAAO,CAACS,UAAU,OAAOD;QAC9B,IAAI/B,QAAQL,YAAYmC,GAAG,CAACP;QAC5B,IAAI,CAACvB,OAAO;YACVA,QAAQ;gBAAEC,MAAMT;gBAASW,WAAW,IAAI8B;gBAAO1B,YAAY;YAAE;YAC7DZ,YAAYgC,GAAG,CAACJ,KAAKvB;QACvB;QACA,MAAMkC,SAASlC;QACf,MAAMmC,QAAQD,OAAO/B,SAAS,CAACiC,IAAI,KAAK;QACxCF,OAAO/B,SAAS,CAACkC,GAAG,CAACR;QACrBA,QAAQK,OAAOjC,IAAI;QACnB,IAAIkC,OAAO,KAAK/B,SAAS8B,QAAQF,UAAU1B;QAC3C,OAAO;YACL4B,OAAO/B,SAAS,CAACmC,MAAM,CAACT;QAC1B;IACF,GAAG;QAACN;QAAKjB;KAAM;IAEf,MAAMiC,SAASpD,YAAY;QACzB,MAAM6C,WAAWf,QAAQC,OAAO;QAChC,MAAMlB,QAAQuB,MAAM5B,YAAYmC,GAAG,CAACP,OAAOQ;QAC3C,IAAI/B,SAASgC,UAAU,KAAK5B,SAASJ,OAAOgC,UAAU1B;IACxD,GAAG;QAACiB;QAAKjB;KAAM;IAEf,MAAMkC,eAAenD,QACnB;;YAAeY;eAAT,IAAIL,IAAI,UAACK,aAAAA,KAAKP,IAAI,qBAATO,WAAWwC,IAAI,mBAAI,EAAE,EAAEC,GAAG,CAAC,CAACC,MAAQ;gBAACA,IAAI3B,GAAG;gBAAE2B,IAAIC,OAAO;aAAC;OACzE;QAAC3C,KAAKP,IAAI;KAAC;IAEb,MAAMmD,mBAAmBxD,QACvB;;YAEKY;eADH,IAAIL,IACF,UAACK,aAAAA,KAAKP,IAAI,qBAATO,WAAWwC,IAAI,mBAAI,EAAE,EAAEC,GAAG,CAAC,CAACC;gBAAkBA;mBAAV;gBAACA,IAAI3B,GAAG;iBAAE2B,mBAAAA,IAAIG,WAAW,YAAfH,mBAAmB;aAAE;;OAExE;QAAC1C,KAAKP,IAAI;KAAC;IAGb,OAAO;QACLD,QAAQ8B,MAAMtB,KAAKR,MAAM,GAAG;QAC5BC,MAAM6B,MAAMtB,KAAKP,IAAI,GAAG;QACxB0B;QACA2B,MAAM,YAAE9C,aAAAA,KAAKP,IAAI,qBAATO,WAAW8C,MAAM,oBAAI5B;QAC7BqB;QACAK;QACAN;IACF;AACF;AAEA,eAAe1B,cAAa"}
@@ -0,0 +1,18 @@
1
+ /** Loading, answered, or failed. A failure reads as a dash in every cell. */
2
+ export type StaffOrgsAiSpendStatus = 'loading' | 'ready' | 'error';
3
+ export interface StaffOrgsAiSpendState {
4
+ status: StaffOrgsAiSpendStatus;
5
+ /** The month the figures describe, once the route has answered. */
6
+ month: string | null;
7
+ /** Spend by org id as the route answered it; empty until it has. */
8
+ spendUsd: Readonly<Record<string, number | null>>;
9
+ }
10
+ /** Forget every shared read; specs start each case from nothing. */
11
+ export declare function resetStaffOrgsAiSpendReadsForTests(): void;
12
+ /**
13
+ * This month's AI spend for a page of orgs, through
14
+ * `/api/ai/admin/orgs-spend` — one request per reader and set of orgs,
15
+ * however many cells and headers ask.
16
+ */
17
+ export declare function useStaffOrgsAiSpend(orgIds: readonly string[] | null | undefined): StaffOrgsAiSpendState;
18
+ export default useStaffOrgsAiSpend;
@@ -0,0 +1,127 @@
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
+ */ 'use client';
17
+ import { authorizedFetch } from "@aglyn/shared-util-http/authorized-token";
18
+ import { useUser } from "@aglyn/tenant-feature-instance";
19
+ import { useEffect, useRef, useState } from "react";
20
+ import { staffOrgsAiSpendQuery } from "../usage/staff-orgs-ai-spend.js";
21
+ const LOADING = {
22
+ status: 'loading',
23
+ data: null
24
+ };
25
+ const NO_SPEND = Object.freeze({});
26
+ const sharedReads = new Map();
27
+ /** Forget every shared read; specs start each case from nothing. */ export function resetStaffOrgsAiSpendReadsForTests() {
28
+ sharedReads.clear();
29
+ }
30
+ function publish(entry, read) {
31
+ entry.read = read;
32
+ for (const listener of entry.listeners)listener(read);
33
+ }
34
+ async function readInto(entry, user, orgIds) {
35
+ entry.generation += 1;
36
+ const generation = entry.generation;
37
+ publish(entry, LOADING);
38
+ try {
39
+ const response = await authorizedFetch(user, `/api/ai/admin/orgs-spend?${staffOrgsAiSpendQuery(orgIds)}`);
40
+ const payload = response.ok ? await response.json().catch(()=>null) : null;
41
+ if (generation !== entry.generation) return;
42
+ const answered = payload !== null && typeof payload === 'object' && typeof payload.spendUsd === 'object' && payload.spendUsd !== null;
43
+ publish(entry, answered ? {
44
+ status: 'ready',
45
+ data: payload
46
+ } : {
47
+ status: 'error',
48
+ data: null
49
+ });
50
+ } catch (unused) {
51
+ if (generation === entry.generation) {
52
+ publish(entry, {
53
+ status: 'error',
54
+ data: null
55
+ });
56
+ }
57
+ }
58
+ }
59
+ /** The ids as one key: distinct and sorted, so the rows' order is not in it. */ function idsKeyOf(orgIds) {
60
+ const distinct = [
61
+ ...new Set((orgIds != null ? orgIds : []).filter((orgId)=>typeof orgId === 'string' && orgId.length > 0))
62
+ ].sort();
63
+ return distinct.length ? JSON.stringify(distinct) : '';
64
+ }
65
+ /**
66
+ * This month's AI spend for a page of orgs, through
67
+ * `/api/ai/admin/orgs-spend` — one request per reader and set of orgs,
68
+ * however many cells and headers ask.
69
+ */ export function useStaffOrgsAiSpend(orgIds) {
70
+ var _ref, _ref1, _ref2;
71
+ var _read_data, _read_data1;
72
+ const { data: user } = useUser();
73
+ // The read is keyed on WHO is signed in and WHICH orgs, never on an
74
+ // object's identity: a provider or a table that hands back a fresh object
75
+ // per render would otherwise re-run the effect on every paint.
76
+ const uid = (_ref = user == null ? void 0 : user.uid) != null ? _ref : null;
77
+ const userRef = useRef(user);
78
+ userRef.current = user;
79
+ const idsKey = idsKeyOf(orgIds);
80
+ const key = uid && idsKey ? `${uid}\x00${idsKey}` : null;
81
+ const [held, setHeld] = useState(()=>{
82
+ var _ref;
83
+ var _sharedReads_get;
84
+ return {
85
+ key,
86
+ read: (_ref = key ? (_sharedReads_get = sharedReads.get(key)) == null ? void 0 : _sharedReads_get.read : undefined) != null ? _ref : LOADING
87
+ };
88
+ });
89
+ useEffect(()=>{
90
+ const signedIn = userRef.current;
91
+ if (!key || !signedIn) return undefined;
92
+ let entry = sharedReads.get(key);
93
+ if (!entry) {
94
+ entry = {
95
+ read: LOADING,
96
+ listeners: new Set(),
97
+ generation: 0
98
+ };
99
+ sharedReads.set(key, entry);
100
+ }
101
+ const shared = entry;
102
+ const listener = (read)=>setHeld({
103
+ key,
104
+ read
105
+ });
106
+ const first = shared.listeners.size === 0;
107
+ shared.listeners.add(listener);
108
+ listener(shared.read);
109
+ if (first) void readInto(shared, signedIn, JSON.parse(idsKey));
110
+ return ()=>{
111
+ shared.listeners.delete(listener);
112
+ };
113
+ }, [
114
+ key,
115
+ idsKey
116
+ ]);
117
+ // A read held for another set of orgs says nothing about this one.
118
+ const read = held.key === key ? held.read : LOADING;
119
+ return {
120
+ status: key ? read.status : 'loading',
121
+ month: (_ref1 = (_read_data = read.data) == null ? void 0 : _read_data.month) != null ? _ref1 : null,
122
+ spendUsd: (_ref2 = (_read_data1 = read.data) == null ? void 0 : _read_data1.spendUsd) != null ? _ref2 : NO_SPEND
123
+ };
124
+ }
125
+ export default useStaffOrgsAiSpend;
126
+
127
+ //# sourceMappingURL=use-staff-orgs-ai-spend.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/components/use-staff-orgs-ai-spend.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'use client'\n\nimport { authorizedFetch } from '@aglyn/shared-util-http/authorized-token'\nimport { useUser } from '@aglyn/tenant-feature-instance'\nimport { useEffect, useRef, useState } from 'react'\nimport {\n staffOrgsAiSpendQuery,\n type StaffOrgsAiSpendWire,\n} from '../usage/staff-orgs-ai-spend'\n\n/** Loading, answered, or failed. A failure reads as a dash in every cell. */\nexport type StaffOrgsAiSpendStatus = 'loading' | 'ready' | 'error'\n\nexport interface StaffOrgsAiSpendState {\n status: StaffOrgsAiSpendStatus\n /** The month the figures describe, once the route has answered. */\n month: string | null\n /** Spend by org id as the route answered it; empty until it has. */\n spendUsd: Readonly<Record<string, number | null>>\n}\n\ninterface SpendRead {\n status: StaffOrgsAiSpendStatus\n data: StaffOrgsAiSpendWire | null\n}\n\n/**\n * One read of one page of orgs, shared by every mount that asks for it.\n *\n * The column is mounted once per ROW and once more for its header, so a read\n * per mount would send a request per org for the same page. Mounts for the\n * same reader and the same set of orgs subscribe to one entry instead: the\n * first subscriber reads, the rest take its answer. An answer that arrives\n * after a newer read of the same entry has started is dropped.\n */\ninterface SharedRead {\n read: SpendRead\n listeners: Set<(read: SpendRead) => void>\n generation: number\n}\n\nconst LOADING: SpendRead = { status: 'loading', data: null }\n\nconst NO_SPEND: Readonly<Record<string, number | null>> = Object.freeze({})\n\nconst sharedReads = new Map<string, SharedRead>()\n\n/** Forget every shared read; specs start each case from nothing. */\nexport function resetStaffOrgsAiSpendReadsForTests(): void {\n sharedReads.clear()\n}\n\nfunction publish(entry: SharedRead, read: SpendRead): void {\n entry.read = read\n for (const listener of entry.listeners) listener(read)\n}\n\nasync function readInto(\n entry: SharedRead,\n user: Parameters<typeof authorizedFetch>[0],\n orgIds: readonly string[],\n): Promise<void> {\n entry.generation += 1\n const generation = entry.generation\n publish(entry, LOADING)\n try {\n const response = await authorizedFetch(\n user,\n `/api/ai/admin/orgs-spend?${staffOrgsAiSpendQuery(orgIds)}`,\n )\n const payload = response.ok\n ? await response.json().catch(() => null)\n : null\n if (generation !== entry.generation) return\n const answered =\n payload !== null &&\n typeof payload === 'object' &&\n typeof payload.spendUsd === 'object' &&\n payload.spendUsd !== null\n publish(\n entry,\n answered\n ? { status: 'ready', data: payload as StaffOrgsAiSpendWire }\n : { status: 'error', data: null },\n )\n } catch {\n if (generation === entry.generation) {\n publish(entry, { status: 'error', data: null })\n }\n }\n}\n\n/** The ids as one key: distinct and sorted, so the rows' order is not in it. */\nfunction idsKeyOf(orgIds: readonly string[] | null | undefined): string {\n const distinct = [\n ...new Set(\n (orgIds ?? []).filter(\n (orgId) => typeof orgId === 'string' && orgId.length > 0,\n ),\n ),\n ].sort()\n return distinct.length ? JSON.stringify(distinct) : ''\n}\n\n/**\n * This month's AI spend for a page of orgs, through\n * `/api/ai/admin/orgs-spend` — one request per reader and set of orgs,\n * however many cells and headers ask.\n */\nexport function useStaffOrgsAiSpend(\n orgIds: readonly string[] | null | undefined,\n): StaffOrgsAiSpendState {\n const { data: user } = useUser()\n // The read is keyed on WHO is signed in and WHICH orgs, never on an\n // object's identity: a provider or a table that hands back a fresh object\n // per render would otherwise re-run the effect on every paint.\n const uid = user?.uid ?? null\n const userRef = useRef(user)\n userRef.current = user\n const idsKey = idsKeyOf(orgIds)\n const key = uid && idsKey ? `${uid}\\x00${idsKey}` : null\n const [held, setHeld] = useState<{ key: string | null; read: SpendRead }>(\n () => ({\n key,\n read: (key ? sharedReads.get(key)?.read : undefined) ?? LOADING,\n }),\n )\n\n useEffect(() => {\n const signedIn = userRef.current\n if (!key || !signedIn) return undefined\n let entry = sharedReads.get(key)\n if (!entry) {\n entry = { read: LOADING, listeners: new Set(), generation: 0 }\n sharedReads.set(key, entry)\n }\n const shared = entry\n const listener = (read: SpendRead) => setHeld({ key, read })\n const first = shared.listeners.size === 0\n shared.listeners.add(listener)\n listener(shared.read)\n if (first) void readInto(shared, signedIn, JSON.parse(idsKey) as string[])\n return () => {\n shared.listeners.delete(listener)\n }\n }, [key, idsKey])\n\n // A read held for another set of orgs says nothing about this one.\n const read = held.key === key ? held.read : LOADING\n return {\n status: key ? read.status : 'loading',\n month: read.data?.month ?? null,\n spendUsd: read.data?.spendUsd ?? NO_SPEND,\n }\n}\n\nexport default useStaffOrgsAiSpend\n"],"names":["authorizedFetch","useUser","useEffect","useRef","useState","staffOrgsAiSpendQuery","LOADING","status","data","NO_SPEND","Object","freeze","sharedReads","Map","resetStaffOrgsAiSpendReadsForTests","clear","publish","entry","read","listener","listeners","readInto","user","orgIds","generation","response","payload","ok","json","catch","answered","spendUsd","idsKeyOf","distinct","Set","filter","orgId","length","sort","JSON","stringify","useStaffOrgsAiSpend","uid","userRef","current","idsKey","key","held","setHeld","get","undefined","signedIn","set","shared","first","size","add","parse","delete","month"],"mappings":"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"}
@@ -0,0 +1,24 @@
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
+ /**
18
+ * The plugin's stable id — persisted in `org.enabledPlugins`, the document
19
+ * id under `pluginSettings`, and the owner every registry records. Matches
20
+ * `plugins.config.json` and `FIRST_PARTY_PLUGINS`.
21
+ */
22
+ export declare const AI_PLUGIN_ID = "ai";
23
+ /** The `pluginSettings/ai` document's schema id — the same string. */
24
+ export declare const AI_PLUGIN_SETTINGS_ID = "ai";
@@ -0,0 +1,23 @@
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 plugin's stable id — persisted in `org.enabledPlugins`, the document
18
+ * id under `pluginSettings`, and the owner every registry records. Matches
19
+ * `plugins.config.json` and `FIRST_PARTY_PLUGINS`.
20
+ */ export const AI_PLUGIN_ID = 'ai';
21
+ /** The `pluginSettings/ai` document's schema id — the same string. */ export const AI_PLUGIN_SETTINGS_ID = AI_PLUGIN_ID;
22
+
23
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../libs/plugins/ai/src/lib/constants.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * The plugin's stable id — persisted in `org.enabledPlugins`, the document\n * id under `pluginSettings`, and the owner every registry records. Matches\n * `plugins.config.json` and `FIRST_PARTY_PLUGINS`.\n */\nexport const AI_PLUGIN_ID = 'ai'\n\n/** The `pluginSettings/ai` document's schema id — the same string. */\nexport const AI_PLUGIN_SETTINGS_ID = AI_PLUGIN_ID\n"],"names":["AI_PLUGIN_ID","AI_PLUGIN_SETTINGS_ID"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED;;;;CAIC,GACD,OAAO,MAAMA,eAAe,KAAI;AAEhC,oEAAoE,GACpE,OAAO,MAAMC,wBAAwBD,aAAY"}