@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/jobs/ai-job-insight-step.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { ResolvedPluginFigureReader } from '@aglyn/aglyn/plugin-manager/plugin-figures'\nimport {\n AI_INSIGHT_ASK_SURFACES,\n AI_INSIGHT_DIGEST_DAYS,\n AI_INSIGHT_DIGEST_READERS,\n AI_INSIGHT_QUESTION_MAX_CHARS,\n AI_INSIGHTS_COLLECTION,\n aiInsightDays,\n aiInsightOutput,\n aiInsightSurface,\n aiInsightSurfaceNeedsSite,\n type AiInsightRecord,\n type AiInsightSurface,\n type AiInsightTable,\n} from '../model/ai-insight'\nimport { AI_ROUTING_TABLE, aiModelForStep } from '../providers/routing'\nimport {\n AI_ACCEPTABLE_USE_BLOCK,\n runAiRequest,\n type AiMessage,\n type AiResult,\n type AiSystemBlock,\n type AiUsage,\n} from '../runtime/ai-runtime'\nimport { AI_GENERATION_MAX_ATTEMPTS } from '../runtime/ai-generation-bounds'\nimport { checkAiInsightAnswer, type AiInsightCheck } from '../runtime/ai-insight-check'\nimport {\n AI_INSIGHT_ANSWER_TOOL_NAME,\n AI_INSIGHT_READ_TOOL_NAME,\n aiInsightAnswerTool,\n aiInsightReadTool,\n parseAiInsightAnswer,\n parseAiInsightReads,\n type AiInsightReadRequest,\n} from '../tools/ai-insight-tool'\nimport { aiDatasetCatalog } from '../insights/ai-figure-readers'\nimport {\n aiInsightDatasetCatalog,\n aiInsightReaderCatalog,\n aiInsightReaderDays,\n aiInsightReaders,\n aiInsightTableText,\n readAiInsightTables,\n} from '../insights/ai-insight-readers'\nimport { assistExchangeExpiry } from '../usage/assist-usage'\nimport { registerAiJobAdmission, type AiJobAdmissionContext, type AiJobAdmissionRefusal } from './ai-job-admission'\nimport { AI_INSIGHT_READ_MAX_TOKENS, AI_JOB_INSIGHT_STEP_BUDGET, AI_JOB_INSIGHT_STEP_MINIMUM_MS } from './ai-job-insight-budget'\nimport type { AiJobStepContext, AiJobStepOutcome, AiJobStepRunner } from './ai-job-text-step'\nimport { registerAiJobStep } from './ai-jobs'\n\n/**\n * The `insight` step (AGL-2915): a question about a site's figures, answered\n * from tables code read, with every insight traced to the rows it cites.\n *\n * ## Two exchanges, and the model never writes a query\n *\n * 1. **The reads.** The model is shown the question and the readers this job\n * may read — each an id, what it answers, its windows and parameters — and\n * answers `read_figures` with a choice among them. It names nothing else: no\n * collection, no field path, no filter. A choice that names no reader this\n * job may read is dropped, and a job left with none reads the surface's\n * defaults. A weekly digest makes no read call: code reads the digest's\n * readers.\n * 2. **The answer.** Code reads the tables through the owners' readers, and the\n * model is shown them and answers `submit_insights`. The trace\n * (`runtime/ai-insight-check.ts`) keeps each insight whose every number is\n * in a row it cites and leaves out the rest. An answer that is not a call,\n * or whose every insight was left out, is asked for once more with the\n * reasons; what the second answer keeps is the answer.\n *\n * Both calls share one allowance of output, twice the routing ceiling, which\n * is what the step's least time is planned against.\n *\n * ## What reaches the model\n *\n * The question, the names and descriptions of the readers, the tables, and\n * for a datasets question the names of the datasets the member may see with\n * their fields' names and types. A table holds counts, sums and rates labeled\n * by a page path, a referring site, a form's, a service's, a product's or a\n * campaign's name, or the values of a dataset field with at most sixty\n * different values that at least three records share. No\n * record, visitor, contact, order, booking, submission or recipient is read\n * into a prompt, and every text cell is masked of email addresses and phone\n * numbers on its way into a table.\n *\n * ## What it writes\n *\n * The answer, at `orgs/{orgId}/aiInsights/{jobId}` under the job's own\n * expiry, and an output that names it and says how many insights it holds.\n * Nothing else: no draft, no setting, no message.\n */\n\ntype Firestore = FirebaseFirestore.Firestore\n\nexport const AI_INSIGHT_NO_SURFACE_COPY = 'This question does not say which page it was asked from.'\nexport const AI_INSIGHT_NO_SITE_COPY = 'Open the site whose numbers you are asking about.'\nexport const AI_INSIGHT_NO_READERS_COPY =\n 'There are no figures to answer from here yet: the features this page reports on are not on for this workspace.'\nexport const AI_INSIGHT_NO_TABLES_COPY = 'The figures could not be read. Try again in a moment.'\nexport const AI_INSIGHT_UNREADABLE_COPY = 'The AI did not answer with insights. Try asking in different words.'\n\n/** The digest's question: what a week's insights cover, in the order a person reads them. */\nexport const AI_INSIGHT_DIGEST_QUESTION =\n 'What changed on this site this week? Write the week’s insights: the change in traffic, the most viewed page, the form that turned the most views into submissions, a campaign that did better than the rest, and any day that stood out — only those the tables support.'\n\n/** The rules both calls are sent: static, byte-identical for every workspace. */\nexport const AI_INSIGHT_RULES = [\n 'You answer a workspace owner’s questions about their own figures: page views, orders, bookings, forms, campaigns, A/B tests and datasets. You never see a record, and you never write a query: code reads figures through fixed readers and gives you their tables.',\n '',\n `When you are given a question and a list of readers, call ${AI_INSIGHT_READ_TOOL_NAME} once with the readers whose tables answer it, most useful first, and the window each should cover. Choose only readers from the list, with their parameters' values taken from what the list and the question give you.`,\n '',\n `When you are given tables, call ${AI_INSIGHT_ANSWER_TOOL_NAME} once. Each table has a handle (t1, t2, …) and numbered rows. Rules for the insights:`,\n '- Say what matters most to the question first. Leave out what the tables do not support.',\n '- Every insight cites the table and the rows its figures come from.',\n '- Every number you write appears in a row you cite, as the table shows it or rounded. Never add, subtract, average or otherwise compute a figure yourself. The only other numbers you may write are the length of a table’s window, a date in it, and how many rows you cite.',\n '- Say a figure rose or fell only when a change you quote shows it.',\n '- Name nobody, and write no email address or phone number.',\n '- Plain sentences: no markdown, no headings, no lists.',\n '- When the tables cannot answer part of the question, say so in gap in one sentence with no numbers; otherwise gap is null.',\n '- Write in the language of the question.',\n].join('\\n')\n\n/** The system blocks both calls send: the rules and the platform's acceptable-use rules. */\nexport const AI_JOB_INSIGHT_SYSTEM: AiSystemBlock[] = [\n { text: `${AI_INSIGHT_RULES}\\n\\n${AI_ACCEPTABLE_USE_BLOCK}`, cacheBreakpoint: true },\n]\n\nconst ZERO_USAGE: AiUsage = { inputTokens: 0, outputTokens: 0, cacheReadTokens: 0, cacheWriteTokens: 0 }\n\nconst str = (value: unknown): string => (typeof value === 'string' ? value.trim() : '')\n\n/** What the step's calls have spent so far, in the outcome's shape. */\nclass InsightSpend {\n usage: AiUsage = { ...ZERO_USAGE }\n estCostUsd = 0\n stopReason: string | null = null\n\n constructor(readonly model: string) {}\n\n add(result: AiResult): void {\n this.usage = {\n inputTokens: this.usage.inputTokens + result.usage.inputTokens,\n outputTokens: this.usage.outputTokens + result.usage.outputTokens,\n cacheReadTokens: this.usage.cacheReadTokens + result.usage.cacheReadTokens,\n cacheWriteTokens: this.usage.cacheWriteTokens + result.usage.cacheWriteTokens,\n }\n this.estCostUsd = Math.round((this.estCostUsd + result.estCostUsd) * 1_000_000) / 1_000_000\n this.stopReason = result.stopReason\n }\n\n outcome(): Pick<AiJobStepOutcome, 'usage' | 'estCostUsd' | 'model' | 'stopReason' | 'effort'> {\n return { usage: this.usage, estCostUsd: this.estCostUsd, model: this.model, stopReason: this.stopReason, effort: null }\n }\n}\n\n/** The read call's user turn: the question, the window asked for, the readers and, for datasets, the datasets. */\nexport function aiInsightReadPrompt(input: {\n question: string\n days: number\n readers: readonly ResolvedPluginFigureReader[]\n datasets: string | null\n}): string {\n return [\n `Question: ${input.question}`,\n `The window picked on the page: ${input.days} days. Use it unless the question names another window a reader lists.`,\n 'Readers you may read here:',\n aiInsightReaderCatalog(input.readers),\n ...(input.datasets === null ? [] : ['', 'Datasets you may read, with their fields:', input.datasets]),\n ].join('\\n')\n}\n\n/** The answer call's user turn: the question and every table. */\nexport function aiInsightAnswerPrompt(question: string, tables: readonly AiInsightTable[]): string {\n return [`Question: ${question}`, '', 'Tables:', '', tables.map(aiInsightTableText).join('\\n\\n')].join('\\n')\n}\n\n/** What a re-ask tells the model: why nothing it wrote could be kept. */\nexport function aiInsightReaskMessage(check: AiInsightCheck | null): string {\n const reasons = check?.findings.length\n ? `None of those insights could be kept: ${[...new Set(check.findings)].slice(0, 8).join('; ')}.`\n : `That answer did not come through ${AI_INSIGHT_ANSWER_TOOL_NAME}.`\n return `${reasons} Answer again with ${AI_INSIGHT_ANSWER_TOOL_NAME}: cite the rows each insight's figures are in, and write every number as a row you cite shows it.`\n}\n\n/** The reads a surface falls back to when the model named none it may read: the digest's own readers. */\nfunction defaultReads(readers: readonly ResolvedPluginFigureReader[], days: number): AiInsightReadRequest[] {\n const ids = readers.map(({ reader }) => reader.id)\n const preferred = AI_INSIGHT_DIGEST_READERS.filter((id) => ids.includes(id))\n const chosen = preferred.length ? preferred : ids\n return chosen.map((id) => ({\n reader: id,\n days: aiInsightReaderDays(readers.find(({ reader }) => reader.id === id)?.reader.windows ?? [], days),\n params: {},\n }))\n}\n\nasync function readHost(\n firestore: Firestore,\n orgId: string,\n hostId: string | null,\n): Promise<{ host: Record<string, unknown> | null; ok: boolean }> {\n if (!hostId) return { host: null, ok: true }\n const snapshot = await firestore.collection('hosts').doc(hostId).get()\n const host = snapshot.exists ? ((snapshot.data() ?? {}) as Record<string, unknown>) : null\n return { host, ok: Boolean(host) && host?.['orgId'] === orgId }\n}\n\nexport const runAiJobInsightStep: AiJobStepRunner = async (context: AiJobStepContext) => {\n const { job, firestore, signal, now } = context\n const model = context.modelFor?.('job.insight') ?? aiModelForStep('job.insight')\n const spend = new InsightSpend(model)\n const stop = (failure: string): AiJobStepOutcome => ({ outputs: [], ...spend.outcome(), failure })\n\n const surface = aiInsightSurface(job.inputs)\n if (!surface) return stop(AI_INSIGHT_NO_SURFACE_COPY)\n const hostId = job.hostId ?? null\n if (aiInsightSurfaceNeedsSite(surface) && !hostId) return stop(AI_INSIGHT_NO_SITE_COPY)\n // The door checks the caller belongs to the org; that the site does is\n // checked here, before anything about it is read.\n const site = await readHost(firestore, job.orgId, hostId)\n if (!site.ok) return stop(AI_INSIGHT_NO_SITE_COPY)\n const readers = await aiInsightReaders({\n orgId: job.orgId,\n hostId,\n org: context.org ?? null,\n host: site.host,\n surface,\n })\n if (!readers.length) return stop(AI_INSIGHT_NO_READERS_COPY)\n\n const digest = surface === 'digest'\n const days = digest ? AI_INSIGHT_DIGEST_DAYS : aiInsightDays(job.inputs?.['days'])\n const question = digest ? AI_INSIGHT_DIGEST_QUESTION : job.brief.slice(0, AI_INSIGHT_QUESTION_MAX_CHARS)\n const maxTokens = AI_JOB_INSIGHT_STEP_BUDGET.maxTokens(model)\n const allowance = AI_GENERATION_MAX_ATTEMPTS * maxTokens\n const left = () => allowance - spend.usage.outputTokens\n const ask = (messages: AiMessage[], tool: 'read' | 'answer', ceiling: number) =>\n runAiRequest({\n model,\n system: AI_JOB_INSIGHT_SYSTEM,\n messages,\n tools: [tool === 'read' ? aiInsightReadTool() : aiInsightAnswerTool()],\n maxTokens: Math.max(1, Math.min(ceiling, left())),\n ...(AI_ROUTING_TABLE['job.insight'].thinking ? { thinking: AI_ROUTING_TABLE['job.insight'].thinking } : {}),\n stream: false,\n ...(signal ? { signal } : {}),\n })\n\n // 1. The reads.\n const base = { orgId: job.orgId, hostId, uid: digest ? null : job.createdBy, now }\n let requests: AiInsightReadRequest[]\n if (digest) {\n requests = defaultReads(readers, days)\n } else {\n const datasets =\n surface === 'datasets'\n ? aiInsightDatasetCatalog(await aiDatasetCatalog(firestore, { orgId: job.orgId, hostId, uid: job.createdBy }))\n : null\n const result = await ask(\n [{ role: 'user', content: aiInsightReadPrompt({ question, days, readers, datasets }) }],\n 'read',\n AI_INSIGHT_READ_MAX_TOKENS,\n )\n spend.add(result)\n if (result.kind === 'refusal') return { outputs: [], ...spend.outcome(), refused: true }\n requests = parseAiInsightReads(result.toolUse.find((use) => use.name === AI_INSIGHT_READ_TOOL_NAME)?.input)\n }\n const maxTables = digest ? AI_INSIGHT_DIGEST_READERS.length : undefined\n let read = await readAiInsightTables(readers, requests, base, maxTables)\n if (!read.tables.length && !digest) read = await readAiInsightTables(readers, defaultReads(readers, days), base)\n if (read.refusals.length) console.warn('ai insight reads refused', { jobId: job.$id, refusals: read.refusals })\n if (!read.tables.length) return stop(AI_INSIGHT_NO_TABLES_COPY)\n const { tables } = read\n\n // 2. The answer, and at most one re-ask.\n let messages: AiMessage[] = [{ role: 'user', content: aiInsightAnswerPrompt(question, tables) }]\n let checked: AiInsightCheck | null = null\n for (let attempt = 0; attempt < AI_GENERATION_MAX_ATTEMPTS && left() > 0; attempt += 1) {\n const result = await ask(messages, 'answer', maxTokens)\n spend.add(result)\n if (result.kind === 'refusal') return { outputs: [], ...spend.outcome(), refused: true }\n const answer = parseAiInsightAnswer(result.toolUse.find((use) => use.name === AI_INSIGHT_ANSWER_TOOL_NAME)?.input)\n const check = answer ? checkAiInsightAnswer(answer, tables) : null\n if (check) checked = check\n if (check && (check.kept.length || !answer?.insights.length)) break\n messages = [\n ...messages,\n { role: 'assistant', content: `Answered with ${AI_INSIGHT_ANSWER_TOOL_NAME}.` },\n { role: 'user', content: aiInsightReaskMessage(check) },\n ]\n }\n if (!checked) return stop(AI_INSIGHT_UNREADABLE_COPY)\n\n const record: AiInsightRecord = {\n jobId: job.$id,\n orgId: job.orgId,\n hostId,\n surface,\n createdBy: job.createdBy,\n question: digest ? str(job.brief) || 'Weekly insights' : question,\n days,\n insights: checked.kept,\n gap: checked.gap,\n tables,\n left: checked.left.length,\n week: digest ? str(job.inputs?.['week']) || null : null,\n createdAtMs: now.getTime(),\n }\n if (checked.left.length) {\n console.info('ai insight left out untraced insights', { jobId: job.$id, findings: checked.findings })\n }\n // Keyed by the job, so a step run again replaces its own answer.\n await firestore\n .collection('orgs')\n .doc(job.orgId)\n .collection(AI_INSIGHTS_COLLECTION)\n .doc(job.$id)\n .set({ ...(JSON.parse(JSON.stringify(record)) as AiInsightRecord), expiresAt: job.expiresAt ?? assistExchangeExpiry(now) })\n return {\n outputs: [aiInsightOutput(job, record, str(site.host?.['subdomain']) || null)],\n ...spend.outcome(),\n }\n}\n\n/**\n * Whether a question may be asked here: a surface a person asks from, a site\n * of the job's own org where the surface needs one, and at least one reader\n * the workspace may read. A digest is made by the weekly sweep and never at a\n * door.\n */\nexport async function aiInsightAdmissionRefusal(\n context: AiJobAdmissionContext,\n): Promise<AiJobAdmissionRefusal | null> {\n const surface: AiInsightSurface | null = aiInsightSurface(context.inputs)\n if (!surface || !AI_INSIGHT_ASK_SURFACES.includes(surface)) {\n return { status: 400, error: 'Ask about your numbers from a site’s Analytics, Data or CRM Reports page.' }\n }\n if (aiInsightSurfaceNeedsSite(surface) && !context.hostId) {\n return { status: 400, error: AI_INSIGHT_NO_SITE_COPY }\n }\n const site = await readHost(context.firestore, context.orgId, context.hostId)\n if (!site.ok) return { status: 404, error: 'Unknown site' }\n const readers = await aiInsightReaders({\n orgId: context.orgId,\n hostId: context.hostId,\n org: context.org,\n host: site.host,\n surface,\n })\n return readers.length ? null : { status: 403, error: AI_INSIGHT_NO_READERS_COPY }\n}\n\n/**\n * The insight kind's registrations, called by the console surface\n * (`registerAiJobKinds` in `server.ts`), never made by importing this module\n * (AGL-3025).\n */\nexport function registerAiInsightJob(): void {\n registerAiJobStep('insight', runAiJobInsightStep, { minimumMs: AI_JOB_INSIGHT_STEP_MINIMUM_MS })\n registerAiJobAdmission('insight', aiInsightAdmissionRefusal)\n}\n"],"names":["AI_INSIGHT_ASK_SURFACES","AI_INSIGHT_DIGEST_DAYS","AI_INSIGHT_DIGEST_READERS","AI_INSIGHT_QUESTION_MAX_CHARS","AI_INSIGHTS_COLLECTION","aiInsightDays","aiInsightOutput","aiInsightSurface","aiInsightSurfaceNeedsSite","AI_ROUTING_TABLE","aiModelForStep","AI_ACCEPTABLE_USE_BLOCK","runAiRequest","AI_GENERATION_MAX_ATTEMPTS","checkAiInsightAnswer","AI_INSIGHT_ANSWER_TOOL_NAME","AI_INSIGHT_READ_TOOL_NAME","aiInsightAnswerTool","aiInsightReadTool","parseAiInsightAnswer","parseAiInsightReads","aiDatasetCatalog","aiInsightDatasetCatalog","aiInsightReaderCatalog","aiInsightReaderDays","aiInsightReaders","aiInsightTableText","readAiInsightTables","assistExchangeExpiry","registerAiJobAdmission","AI_INSIGHT_READ_MAX_TOKENS","AI_JOB_INSIGHT_STEP_BUDGET","AI_JOB_INSIGHT_STEP_MINIMUM_MS","registerAiJobStep","AI_INSIGHT_NO_SURFACE_COPY","AI_INSIGHT_NO_SITE_COPY","AI_INSIGHT_NO_READERS_COPY","AI_INSIGHT_NO_TABLES_COPY","AI_INSIGHT_UNREADABLE_COPY","AI_INSIGHT_DIGEST_QUESTION","AI_INSIGHT_RULES","join","AI_JOB_INSIGHT_SYSTEM","text","cacheBreakpoint","ZERO_USAGE","inputTokens","outputTokens","cacheReadTokens","cacheWriteTokens","str","value","trim","InsightSpend","add","result","usage","estCostUsd","Math","round","stopReason","outcome","model","effort","aiInsightReadPrompt","input","question","days","readers","datasets","aiInsightAnswerPrompt","tables","map","aiInsightReaskMessage","check","reasons","findings","length","Set","slice","defaultReads","ids","reader","id","preferred","filter","includes","chosen","find","windows","params","readHost","firestore","orgId","hostId","snapshot","host","ok","collection","doc","get","exists","data","Boolean","runAiJobInsightStep","context","job","site","signal","now","modelFor","spend","stop","failure","outputs","surface","inputs","org","digest","brief","maxTokens","allowance","left","ask","messages","tool","ceiling","system","tools","max","min","thinking","stream","base","uid","createdBy","requests","role","content","kind","refused","toolUse","use","name","maxTables","undefined","read","refusals","console","warn","jobId","$id","checked","attempt","answer","kept","insights","record","gap","week","createdAtMs","getTime","info","set","JSON","parse","stringify","expiresAt","aiInsightAdmissionRefusal","status","error","registerAiInsightJob","minimumMs"],"mappings":"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"}
@@ -0,0 +1,103 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ import { duplicateResource } from '@aglyn/tenant-data-admin/server/duplicate-resource';
18
+ import type { AiJob, AiJobPlan, AiJobReview } from '../model/ai-jobs.types';
19
+ import type { AiSiteInventory } from '../model/ai-site-inventory';
20
+ import { type AiValidatedTree } from '../runtime/ai-doctrine';
21
+ import { type AiDoctrineViolation } from '../runtime/ai-doctrine-validators';
22
+ import type { AiSystemBlock } from '../runtime/ai-runtime';
23
+ import { readSiteInventory } from '../runtime/site-inventory';
24
+ import { type AiJobAdmission } from './ai-job-admission';
25
+ import type { AiJobStepRunner } from './ai-job-text-step';
26
+ /**
27
+ * The layout step (AGL-2909): the generation step of a `layout` job, run once
28
+ * a member confirmed the job's plan.
29
+ *
30
+ * It builds ONE shared layout — a header with the site's navigation, the
31
+ * Layout Slot each page renders in, a footer — through
32
+ * `runValidatedGeneration('layout', …)`, so every building rule holds on the
33
+ * tree before it is kept, and adds three checks of its own through `extend`: a
34
+ * component the confirmed plan reuses is placed (rule 7), every region the
35
+ * plan gives the layout is built (AGL-3024), and a navigation or menu
36
+ * component the site already has is placed rather than drawn again (rule 1).
37
+ *
38
+ * The layout lands as a new draft (`ai-job-drafts.ts`): no screen uses it and
39
+ * no layout nests it, so nothing on the live site changes until a member
40
+ * assigns it. A plan that starts from a copy of a layout the site has gets
41
+ * that copy, through the platform's duplicate module, and nothing generated —
42
+ * so the copy is read back and held to the plan's regions the same way
43
+ * (`aiCopiedLayoutReview`), because a branch that generates nothing is the one
44
+ * branch where a promise can go unmet with no model to answer for it.
45
+ *
46
+ * A generation step runs on the job beat, never at an inline door: it
47
+ * registers the least time its lookup rounds, its answer and its re-ask need
48
+ * (AGL-3035), runs without extended thinking — the plan was reasoned out and
49
+ * confirmed before it — and asks for no more of a tighter ceiling than the
50
+ * doctrine's default for a layout than fits that time on the model it runs.
51
+ */
52
+ /** The longest answer a layout may run to; the tree is held to the layout budget either way. */
53
+ export declare const AI_JOB_LAYOUT_MAX_TOKENS: number;
54
+ /**
55
+ * The layout step's time (AGL-3035, AGL-3036): its two inventory-lookup
56
+ * rounds, its answer and its re-ask at the routing table's ceiling on the tier
57
+ * `job.layout` is served from, fitted to what a beat can give a step.
58
+ */
59
+ export declare const AI_JOB_LAYOUT_STEP_BUDGET: import("./ai-job-budget").AiJobStepBudget;
60
+ /** The least time one layout step needs before it starts. */
61
+ export declare const AI_JOB_LAYOUT_STEP_MINIMUM_MS: number;
62
+ /** A layout's name when the plan names none. */
63
+ export declare const AI_JOB_LAYOUT_DEFAULT_NAME = "Site layout";
64
+ /** The layout step's own instructions, cached after the doctrine. */
65
+ export declare const AI_JOB_LAYOUT_INSTRUCTIONS: readonly AiSystemBlock[];
66
+ /** The layout job as the generation's user turn: the name, the brief, the confirmed plan. */
67
+ export declare function aiJobLayoutPrompt(job: Pick<AiJob, 'brief'>, plan: AiJobPlan | null, name: string): string;
68
+ /**
69
+ * The layout door's checks on a tree the doctrine admitted: every component
70
+ * the confirmed plan reuses is placed, every region the confirmed plan gives
71
+ * the layout is built (AGL-3024), and navigation the site already keeps as a
72
+ * component is placed rather than drawn again in the header.
73
+ */
74
+ export declare function aiLayoutReuseCheck(inventory: AiSiteInventory | null, plan: AiJobPlan | null): (tree: AiValidatedTree) => AiDoctrineViolation[];
75
+ /**
76
+ * The regions the confirmed plan gives the layout, against the layout a COPY
77
+ * actually produced (AGL-3024); `null` when the copy keeps the plan, or when
78
+ * the plan promised no region to keep.
79
+ *
80
+ * The duplicate branch generates nothing, so it is the one place a plan's
81
+ * promise can go unmet without a model ever answering for it. A copy that
82
+ * cannot be read — deleted between the write and this read, or stored under a
83
+ * root this check does not know — settles nothing, and a promise this step
84
+ * cannot settle is reviewed by a person rather than reported as kept.
85
+ */
86
+ export declare function aiCopiedLayoutReview(firestore: FirebaseFirestore.Firestore, input: {
87
+ hostId: string;
88
+ id: string;
89
+ name: string;
90
+ plan: AiJobPlan | null;
91
+ }): Promise<AiJobReview | null>;
92
+ /** A layout job is admitted for a site of the job's own org with a shared layout to spare. */
93
+ export declare const aiLayoutJobAdmission: AiJobAdmission;
94
+ export interface AiJobLayoutStepDeps {
95
+ /** The inventory reader; specs hand in a fake. */
96
+ readInventory?: typeof readSiteInventory;
97
+ /** The platform's duplicate module, for a plan that starts from a copy. */
98
+ duplicate?: typeof duplicateResource;
99
+ }
100
+ export declare function createAiJobLayoutStep(deps?: AiJobLayoutStepDeps): AiJobStepRunner;
101
+ export declare const runAiJobLayoutStep: AiJobStepRunner;
102
+ /** Registers the layout step and the check a layout job passes before it is created or resumed. */
103
+ export declare function registerAiLayoutJob(): void;
@@ -0,0 +1,340 @@
1
+ import { _ as _extends } from "@swc/helpers/_/_extends";
2
+ /**
3
+ * @license
4
+ * Copyright 2026 Aglyn LLC
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */ import { CANVAS_ROOT_ELEMENT_ID } from "@aglyn/aglyn/foundation/constants/canvas";
18
+ import { duplicateResource } from "@aglyn/tenant-data-admin/server/duplicate-resource";
19
+ import { AI_STEP_TIERS } from "../providers/catalog.js";
20
+ import { AI_ROUTING_TABLE, aiModelForStep } from "../providers/routing.js";
21
+ import { aiDoctrineTreeTool, runValidatedGeneration } from "../runtime/ai-doctrine.js";
22
+ import { walkTree } from "../runtime/ai-doctrine-validators.js";
23
+ import { readSiteInventory } from "../runtime/site-inventory.js";
24
+ import { registerAiJobAdmission } from "./ai-job-admission.js";
25
+ import { aiJobDraftId } from "./ai-job-draft-ids.js";
26
+ import { aiDraftAdmissionRefusal, aiDraftAllowanceRefusal, aiSiteSubdomain, readAiDraft, readAiDraftNodes, writeAiDraft } from "./ai-job-drafts.js";
27
+ import { aiBracketedFactsNote, aiConfirmedPlan, aiDoctrineReview, aiGenerationSpent, aiJobBriefLine, aiLimitReview, aiModelNodeIds, aiPlacedComponentIds, aiPlanCreation, aiPlanReferenceLines, aiPlanReuseViolations, aiUnspentOutcome } from "./ai-job-generation.js";
28
+ import { aiPlanRegionViolations, aiPlannedLayoutRegions } from "./ai-job-plan-conformance.js";
29
+ import { aiJobStepBudget } from "./ai-job-budget.js";
30
+ import { registerAiJobStep } from "./ai-jobs.js";
31
+ /**
32
+ * The layout step (AGL-2909): the generation step of a `layout` job, run once
33
+ * a member confirmed the job's plan.
34
+ *
35
+ * It builds ONE shared layout — a header with the site's navigation, the
36
+ * Layout Slot each page renders in, a footer — through
37
+ * `runValidatedGeneration('layout', …)`, so every building rule holds on the
38
+ * tree before it is kept, and adds three checks of its own through `extend`: a
39
+ * component the confirmed plan reuses is placed (rule 7), every region the
40
+ * plan gives the layout is built (AGL-3024), and a navigation or menu
41
+ * component the site already has is placed rather than drawn again (rule 1).
42
+ *
43
+ * The layout lands as a new draft (`ai-job-drafts.ts`): no screen uses it and
44
+ * no layout nests it, so nothing on the live site changes until a member
45
+ * assigns it. A plan that starts from a copy of a layout the site has gets
46
+ * that copy, through the platform's duplicate module, and nothing generated —
47
+ * so the copy is read back and held to the plan's regions the same way
48
+ * (`aiCopiedLayoutReview`), because a branch that generates nothing is the one
49
+ * branch where a promise can go unmet with no model to answer for it.
50
+ *
51
+ * A generation step runs on the job beat, never at an inline door: it
52
+ * registers the least time its lookup rounds, its answer and its re-ask need
53
+ * (AGL-3035), runs without extended thinking — the plan was reasoned out and
54
+ * confirmed before it — and asks for no more of a tighter ceiling than the
55
+ * doctrine's default for a layout than fits that time on the model it runs.
56
+ */ /** The longest answer a layout may run to; the tree is held to the layout budget either way. */ export const AI_JOB_LAYOUT_MAX_TOKENS = AI_ROUTING_TABLE['job.layout'].maxTokens;
57
+ /**
58
+ * The layout step's time (AGL-3035, AGL-3036): its two inventory-lookup
59
+ * rounds, its answer and its re-ask at the routing table's ceiling on the tier
60
+ * `job.layout` is served from, fitted to what a beat can give a step.
61
+ */ export const AI_JOB_LAYOUT_STEP_BUDGET = aiJobStepBudget({
62
+ tier: AI_STEP_TIERS['job.layout'],
63
+ maxTokens: AI_JOB_LAYOUT_MAX_TOKENS
64
+ });
65
+ /** The least time one layout step needs before it starts. */ export const AI_JOB_LAYOUT_STEP_MINIMUM_MS = AI_JOB_LAYOUT_STEP_BUDGET.minimumMs;
66
+ /** A layout's name when the plan names none. */ export const AI_JOB_LAYOUT_DEFAULT_NAME = 'Site layout';
67
+ /** The layout step's own instructions, cached after the doctrine. */ export const AI_JOB_LAYOUT_INSTRUCTIONS = [
68
+ {
69
+ text: [
70
+ 'You build one shared layout for a website: the frame every page of the site renders inside. Answer with submit_layout: the whole layout as one flat node map.',
71
+ 'A layout is a header, one Layout Slot and a footer, top to bottom. The header is an App Bar (muiAppBar) holding a Toolbar Content (muiToolbar) with the site’s name as text and its navigation. The footer is a Section (section) whose element is footer.',
72
+ 'Navigation links the site’s own screens by id: a Screen Link (muiScreenLink) whose screenId is a screen id from the site inventory, in the order the brief and the confirmed plan give, seven at most in the header. Never invent a screen id, and never link a screen by its address.',
73
+ 'When the site inventory lists a component whose name says it is navigation, a menu or a mega menu, place it in the header as an instance instead of building the navigation again. Place every component the confirmed plan reuses.',
74
+ 'The Layout Slot (layoutSlot) is where each page renders and is the page’s main landmark: leave its component unset or main, and put nothing inside it. A layout carries no h1, because every page brings its own.'
75
+ ].join('\n')
76
+ }
77
+ ];
78
+ /** The layout job as the generation's user turn: the name, the brief, the confirmed plan. */ export function aiJobLayoutPrompt(job, plan, name) {
79
+ return [
80
+ `Layout name: ${name}`,
81
+ aiJobBriefLine(job),
82
+ ...aiPlanReferenceLines(plan)
83
+ ].join('\n');
84
+ }
85
+ /** A component name that says it is the site's navigation; a footer's links are not. */ const NAVIGATION_NAME = /\b(?:nav|navigation|navbar|menu|mega ?menu)\b/i;
86
+ const FOOTER_NAME = /\bfooter\b/i;
87
+ /** A node that links somewhere: a Screen Link, or a Button pointed at a screen or an address. */ function isLink(node) {
88
+ var _node_props, _node_props1;
89
+ if (node.componentId === 'muiScreenLink') return true;
90
+ return node.componentId === 'muiButton' && (typeof ((_node_props = node.props) == null ? void 0 : _node_props['screenId']) === 'string' || typeof ((_node_props1 = node.props) == null ? void 0 : _node_props1['href']) === 'string');
91
+ }
92
+ /**
93
+ * The layout door's checks on a tree the doctrine admitted: every component
94
+ * the confirmed plan reuses is placed, every region the confirmed plan gives
95
+ * the layout is built (AGL-3024), and navigation the site already keeps as a
96
+ * component is placed rather than drawn again in the header.
97
+ */ export function aiLayoutReuseCheck(inventory, plan) {
98
+ var _ref;
99
+ const components = (_ref = inventory == null ? void 0 : inventory.components) != null ? _ref : [];
100
+ const navigation = components.filter((component)=>NAVIGATION_NAME.test(component.name) && !FOOTER_NAME.test(component.name));
101
+ return (tree)=>{
102
+ const placed = aiPlacedComponentIds(tree);
103
+ const violations = [
104
+ ...aiPlanReuseViolations(inventory, plan, placed, 'layout'),
105
+ ...aiPlanRegionViolations(plan, {
106
+ rootId: tree.rootId,
107
+ nodes: tree.nodes
108
+ })
109
+ ];
110
+ if (navigation.length && !navigation.some((component)=>placed.has(component.id))) {
111
+ const visits = walkTree({
112
+ rootId: tree.rootId,
113
+ nodes: tree.nodes
114
+ });
115
+ const slot = visits.findIndex(({ node })=>node.componentId === 'layoutSlot');
116
+ const header = slot === -1 ? visits : visits.slice(0, slot);
117
+ const links = header.filter(({ node })=>isLink(node)).map(({ id })=>id);
118
+ if (links.length >= 2) {
119
+ violations.push({
120
+ rule: 1,
121
+ code: 'navigation-rebuilt',
122
+ message: `The site already has the "${navigation[0].name}" component. Place it in the header instead of building the navigation again.`,
123
+ nodeIds: aiModelNodeIds(links, tree.sourceIds)
124
+ });
125
+ }
126
+ }
127
+ return violations;
128
+ };
129
+ }
130
+ /**
131
+ * The regions the confirmed plan gives the layout, against the layout a COPY
132
+ * actually produced (AGL-3024); `null` when the copy keeps the plan, or when
133
+ * the plan promised no region to keep.
134
+ *
135
+ * The duplicate branch generates nothing, so it is the one place a plan's
136
+ * promise can go unmet without a model ever answering for it. A copy that
137
+ * cannot be read — deleted between the write and this read, or stored under a
138
+ * root this check does not know — settles nothing, and a promise this step
139
+ * cannot settle is reviewed by a person rather than reported as kept.
140
+ */ export async function aiCopiedLayoutReview(firestore, input) {
141
+ var _ref;
142
+ const planned = aiPlannedLayoutRegions(input.plan);
143
+ if (!planned.regions.length && !planned.unreadable.length) return null;
144
+ const stored = await readAiDraftNodes(firestore, {
145
+ kind: 'layout',
146
+ hostId: input.hostId,
147
+ id: input.id
148
+ });
149
+ const nodes = (_ref = stored == null ? void 0 : stored.nodes) != null ? _ref : {};
150
+ if (!nodes[CANVAS_ROOT_ELEMENT_ID]) {
151
+ return {
152
+ reason: 'doctrine',
153
+ message: `"${input.name}" was copied from the layout the plan names, and this job could not read the copy back to check it has the regions the plan gives it. Open the layout and check it before you put a page in it.`,
154
+ findings: []
155
+ };
156
+ }
157
+ const violations = aiPlanRegionViolations(input.plan, {
158
+ rootId: CANVAS_ROOT_ELEMENT_ID,
159
+ nodes
160
+ });
161
+ if (!violations.length) return null;
162
+ return aiDoctrineReview({
163
+ message: `"${input.name}" is a copy of the layout the plan names, and a copy is all it is: ${violations[0].message}`,
164
+ violations
165
+ });
166
+ }
167
+ /** A layout job is admitted for a site of the job's own org with a shared layout to spare. */ export const aiLayoutJobAdmission = (context)=>aiDraftAdmissionRefusal(context.firestore, {
168
+ orgId: context.orgId,
169
+ hostId: context.hostId,
170
+ kind: 'layout',
171
+ org: context.org
172
+ });
173
+ export function createAiJobLayoutStep(deps = {}) {
174
+ var _deps_readInventory, _deps_duplicate;
175
+ const readInventory = (_deps_readInventory = deps.readInventory) != null ? _deps_readInventory : readSiteInventory;
176
+ const duplicate = (_deps_duplicate = deps.duplicate) != null ? _deps_duplicate : duplicateResource;
177
+ return async ({ job, now, signal, firestore, modelFor })=>{
178
+ var _ref, _orgSnapshot_data;
179
+ const hostId = job.hostId;
180
+ if (!hostId) throw new Error('a layout job names no site, and its admission refuses one');
181
+ const output = (draft, load, note)=>_extends({
182
+ resource: 'layout',
183
+ id: draft.id,
184
+ versionId: draft.versionId,
185
+ hostId,
186
+ hostSubdomain: draft.hostSubdomain,
187
+ label: draft.name
188
+ }, load ? {
189
+ load
190
+ } : {}, note ? {
191
+ note
192
+ } : {});
193
+ // The switch's answer for this job, else the routing table's (AGL-2942).
194
+ const model = (_ref = modelFor == null ? void 0 : modelFor('job.layout')) != null ? _ref : aiModelForStep('job.layout');
195
+ // A run cut off after its draft was written reports that draft, found by the id the job recorded.
196
+ const draftId = aiJobDraftId(job, 'layout');
197
+ const written = await readAiDraft(firestore, {
198
+ kind: 'layout',
199
+ hostId,
200
+ id: draftId
201
+ });
202
+ if (written) return aiUnspentOutcome(model, {
203
+ outputs: [
204
+ output(written)
205
+ ]
206
+ });
207
+ const [inventory, orgSnapshot] = await Promise.all([
208
+ readInventory(job.orgId, hostId, {
209
+ firestore
210
+ }),
211
+ firestore.collection('orgs').doc(job.orgId).get()
212
+ ]);
213
+ const org = (_orgSnapshot_data = orgSnapshot.data()) != null ? _orgSnapshot_data : null;
214
+ const plan = aiConfirmedPlan(job);
215
+ const creation = aiPlanCreation(plan, 'layout');
216
+ const name = (creation == null ? void 0 : creation.name) || AI_JOB_LAYOUT_DEFAULT_NAME;
217
+ // The plan starts from a copy of a layout the site has (rule 15): the copy
218
+ // is the draft, and nothing is generated. A source gone since the plan
219
+ // was made is built from the brief instead.
220
+ if ((creation == null ? void 0 : creation.duplicateOf) && inventory.layouts.some((layout)=>layout.id === creation.duplicateOf)) {
221
+ const copy = await duplicate('layout', {
222
+ orgId: job.orgId,
223
+ hostId,
224
+ sourceId: creation.duplicateOf,
225
+ name,
226
+ uid: job.createdBy,
227
+ org: org
228
+ });
229
+ if (copy.ok) {
230
+ // A copy is not a build (AGL-3024). This branch generates nothing, so
231
+ // whatever the plan promised BEYOND the source is not in the draft
232
+ // unless the source already had it: a plan reading "from a copy of the
233
+ // base layout, adding a sidebar" gets the base layout, the sidebar
234
+ // nowhere in it, and until now reported Done. The copy's own regions
235
+ // answer the plan's, and a copy that cannot be read answers nothing —
236
+ // which is a stop for a person, never a Done.
237
+ const review = await aiCopiedLayoutReview(firestore, {
238
+ hostId,
239
+ id: copy.id,
240
+ plan,
241
+ name
242
+ });
243
+ if (review) return aiUnspentOutcome(model, {
244
+ review
245
+ });
246
+ const hostSubdomain = await aiSiteSubdomain(firestore, hostId);
247
+ return aiUnspentOutcome(model, {
248
+ outputs: [
249
+ output({
250
+ id: copy.id,
251
+ versionId: copy.versionId,
252
+ name: copy.name,
253
+ hostSubdomain
254
+ })
255
+ ]
256
+ });
257
+ }
258
+ if (copy.ok === false && copy.status === 403) {
259
+ return aiUnspentOutcome(model, {
260
+ review: aiLimitReview(copy.error)
261
+ });
262
+ }
263
+ }
264
+ const allowance = await aiDraftAllowanceRefusal(firestore, {
265
+ kind: 'layout',
266
+ hostId,
267
+ org
268
+ });
269
+ if (allowance) return aiUnspentOutcome(model, {
270
+ review: aiLimitReview(allowance)
271
+ });
272
+ const result = await runValidatedGeneration('layout', _extends({
273
+ step: 'job.layout',
274
+ model,
275
+ instructions: AI_JOB_LAYOUT_INSTRUCTIONS,
276
+ inventory,
277
+ messages: [
278
+ {
279
+ role: 'user',
280
+ content: aiJobLayoutPrompt(job, plan, name)
281
+ }
282
+ ],
283
+ tool: aiDoctrineTreeTool('layout'),
284
+ maxTokens: AI_JOB_LAYOUT_STEP_BUDGET.maxTokens(model)
285
+ }, AI_ROUTING_TABLE['job.layout'].thinking ? {
286
+ thinking: AI_ROUTING_TABLE['job.layout'].thinking
287
+ } : {}, AI_ROUTING_TABLE['job.layout'].effort ? {
288
+ effort: AI_ROUTING_TABLE['job.layout'].effort
289
+ } : {}, {
290
+ extend: aiLayoutReuseCheck(inventory, plan)
291
+ }, signal ? {
292
+ signal
293
+ } : {}));
294
+ const spent = aiGenerationSpent(result);
295
+ if (result.status === 'refused') return _extends({}, spent, {
296
+ refused: true
297
+ });
298
+ if (result.status === 'needs_input') return _extends({}, spent, {
299
+ review: aiDoctrineReview(result)
300
+ });
301
+ const draft = await writeAiDraft(firestore, {
302
+ kind: 'layout',
303
+ hostId,
304
+ id: draftId,
305
+ uid: job.createdBy,
306
+ org,
307
+ name,
308
+ nodes: result.value.nodes,
309
+ now
310
+ });
311
+ if (draft.ok === false) {
312
+ if (draft.status === 404) throw new Error(`site ${hostId} vanished while its layout was generated`);
313
+ return _extends({}, spent, {
314
+ review: aiLimitReview(draft.error)
315
+ });
316
+ }
317
+ // The facts the brief did not give, which the member fills before publishing (AGL-3056).
318
+ const note = aiBracketedFactsNote({
319
+ tree: {
320
+ rootId: result.value.rootId,
321
+ nodes: result.value.nodes
322
+ },
323
+ inventory
324
+ });
325
+ return _extends({}, spent, {
326
+ outputs: [
327
+ output(draft, result.value.load, note)
328
+ ]
329
+ });
330
+ };
331
+ }
332
+ export const runAiJobLayoutStep = createAiJobLayoutStep();
333
+ /** Registers the layout step and the check a layout job passes before it is created or resumed. */ export function registerAiLayoutJob() {
334
+ registerAiJobStep('layout', runAiJobLayoutStep, {
335
+ minimumMs: AI_JOB_LAYOUT_STEP_MINIMUM_MS
336
+ });
337
+ registerAiJobAdmission('layout', aiLayoutJobAdmission);
338
+ }
339
+
340
+ //# sourceMappingURL=ai-job-layout-step.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/jobs/ai-job-layout-step.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { CANVAS_ROOT_ELEMENT_ID } from '@aglyn/aglyn/foundation/constants/canvas'\nimport type { AglynOrgBilling } from '@aglyn/aglyn/foundation/definitions/org-billing.types'\nimport { duplicateResource } from '@aglyn/tenant-data-admin/server/duplicate-resource'\nimport type { AiJob, AiJobOutput, AiJobPlan, AiJobReview } from '../model/ai-jobs.types'\nimport type { AiSiteInventory } from '../model/ai-site-inventory'\nimport { AI_STEP_TIERS } from '../providers/catalog'\nimport { AI_ROUTING_TABLE, aiModelForStep } from '../providers/routing'\nimport {\n aiDoctrineTreeTool,\n runValidatedGeneration,\n type AiValidatedTree,\n} from '../runtime/ai-doctrine'\nimport {\n walkTree,\n type AiDoctrineNode,\n type AiDoctrineTree,\n type AiDoctrineViolation,\n} from '../runtime/ai-doctrine-validators'\nimport type { AiLoadEstimate } from '../runtime/ai-palette'\nimport type { AiSystemBlock } from '../runtime/ai-runtime'\nimport { readSiteInventory } from '../runtime/site-inventory'\nimport { registerAiJobAdmission, type AiJobAdmission } from './ai-job-admission'\nimport { aiJobDraftId } from './ai-job-draft-ids'\nimport {\n aiDraftAdmissionRefusal,\n aiDraftAllowanceRefusal,\n aiSiteSubdomain,\n readAiDraft,\n readAiDraftNodes,\n writeAiDraft,\n type AiDraftRecord,\n} from './ai-job-drafts'\nimport {\n aiBracketedFactsNote,\n aiConfirmedPlan,\n aiDoctrineReview,\n aiGenerationSpent,\n aiJobBriefLine,\n aiLimitReview,\n aiModelNodeIds,\n aiPlacedComponentIds,\n aiPlanCreation,\n aiPlanReferenceLines,\n aiPlanReuseViolations,\n aiUnspentOutcome,\n} from './ai-job-generation'\nimport { aiPlanRegionViolations, aiPlannedLayoutRegions } from './ai-job-plan-conformance'\nimport type { AiJobStepRunner } from './ai-job-text-step'\nimport { aiJobStepBudget } from './ai-job-budget'\nimport { registerAiJobStep } from './ai-jobs'\n\n/**\n * The layout step (AGL-2909): the generation step of a `layout` job, run once\n * a member confirmed the job's plan.\n *\n * It builds ONE shared layout — a header with the site's navigation, the\n * Layout Slot each page renders in, a footer — through\n * `runValidatedGeneration('layout', …)`, so every building rule holds on the\n * tree before it is kept, and adds three checks of its own through `extend`: a\n * component the confirmed plan reuses is placed (rule 7), every region the\n * plan gives the layout is built (AGL-3024), and a navigation or menu\n * component the site already has is placed rather than drawn again (rule 1).\n *\n * The layout lands as a new draft (`ai-job-drafts.ts`): no screen uses it and\n * no layout nests it, so nothing on the live site changes until a member\n * assigns it. A plan that starts from a copy of a layout the site has gets\n * that copy, through the platform's duplicate module, and nothing generated —\n * so the copy is read back and held to the plan's regions the same way\n * (`aiCopiedLayoutReview`), because a branch that generates nothing is the one\n * branch where a promise can go unmet with no model to answer for it.\n *\n * A generation step runs on the job beat, never at an inline door: it\n * registers the least time its lookup rounds, its answer and its re-ask need\n * (AGL-3035), runs without extended thinking — the plan was reasoned out and\n * confirmed before it — and asks for no more of a tighter ceiling than the\n * doctrine's default for a layout than fits that time on the model it runs.\n */\n\n/** The longest answer a layout may run to; the tree is held to the layout budget either way. */\nexport const AI_JOB_LAYOUT_MAX_TOKENS = AI_ROUTING_TABLE['job.layout'].maxTokens\n\n/**\n * The layout step's time (AGL-3035, AGL-3036): its two inventory-lookup\n * rounds, its answer and its re-ask at the routing table's ceiling on the tier\n * `job.layout` is served from, fitted to what a beat can give a step.\n */\nexport const AI_JOB_LAYOUT_STEP_BUDGET = aiJobStepBudget({\n tier: AI_STEP_TIERS['job.layout'],\n maxTokens: AI_JOB_LAYOUT_MAX_TOKENS,\n})\n\n/** The least time one layout step needs before it starts. */\nexport const AI_JOB_LAYOUT_STEP_MINIMUM_MS = AI_JOB_LAYOUT_STEP_BUDGET.minimumMs\n\n/** A layout's name when the plan names none. */\nexport const AI_JOB_LAYOUT_DEFAULT_NAME = 'Site layout'\n\n/** The layout step's own instructions, cached after the doctrine. */\nexport const AI_JOB_LAYOUT_INSTRUCTIONS: readonly AiSystemBlock[] = [\n {\n text: [\n 'You build one shared layout for a website: the frame every page of the site renders inside. Answer with submit_layout: the whole layout as one flat node map.',\n 'A layout is a header, one Layout Slot and a footer, top to bottom. The header is an App Bar (muiAppBar) holding a Toolbar Content (muiToolbar) with the site’s name as text and its navigation. The footer is a Section (section) whose element is footer.',\n 'Navigation links the site’s own screens by id: a Screen Link (muiScreenLink) whose screenId is a screen id from the site inventory, in the order the brief and the confirmed plan give, seven at most in the header. Never invent a screen id, and never link a screen by its address.',\n 'When the site inventory lists a component whose name says it is navigation, a menu or a mega menu, place it in the header as an instance instead of building the navigation again. Place every component the confirmed plan reuses.',\n 'The Layout Slot (layoutSlot) is where each page renders and is the page’s main landmark: leave its component unset or main, and put nothing inside it. A layout carries no h1, because every page brings its own.',\n ].join('\\n'),\n },\n]\n\n/** The layout job as the generation's user turn: the name, the brief, the confirmed plan. */\nexport function aiJobLayoutPrompt(\n job: Pick<AiJob, 'brief'>,\n plan: AiJobPlan | null,\n name: string,\n): string {\n return [`Layout name: ${name}`, aiJobBriefLine(job), ...aiPlanReferenceLines(plan)].join('\\n')\n}\n\n/** A component name that says it is the site's navigation; a footer's links are not. */\nconst NAVIGATION_NAME = /\\b(?:nav|navigation|navbar|menu|mega ?menu)\\b/i\nconst FOOTER_NAME = /\\bfooter\\b/i\n\n/** A node that links somewhere: a Screen Link, or a Button pointed at a screen or an address. */\nfunction isLink(node: AiDoctrineNode): boolean {\n if (node.componentId === 'muiScreenLink') return true\n return (\n node.componentId === 'muiButton' &&\n (typeof node.props?.['screenId'] === 'string' || typeof node.props?.['href'] === 'string')\n )\n}\n\n/**\n * The layout door's checks on a tree the doctrine admitted: every component\n * the confirmed plan reuses is placed, every region the confirmed plan gives\n * the layout is built (AGL-3024), and navigation the site already keeps as a\n * component is placed rather than drawn again in the header.\n */\nexport function aiLayoutReuseCheck(\n inventory: AiSiteInventory | null,\n plan: AiJobPlan | null,\n): (tree: AiValidatedTree) => AiDoctrineViolation[] {\n const components = inventory?.components ?? []\n const navigation = components.filter(\n (component) => NAVIGATION_NAME.test(component.name) && !FOOTER_NAME.test(component.name),\n )\n return (tree) => {\n const placed = aiPlacedComponentIds(tree)\n const violations: AiDoctrineViolation[] = [\n ...aiPlanReuseViolations(inventory, plan, placed, 'layout'),\n ...aiPlanRegionViolations(plan, {\n rootId: tree.rootId,\n nodes: tree.nodes as unknown as Record<string, AiDoctrineNode>,\n }),\n ]\n if (navigation.length && !navigation.some((component) => placed.has(component.id))) {\n const visits = walkTree({\n rootId: tree.rootId,\n nodes: tree.nodes as unknown as Record<string, AiDoctrineNode>,\n })\n const slot = visits.findIndex(({ node }) => node.componentId === 'layoutSlot')\n const header = slot === -1 ? visits : visits.slice(0, slot)\n const links = header.filter(({ node }) => isLink(node)).map(({ id }) => id)\n if (links.length >= 2) {\n violations.push({\n rule: 1,\n code: 'navigation-rebuilt',\n message: `The site already has the \"${navigation[0].name}\" component. Place it in the header instead of building the navigation again.`,\n nodeIds: aiModelNodeIds(links, tree.sourceIds),\n })\n }\n }\n return violations\n }\n}\n\n/**\n * The regions the confirmed plan gives the layout, against the layout a COPY\n * actually produced (AGL-3024); `null` when the copy keeps the plan, or when\n * the plan promised no region to keep.\n *\n * The duplicate branch generates nothing, so it is the one place a plan's\n * promise can go unmet without a model ever answering for it. A copy that\n * cannot be read — deleted between the write and this read, or stored under a\n * root this check does not know — settles nothing, and a promise this step\n * cannot settle is reviewed by a person rather than reported as kept.\n */\nexport async function aiCopiedLayoutReview(\n firestore: FirebaseFirestore.Firestore,\n input: { hostId: string; id: string; name: string; plan: AiJobPlan | null },\n): Promise<AiJobReview | null> {\n const planned = aiPlannedLayoutRegions(input.plan)\n if (!planned.regions.length && !planned.unreadable.length) return null\n const stored = await readAiDraftNodes(firestore, {\n kind: 'layout',\n hostId: input.hostId,\n id: input.id,\n })\n const nodes = (stored?.nodes ?? {}) as unknown as Record<string, AiDoctrineNode>\n if (!nodes[CANVAS_ROOT_ELEMENT_ID]) {\n return {\n reason: 'doctrine',\n message: `\"${input.name}\" was copied from the layout the plan names, and this job could not read the copy back to check it has the regions the plan gives it. Open the layout and check it before you put a page in it.`,\n findings: [],\n }\n }\n const violations = aiPlanRegionViolations(input.plan, { rootId: CANVAS_ROOT_ELEMENT_ID, nodes })\n if (!violations.length) return null\n return aiDoctrineReview({\n message: `\"${input.name}\" is a copy of the layout the plan names, and a copy is all it is: ${violations[0].message}`,\n violations,\n })\n}\n\n/** A layout job is admitted for a site of the job's own org with a shared layout to spare. */\nexport const aiLayoutJobAdmission: AiJobAdmission = (context) =>\n aiDraftAdmissionRefusal(context.firestore, {\n orgId: context.orgId,\n hostId: context.hostId,\n kind: 'layout',\n org: context.org,\n })\n\nexport interface AiJobLayoutStepDeps {\n /** The inventory reader; specs hand in a fake. */\n readInventory?: typeof readSiteInventory\n /** The platform's duplicate module, for a plan that starts from a copy. */\n duplicate?: typeof duplicateResource\n}\n\nexport function createAiJobLayoutStep(deps: AiJobLayoutStepDeps = {}): AiJobStepRunner {\n const readInventory = deps.readInventory ?? readSiteInventory\n const duplicate = deps.duplicate ?? duplicateResource\n return async ({ job, now, signal, firestore, modelFor }) => {\n const hostId = job.hostId\n if (!hostId) throw new Error('a layout job names no site, and its admission refuses one')\n const output = (draft: AiDraftRecord, load?: AiLoadEstimate | null, note?: string | null): AiJobOutput => ({\n resource: 'layout',\n id: draft.id,\n versionId: draft.versionId,\n hostId,\n hostSubdomain: draft.hostSubdomain,\n label: draft.name,\n ...(load ? { load } : {}),\n ...(note ? { note } : {}),\n })\n // The switch's answer for this job, else the routing table's (AGL-2942).\n const model = modelFor?.('job.layout') ?? aiModelForStep('job.layout')\n\n // A run cut off after its draft was written reports that draft, found by the id the job recorded.\n const draftId = aiJobDraftId(job, 'layout')\n const written = await readAiDraft(firestore, { kind: 'layout', hostId, id: draftId })\n if (written) return aiUnspentOutcome(model, { outputs: [output(written)] })\n\n const [inventory, orgSnapshot] = await Promise.all([\n readInventory(job.orgId, hostId, { firestore }),\n firestore.collection('orgs').doc(job.orgId).get(),\n ])\n const org = (orgSnapshot.data() ?? null) as Partial<AglynOrgBilling> | null\n const plan = aiConfirmedPlan(job)\n const creation = aiPlanCreation(plan, 'layout')\n const name = creation?.name || AI_JOB_LAYOUT_DEFAULT_NAME\n\n // The plan starts from a copy of a layout the site has (rule 15): the copy\n // is the draft, and nothing is generated. A source gone since the plan\n // was made is built from the brief instead.\n if (creation?.duplicateOf && inventory.layouts.some((layout) => layout.id === creation.duplicateOf)) {\n const copy = await duplicate('layout', {\n orgId: job.orgId,\n hostId,\n sourceId: creation.duplicateOf,\n name,\n uid: job.createdBy,\n org: org as Record<string, unknown> | null,\n })\n if (copy.ok) {\n // A copy is not a build (AGL-3024). This branch generates nothing, so\n // whatever the plan promised BEYOND the source is not in the draft\n // unless the source already had it: a plan reading \"from a copy of the\n // base layout, adding a sidebar\" gets the base layout, the sidebar\n // nowhere in it, and until now reported Done. The copy's own regions\n // answer the plan's, and a copy that cannot be read answers nothing —\n // which is a stop for a person, never a Done.\n const review = await aiCopiedLayoutReview(firestore, { hostId, id: copy.id, plan, name })\n if (review) return aiUnspentOutcome(model, { review })\n const hostSubdomain = await aiSiteSubdomain(firestore, hostId)\n return aiUnspentOutcome(model, {\n outputs: [output({ id: copy.id, versionId: copy.versionId, name: copy.name, hostSubdomain })],\n })\n }\n if (copy.ok === false && copy.status === 403) {\n return aiUnspentOutcome(model, { review: aiLimitReview(copy.error) })\n }\n }\n\n const allowance = await aiDraftAllowanceRefusal(firestore, { kind: 'layout', hostId, org })\n if (allowance) return aiUnspentOutcome(model, { review: aiLimitReview(allowance) })\n\n const result = await runValidatedGeneration('layout', {\n step: 'job.layout',\n model,\n instructions: AI_JOB_LAYOUT_INSTRUCTIONS,\n inventory,\n messages: [{ role: 'user', content: aiJobLayoutPrompt(job, plan, name) }],\n tool: aiDoctrineTreeTool('layout'),\n maxTokens: AI_JOB_LAYOUT_STEP_BUDGET.maxTokens(model),\n ...(AI_ROUTING_TABLE['job.layout'].thinking ? { thinking: AI_ROUTING_TABLE['job.layout'].thinking } : {}),\n ...(AI_ROUTING_TABLE['job.layout'].effort ? { effort: AI_ROUTING_TABLE['job.layout'].effort } : {}),\n extend: aiLayoutReuseCheck(inventory, plan),\n ...(signal ? { signal } : {}),\n })\n const spent = aiGenerationSpent(result)\n if (result.status === 'refused') return { ...spent, refused: true }\n if (result.status === 'needs_input') return { ...spent, review: aiDoctrineReview(result) }\n\n const draft = await writeAiDraft(firestore, {\n kind: 'layout',\n hostId,\n id: draftId,\n uid: job.createdBy,\n org,\n name,\n nodes: result.value.nodes,\n now,\n })\n if (draft.ok === false) {\n if (draft.status === 404) throw new Error(`site ${hostId} vanished while its layout was generated`)\n return { ...spent, review: aiLimitReview(draft.error) }\n }\n // The facts the brief did not give, which the member fills before publishing (AGL-3056).\n const note = aiBracketedFactsNote({\n tree: { rootId: result.value.rootId, nodes: result.value.nodes as unknown as AiDoctrineTree['nodes'] },\n inventory,\n })\n return { ...spent, outputs: [output(draft, result.value.load, note)] }\n }\n}\n\nexport const runAiJobLayoutStep = createAiJobLayoutStep()\n\n/** Registers the layout step and the check a layout job passes before it is created or resumed. */\nexport function registerAiLayoutJob(): void {\n registerAiJobStep('layout', runAiJobLayoutStep, { minimumMs: AI_JOB_LAYOUT_STEP_MINIMUM_MS })\n registerAiJobAdmission('layout', aiLayoutJobAdmission)\n}\n"],"names":["CANVAS_ROOT_ELEMENT_ID","duplicateResource","AI_STEP_TIERS","AI_ROUTING_TABLE","aiModelForStep","aiDoctrineTreeTool","runValidatedGeneration","walkTree","readSiteInventory","registerAiJobAdmission","aiJobDraftId","aiDraftAdmissionRefusal","aiDraftAllowanceRefusal","aiSiteSubdomain","readAiDraft","readAiDraftNodes","writeAiDraft","aiBracketedFactsNote","aiConfirmedPlan","aiDoctrineReview","aiGenerationSpent","aiJobBriefLine","aiLimitReview","aiModelNodeIds","aiPlacedComponentIds","aiPlanCreation","aiPlanReferenceLines","aiPlanReuseViolations","aiUnspentOutcome","aiPlanRegionViolations","aiPlannedLayoutRegions","aiJobStepBudget","registerAiJobStep","AI_JOB_LAYOUT_MAX_TOKENS","maxTokens","AI_JOB_LAYOUT_STEP_BUDGET","tier","AI_JOB_LAYOUT_STEP_MINIMUM_MS","minimumMs","AI_JOB_LAYOUT_DEFAULT_NAME","AI_JOB_LAYOUT_INSTRUCTIONS","text","join","aiJobLayoutPrompt","job","plan","name","NAVIGATION_NAME","FOOTER_NAME","isLink","node","componentId","props","aiLayoutReuseCheck","inventory","components","navigation","filter","component","test","tree","placed","violations","rootId","nodes","length","some","has","id","visits","slot","findIndex","header","slice","links","map","push","rule","code","message","nodeIds","sourceIds","aiCopiedLayoutReview","firestore","input","planned","regions","unreadable","stored","kind","hostId","reason","findings","aiLayoutJobAdmission","context","orgId","org","createAiJobLayoutStep","deps","readInventory","duplicate","now","signal","modelFor","orgSnapshot","Error","output","draft","load","note","resource","versionId","hostSubdomain","label","model","draftId","written","outputs","Promise","all","collection","doc","get","data","creation","duplicateOf","layouts","layout","copy","sourceId","uid","createdBy","ok","review","status","error","allowance","result","step","instructions","messages","role","content","tool","thinking","effort","extend","spent","refused","value","runAiJobLayoutStep","registerAiLayoutJob"],"mappings":"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"}
@@ -0,0 +1,57 @@
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 time a page pass needs (AGL-2907, AGL-3036), declared apart from the
19
+ * page step: the site scaffold builds its pages through that step, and reads
20
+ * the time a page needs without loading the step it hands them to.
21
+ */
22
+ /** The most one section's answer may run to on any model; slower tiers get less. */
23
+ export declare const AI_JOB_PAGE_SECTION_MAX_TOKENS = 2000;
24
+ /**
25
+ * The ceiling a section's answer asks on the tier the page step is served
26
+ * from (AGL-2907): fifteen elements at `AI_JOB_PAGE_REAL_TOKENS_PER_ELEMENT`
27
+ * (AGL-3042), the size every golden section and a two-person introduction fit
28
+ * (`ai-job-page-evals.spec.ts`) and a Free page's credits are counted at
29
+ * (`ai-job-free-page.spec.ts`). A faster tier asks more in the same time, up
30
+ * to `AI_JOB_PAGE_SECTION_MAX_TOKENS`, and a slower one less.
31
+ *
32
+ * A Free page fits its wall at this ceiling with little to spare, so the
33
+ * ceiling does not move to make a section fit: a few tokens past it, the Free
34
+ * page that builds its layout first leaves no more of the wall than its
35
+ * largest pass spends, which is the room a re-asked section needs
36
+ * (`ai-job-free-page.spec.ts` finds the largest ceiling that holds, and
37
+ * `docs/AI_JOBS.md` quotes it). The sections a Free plan may ask for are
38
+ * counted at this ceiling too (AGL-3070). A section that runs past it is asked for
39
+ * smaller instead (AGL-3042), and on a workspace that keeps no reusable
40
+ * components a repeated item is written once, which is what lets a Free
41
+ * section of cards with real copy fit at all (AGL-3053).
42
+ */
43
+ export declare const AI_JOB_PAGE_SECTION_TOKENS = 1050;
44
+ /**
45
+ * A section pass's time (AGL-3036): its two inventory-lookup rounds, its
46
+ * answer and its re-ask at `AI_JOB_PAGE_SECTION_TOKENS` on the served tier,
47
+ * with the step's reads and writes, at the rates `ai-job-budget.ts` assumes.
48
+ */
49
+ export declare const AI_JOB_PAGE_STEP_BUDGET: import("./ai-job-budget").AiJobStepBudget;
50
+ /**
51
+ * The least time one section pass needs before it starts. Registered with the
52
+ * step, so neither the beat nor an inline door starts a pass that its budget
53
+ * would cut off. A spec holds it inside the beat's own budget.
54
+ */
55
+ export declare const AI_JOB_PAGE_STEP_MINIMUM_MS: number;
56
+ /** The ceiling a section's answer asks on this model: the most whose worst case fits a pass. */
57
+ export declare function aiJobPageSectionMaxTokens(model: string): number;