@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.
- package/LICENSE +201 -0
- package/README.md +25 -0
- package/package.json +60 -0
- package/src/index.d.ts +21 -0
- package/src/index.js +22 -0
- package/src/index.js.map +1 -0
- package/src/lib/activity/ai-activity-actions.d.ts +106 -0
- package/src/lib/activity/ai-activity-actions.js +209 -0
- package/src/lib/activity/ai-activity-actions.js.map +1 -0
- package/src/lib/activity/ai-activity.d.ts +219 -0
- package/src/lib/activity/ai-activity.js +251 -0
- package/src/lib/activity/ai-activity.js.map +1 -0
- package/src/lib/billing/ai-overage-charge.d.ts +102 -0
- package/src/lib/billing/ai-overage-charge.js +258 -0
- package/src/lib/billing/ai-overage-charge.js.map +1 -0
- package/src/lib/billing/ai-overage-close.d.ts +62 -0
- package/src/lib/billing/ai-overage-close.js +129 -0
- package/src/lib/billing/ai-overage-close.js.map +1 -0
- package/src/lib/billing/ai-overage-cutover.d.ts +63 -0
- package/src/lib/billing/ai-overage-cutover.js +114 -0
- package/src/lib/billing/ai-overage-cutover.js.map +1 -0
- package/src/lib/billing/ai-overage-events.d.ts +77 -0
- package/src/lib/billing/ai-overage-events.js +174 -0
- package/src/lib/billing/ai-overage-events.js.map +1 -0
- package/src/lib/billing/ai-overage-gate.d.ts +147 -0
- package/src/lib/billing/ai-overage-gate.js +177 -0
- package/src/lib/billing/ai-overage-gate.js.map +1 -0
- package/src/lib/billing/ai-overage-ledger.d.ts +135 -0
- package/src/lib/billing/ai-overage-ledger.js +278 -0
- package/src/lib/billing/ai-overage-ledger.js.map +1 -0
- package/src/lib/billing/ai-overage-standing-writes.d.ts +110 -0
- package/src/lib/billing/ai-overage-standing-writes.js +205 -0
- package/src/lib/billing/ai-overage-standing-writes.js.map +1 -0
- package/src/lib/billing/ai-overage-standing.d.ts +168 -0
- package/src/lib/billing/ai-overage-standing.js +215 -0
- package/src/lib/billing/ai-overage-standing.js.map +1 -0
- package/src/lib/billing/ai-overage-trigger.d.ts +30 -0
- package/src/lib/billing/ai-overage-trigger.js +76 -0
- package/src/lib/billing/ai-overage-trigger.js.map +1 -0
- package/src/lib/components/ai-allotment-editor.component.d.ts +40 -0
- package/src/lib/components/ai-allotment-editor.component.js +213 -0
- package/src/lib/components/ai-allotment-editor.component.js.map +1 -0
- package/src/lib/components/ai-assist-actions-context.d.ts +13 -0
- package/src/lib/components/ai-assist-actions-context.js +21 -0
- package/src/lib/components/ai-assist-actions-context.js.map +1 -0
- package/src/lib/components/ai-assist-provider.component.d.ts +51 -0
- package/src/lib/components/ai-assist-provider.component.js +519 -0
- package/src/lib/components/ai-assist-provider.component.js.map +1 -0
- package/src/lib/components/ai-brief-dialog.component.d.ts +56 -0
- package/src/lib/components/ai-brief-dialog.component.js +319 -0
- package/src/lib/components/ai-brief-dialog.component.js.map +1 -0
- package/src/lib/components/ai-collaborator-permissions-column.component.d.ts +32 -0
- package/src/lib/components/ai-collaborator-permissions-column.component.js +132 -0
- package/src/lib/components/ai-collaborator-permissions-column.component.js.map +1 -0
- package/src/lib/components/ai-credits-card.component.d.ts +34 -0
- package/src/lib/components/ai-credits-card.component.js +131 -0
- package/src/lib/components/ai-credits-card.component.js.map +1 -0
- package/src/lib/components/ai-credits-columns.component.d.ts +56 -0
- package/src/lib/components/ai-credits-columns.component.js +118 -0
- package/src/lib/components/ai-credits-columns.component.js.map +1 -0
- package/src/lib/components/ai-crm-email-draft.component.d.ts +17 -0
- package/src/lib/components/ai-crm-email-draft.component.js +159 -0
- package/src/lib/components/ai-crm-email-draft.component.js.map +1 -0
- package/src/lib/components/ai-crm-import-mapping.component.d.ts +20 -0
- package/src/lib/components/ai-crm-import-mapping.component.js +167 -0
- package/src/lib/components/ai-crm-import-mapping.component.js.map +1 -0
- package/src/lib/components/ai-crm-record-card.component.d.ts +27 -0
- package/src/lib/components/ai-crm-record-card.component.js +263 -0
- package/src/lib/components/ai-crm-record-card.component.js.map +1 -0
- package/src/lib/components/ai-describe-automation.component.d.ts +31 -0
- package/src/lib/components/ai-describe-automation.component.js +226 -0
- package/src/lib/components/ai-describe-automation.component.js.map +1 -0
- package/src/lib/components/ai-describe-button.component.d.ts +39 -0
- package/src/lib/components/ai-describe-button.component.js +87 -0
- package/src/lib/components/ai-describe-button.component.js.map +1 -0
- package/src/lib/components/ai-describe-page.component.d.ts +26 -0
- package/src/lib/components/ai-describe-page.component.js +18 -0
- package/src/lib/components/ai-describe-page.component.js.map +1 -0
- package/src/lib/components/ai-experiment-cards.component.d.ts +75 -0
- package/src/lib/components/ai-experiment-cards.component.js +573 -0
- package/src/lib/components/ai-experiment-cards.component.js.map +1 -0
- package/src/lib/components/ai-explain-automation.component.d.ts +31 -0
- package/src/lib/components/ai-explain-automation.component.js +265 -0
- package/src/lib/components/ai-explain-automation.component.js.map +1 -0
- package/src/lib/components/ai-insight-dialog.component.d.ts +37 -0
- package/src/lib/components/ai-insight-dialog.component.js +441 -0
- package/src/lib/components/ai-insight-dialog.component.js.map +1 -0
- package/src/lib/components/ai-job-plan.component.d.ts +46 -0
- package/src/lib/components/ai-job-plan.component.js +192 -0
- package/src/lib/components/ai-job-plan.component.js.map +1 -0
- package/src/lib/components/ai-model-selector.component.d.ts +21 -0
- package/src/lib/components/ai-model-selector.component.js +109 -0
- package/src/lib/components/ai-model-selector.component.js.map +1 -0
- package/src/lib/components/ai-page-brief-dialog.component.d.ts +29 -0
- package/src/lib/components/ai-page-brief-dialog.component.js +27 -0
- package/src/lib/components/ai-page-brief-dialog.component.js.map +1 -0
- package/src/lib/components/ai-permissions-on-host.component.d.ts +55 -0
- package/src/lib/components/ai-permissions-on-host.component.js +91 -0
- package/src/lib/components/ai-permissions-on-host.component.js.map +1 -0
- package/src/lib/components/ai-product-copy-card.component.d.ts +25 -0
- package/src/lib/components/ai-product-copy-card.component.js +328 -0
- package/src/lib/components/ai-product-copy-card.component.js.map +1 -0
- package/src/lib/components/ai-product-import-option.component.d.ts +14 -0
- package/src/lib/components/ai-product-import-option.component.js +58 -0
- package/src/lib/components/ai-product-import-option.component.js.map +1 -0
- package/src/lib/components/ai-products-hub-card.component.d.ts +15 -0
- package/src/lib/components/ai-products-hub-card.component.js +418 -0
- package/src/lib/components/ai-products-hub-card.component.js.map +1 -0
- package/src/lib/components/ai-products-proposals.component.d.ts +19 -0
- package/src/lib/components/ai-products-proposals.component.js +547 -0
- package/src/lib/components/ai-products-proposals.component.js.map +1 -0
- package/src/lib/components/ai-save-as-component.component.d.ts +38 -0
- package/src/lib/components/ai-save-as-component.component.js +231 -0
- package/src/lib/components/ai-save-as-component.component.js.map +1 -0
- package/src/lib/components/ai-seo-audit-card.component.d.ts +9 -0
- package/src/lib/components/ai-seo-audit-card.component.js +620 -0
- package/src/lib/components/ai-seo-audit-card.component.js.map +1 -0
- package/src/lib/components/ai-seo-fields-card.component.d.ts +10 -0
- package/src/lib/components/ai-seo-fields-card.component.js +453 -0
- package/src/lib/components/ai-seo-fields-card.component.js.map +1 -0
- package/src/lib/components/ai-site-batch-card.component.d.ts +32 -0
- package/src/lib/components/ai-site-batch-card.component.js +531 -0
- package/src/lib/components/ai-site-batch-card.component.js.map +1 -0
- package/src/lib/components/ai-site-seo-start-card.component.d.ts +26 -0
- package/src/lib/components/ai-site-seo-start-card.component.js +178 -0
- package/src/lib/components/ai-site-seo-start-card.component.js.map +1 -0
- package/src/lib/components/ai-site-start-card.component.d.ts +19 -0
- package/src/lib/components/ai-site-start-card.component.js +348 -0
- package/src/lib/components/ai-site-start-card.component.js.map +1 -0
- package/src/lib/components/ai-template-collection-field.component.d.ts +32 -0
- package/src/lib/components/ai-template-collection-field.component.js +63 -0
- package/src/lib/components/ai-template-collection-field.component.js.map +1 -0
- package/src/lib/components/ai-theme-proposal-card.component.d.ts +6 -0
- package/src/lib/components/ai-theme-proposal-card.component.js +619 -0
- package/src/lib/components/ai-theme-proposal-card.component.js.map +1 -0
- package/src/lib/components/ai-usage-strip.component.d.ts +27 -0
- package/src/lib/components/ai-usage-strip.component.js +145 -0
- package/src/lib/components/ai-usage-strip.component.js.map +1 -0
- package/src/lib/components/assist-edit-canvas.d.ts +169 -0
- package/src/lib/components/assist-edit-canvas.js +636 -0
- package/src/lib/components/assist-edit-canvas.js.map +1 -0
- package/src/lib/components/assist-edit-card.component.d.ts +16 -0
- package/src/lib/components/assist-edit-card.component.js +181 -0
- package/src/lib/components/assist-edit-card.component.js.map +1 -0
- package/src/lib/components/assist-jobs-drawer.component.d.ts +72 -0
- package/src/lib/components/assist-jobs-drawer.component.js +626 -0
- package/src/lib/components/assist-jobs-drawer.component.js.map +1 -0
- package/src/lib/components/assist-panel.component.d.ts +136 -0
- package/src/lib/components/assist-panel.component.js +1099 -0
- package/src/lib/components/assist-panel.component.js.map +1 -0
- package/src/lib/components/assist-signals-page.component.d.ts +3 -0
- package/src/lib/components/assist-signals-page.component.js +1017 -0
- package/src/lib/components/assist-signals-page.component.js.map +1 -0
- package/src/lib/components/besigner-ai-controls.component.d.ts +29 -0
- package/src/lib/components/besigner-ai-controls.component.js +81 -0
- package/src/lib/components/besigner-ai-controls.component.js.map +1 -0
- package/src/lib/components/billing-ai-allotments.component.d.ts +36 -0
- package/src/lib/components/billing-ai-allotments.component.js +486 -0
- package/src/lib/components/billing-ai-allotments.component.js.map +1 -0
- package/src/lib/components/billing-ai-top-users.component.d.ts +44 -0
- package/src/lib/components/billing-ai-top-users.component.js +304 -0
- package/src/lib/components/billing-ai-top-users.component.js.map +1 -0
- package/src/lib/components/billing-assist-overage-card.component.d.ts +69 -0
- package/src/lib/components/billing-assist-overage-card.component.js +437 -0
- package/src/lib/components/billing-assist-overage-card.component.js.map +1 -0
- package/src/lib/components/host-ai-allotments.component.d.ts +40 -0
- package/src/lib/components/host-ai-allotments.component.js +239 -0
- package/src/lib/components/host-ai-allotments.component.js.map +1 -0
- package/src/lib/components/member-ai-allotment-card.component.d.ts +28 -0
- package/src/lib/components/member-ai-allotment-card.component.js +172 -0
- package/src/lib/components/member-ai-allotment-card.component.js.map +1 -0
- package/src/lib/components/member-ai-usage-card.component.d.ts +28 -0
- package/src/lib/components/member-ai-usage-card.component.js +240 -0
- package/src/lib/components/member-ai-usage-card.component.js.map +1 -0
- package/src/lib/components/staff-org-ai-card.component.d.ts +17 -0
- package/src/lib/components/staff-org-ai-card.component.js +739 -0
- package/src/lib/components/staff-org-ai-card.component.js.map +1 -0
- package/src/lib/components/staff-org-usage-ai-columns.component.d.ts +41 -0
- package/src/lib/components/staff-org-usage-ai-columns.component.js +65 -0
- package/src/lib/components/staff-org-usage-ai-columns.component.js.map +1 -0
- package/src/lib/components/staff-orgs-ai-spend-column.component.d.ts +28 -0
- package/src/lib/components/staff-orgs-ai-spend-column.component.js +89 -0
- package/src/lib/components/staff-orgs-ai-spend-column.component.js.map +1 -0
- package/src/lib/components/staff-user-ai-usage-card.component.d.ts +27 -0
- package/src/lib/components/staff-user-ai-usage-card.component.js +183 -0
- package/src/lib/components/staff-user-ai-usage-card.component.js.map +1 -0
- package/src/lib/components/use-ai-allotments.d.ts +49 -0
- package/src/lib/components/use-ai-allotments.js +171 -0
- package/src/lib/components/use-ai-allotments.js.map +1 -0
- package/src/lib/components/use-ai-crm-answer.d.ts +50 -0
- package/src/lib/components/use-ai-crm-answer.js +220 -0
- package/src/lib/components/use-ai-crm-answer.js.map +1 -0
- package/src/lib/components/use-ai-job-run.d.ts +51 -0
- package/src/lib/components/use-ai-job-run.js +176 -0
- package/src/lib/components/use-ai-job-run.js.map +1 -0
- package/src/lib/components/use-ai-model-choice.d.ts +47 -0
- package/src/lib/components/use-ai-model-choice.js +150 -0
- package/src/lib/components/use-ai-model-choice.js.map +1 -0
- package/src/lib/components/use-ai-products-jobs.d.ts +36 -0
- package/src/lib/components/use-ai-products-jobs.js +190 -0
- package/src/lib/components/use-ai-products-jobs.js.map +1 -0
- package/src/lib/components/use-ai-usage-meter.d.ts +11 -0
- package/src/lib/components/use-ai-usage-meter.js +96 -0
- package/src/lib/components/use-ai-usage-meter.js.map +1 -0
- package/src/lib/components/use-org-ai-usage.d.ts +42 -0
- package/src/lib/components/use-org-ai-usage.js +181 -0
- package/src/lib/components/use-org-ai-usage.js.map +1 -0
- package/src/lib/components/use-staff-orgs-ai-spend.d.ts +18 -0
- package/src/lib/components/use-staff-orgs-ai-spend.js +127 -0
- package/src/lib/components/use-staff-orgs-ai-spend.js.map +1 -0
- package/src/lib/constants.d.ts +24 -0
- package/src/lib/constants.js +23 -0
- package/src/lib/constants.js.map +1 -0
- package/src/lib/declarations.d.ts +48 -0
- package/src/lib/declarations.js +129 -0
- package/src/lib/declarations.js.map +1 -0
- package/src/lib/declarations.server.d.ts +35 -0
- package/src/lib/declarations.server.js +138 -0
- package/src/lib/declarations.server.js.map +1 -0
- package/src/lib/insights/ai-figure-readers.d.ts +90 -0
- package/src/lib/insights/ai-figure-readers.js +863 -0
- package/src/lib/insights/ai-figure-readers.js.map +1 -0
- package/src/lib/insights/ai-insight-digest.d.ts +165 -0
- package/src/lib/insights/ai-insight-digest.js +363 -0
- package/src/lib/insights/ai-insight-digest.js.map +1 -0
- package/src/lib/insights/ai-insight-readers.d.ts +71 -0
- package/src/lib/insights/ai-insight-readers.js +141 -0
- package/src/lib/insights/ai-insight-readers.js.map +1 -0
- package/src/lib/jobs/ai-crm-access.d.ts +61 -0
- package/src/lib/jobs/ai-crm-access.js +94 -0
- package/src/lib/jobs/ai-crm-access.js.map +1 -0
- package/src/lib/jobs/ai-email-bindings.d.ts +97 -0
- package/src/lib/jobs/ai-email-bindings.js +147 -0
- package/src/lib/jobs/ai-email-bindings.js.map +1 -0
- package/src/lib/jobs/ai-job-admission.d.ts +82 -0
- package/src/lib/jobs/ai-job-admission.js +45 -0
- package/src/lib/jobs/ai-job-admission.js.map +1 -0
- package/src/lib/jobs/ai-job-budget.d.ts +167 -0
- package/src/lib/jobs/ai-job-budget.js +161 -0
- package/src/lib/jobs/ai-job-budget.js.map +1 -0
- package/src/lib/jobs/ai-job-campaign-step.d.ts +108 -0
- package/src/lib/jobs/ai-job-campaign-step.js +340 -0
- package/src/lib/jobs/ai-job-campaign-step.js.map +1 -0
- package/src/lib/jobs/ai-job-component-checks.d.ts +74 -0
- package/src/lib/jobs/ai-job-component-checks.js +442 -0
- package/src/lib/jobs/ai-job-component-checks.js.map +1 -0
- package/src/lib/jobs/ai-job-component-step.d.ts +75 -0
- package/src/lib/jobs/ai-job-component-step.js +262 -0
- package/src/lib/jobs/ai-job-component-step.js.map +1 -0
- package/src/lib/jobs/ai-job-crm-step.d.ts +192 -0
- package/src/lib/jobs/ai-job-crm-step.js +734 -0
- package/src/lib/jobs/ai-job-crm-step.js.map +1 -0
- package/src/lib/jobs/ai-job-draft-ids.d.ts +62 -0
- package/src/lib/jobs/ai-job-draft-ids.js +132 -0
- package/src/lib/jobs/ai-job-draft-ids.js.map +1 -0
- package/src/lib/jobs/ai-job-drafts.d.ts +304 -0
- package/src/lib/jobs/ai-job-drafts.js +557 -0
- package/src/lib/jobs/ai-job-drafts.js.map +1 -0
- package/src/lib/jobs/ai-job-email-step.d.ts +195 -0
- package/src/lib/jobs/ai-job-email-step.js +547 -0
- package/src/lib/jobs/ai-job-email-step.js.map +1 -0
- package/src/lib/jobs/ai-job-experiment-step.d.ts +105 -0
- package/src/lib/jobs/ai-job-experiment-step.js +445 -0
- package/src/lib/jobs/ai-job-experiment-step.js.map +1 -0
- package/src/lib/jobs/ai-job-form-step.d.ts +250 -0
- package/src/lib/jobs/ai-job-form-step.js +634 -0
- package/src/lib/jobs/ai-job-form-step.js.map +1 -0
- package/src/lib/jobs/ai-job-generation.d.ts +114 -0
- package/src/lib/jobs/ai-job-generation.js +384 -0
- package/src/lib/jobs/ai-job-generation.js.map +1 -0
- package/src/lib/jobs/ai-job-insight-budget.d.ts +41 -0
- package/src/lib/jobs/ai-job-insight-budget.js +46 -0
- package/src/lib/jobs/ai-job-insight-budget.js.map +1 -0
- package/src/lib/jobs/ai-job-insight-step.d.ts +58 -0
- package/src/lib/jobs/ai-job-insight-step.js +350 -0
- package/src/lib/jobs/ai-job-insight-step.js.map +1 -0
- package/src/lib/jobs/ai-job-layout-step.d.ts +103 -0
- package/src/lib/jobs/ai-job-layout-step.js +340 -0
- package/src/lib/jobs/ai-job-layout-step.js.map +1 -0
- package/src/lib/jobs/ai-job-page-budget.d.ts +57 -0
- package/src/lib/jobs/ai-job-page-budget.js +60 -0
- package/src/lib/jobs/ai-job-page-budget.js.map +1 -0
- package/src/lib/jobs/ai-job-page-sections.d.ts +150 -0
- package/src/lib/jobs/ai-job-page-sections.js +450 -0
- package/src/lib/jobs/ai-job-page-sections.js.map +1 -0
- package/src/lib/jobs/ai-job-page-step.d.ts +198 -0
- package/src/lib/jobs/ai-job-page-step.js +667 -0
- package/src/lib/jobs/ai-job-page-step.js.map +1 -0
- package/src/lib/jobs/ai-job-plan-conformance.d.ts +107 -0
- package/src/lib/jobs/ai-job-plan-conformance.js +164 -0
- package/src/lib/jobs/ai-job-plan-conformance.js.map +1 -0
- package/src/lib/jobs/ai-job-plan-step.d.ts +196 -0
- package/src/lib/jobs/ai-job-plan-step.js +458 -0
- package/src/lib/jobs/ai-job-plan-step.js.map +1 -0
- package/src/lib/jobs/ai-job-plugin-drafts.d.ts +76 -0
- package/src/lib/jobs/ai-job-plugin-drafts.js +91 -0
- package/src/lib/jobs/ai-job-plugin-drafts.js.map +1 -0
- package/src/lib/jobs/ai-job-products-step.d.ts +106 -0
- package/src/lib/jobs/ai-job-products-step.js +436 -0
- package/src/lib/jobs/ai-job-products-step.js.map +1 -0
- package/src/lib/jobs/ai-job-seo-budget.d.ts +52 -0
- package/src/lib/jobs/ai-job-seo-budget.js +63 -0
- package/src/lib/jobs/ai-job-seo-budget.js.map +1 -0
- package/src/lib/jobs/ai-job-seo-step.d.ts +145 -0
- package/src/lib/jobs/ai-job-seo-step.js +809 -0
- package/src/lib/jobs/ai-job-seo-step.js.map +1 -0
- package/src/lib/jobs/ai-job-site-step.d.ts +252 -0
- package/src/lib/jobs/ai-job-site-step.js +538 -0
- package/src/lib/jobs/ai-job-site-step.js.map +1 -0
- package/src/lib/jobs/ai-job-template-step.d.ts +105 -0
- package/src/lib/jobs/ai-job-template-step.js +391 -0
- package/src/lib/jobs/ai-job-template-step.js.map +1 -0
- package/src/lib/jobs/ai-job-text-step.d.ts +125 -0
- package/src/lib/jobs/ai-job-text-step.js +128 -0
- package/src/lib/jobs/ai-job-text-step.js.map +1 -0
- package/src/lib/jobs/ai-job-theme-budget.d.ts +38 -0
- package/src/lib/jobs/ai-job-theme-budget.js +43 -0
- package/src/lib/jobs/ai-job-theme-budget.js.map +1 -0
- package/src/lib/jobs/ai-job-theme-step.d.ts +115 -0
- package/src/lib/jobs/ai-job-theme-step.js +337 -0
- package/src/lib/jobs/ai-job-theme-step.js.map +1 -0
- package/src/lib/jobs/ai-job-workflow-step.d.ts +139 -0
- package/src/lib/jobs/ai-job-workflow-step.js +530 -0
- package/src/lib/jobs/ai-job-workflow-step.js.map +1 -0
- package/src/lib/jobs/ai-jobs-beat.d.ts +78 -0
- package/src/lib/jobs/ai-jobs-beat.js +93 -0
- package/src/lib/jobs/ai-jobs-beat.js.map +1 -0
- package/src/lib/jobs/ai-jobs-pause.d.ts +38 -0
- package/src/lib/jobs/ai-jobs-pause.js +45 -0
- package/src/lib/jobs/ai-jobs-pause.js.map +1 -0
- package/src/lib/jobs/ai-jobs.d.ts +558 -0
- package/src/lib/jobs/ai-jobs.js +1410 -0
- package/src/lib/jobs/ai-jobs.js.map +1 -0
- package/src/lib/jobs/ai-media-asset-server.d.ts +34 -0
- package/src/lib/jobs/ai-media-asset-server.js +34 -0
- package/src/lib/jobs/ai-media-asset-server.js.map +1 -0
- package/src/lib/jobs/ai-media-asset.d.ts +59 -0
- package/src/lib/jobs/ai-media-asset.js +86 -0
- package/src/lib/jobs/ai-media-asset.js.map +1 -0
- package/src/lib/jobs/ai-product-image.d.ts +78 -0
- package/src/lib/jobs/ai-product-image.js +113 -0
- package/src/lib/jobs/ai-product-image.js.map +1 -0
- package/src/lib/jobs/ai-theme-brand-inputs.d.ts +125 -0
- package/src/lib/jobs/ai-theme-brand-inputs.js +378 -0
- package/src/lib/jobs/ai-theme-brand-inputs.js.map +1 -0
- package/src/lib/jobs/ai-theme-brand-server.d.ts +33 -0
- package/src/lib/jobs/ai-theme-brand-server.js +33 -0
- package/src/lib/jobs/ai-theme-brand-server.js.map +1 -0
- package/src/lib/jobs/ai-workflow-records.d.ts +84 -0
- package/src/lib/jobs/ai-workflow-records.js +158 -0
- package/src/lib/jobs/ai-workflow-records.js.map +1 -0
- package/src/lib/jobs/fixtures/ai-free-page-built-recording.d.ts +31 -0
- package/src/lib/jobs/fixtures/ai-free-page-built-recording.js +367 -0
- package/src/lib/jobs/fixtures/ai-free-page-built-recording.js.map +1 -0
- package/src/lib/jobs/fixtures/ai-free-page-recording.d.ts +69 -0
- package/src/lib/jobs/fixtures/ai-free-page-recording.js +442 -0
- package/src/lib/jobs/fixtures/ai-free-page-recording.js.map +1 -0
- package/src/lib/jobs/fixtures/ai-page-briefs.d.ts +146 -0
- package/src/lib/jobs/fixtures/ai-page-briefs.js +1850 -0
- package/src/lib/jobs/fixtures/ai-page-briefs.js.map +1 -0
- package/src/lib/model/ai-allotments.d.ts +208 -0
- package/src/lib/model/ai-allotments.js +269 -0
- package/src/lib/model/ai-allotments.js.map +1 -0
- package/src/lib/model/ai-automation-draft.d.ts +74 -0
- package/src/lib/model/ai-automation-draft.js +310 -0
- package/src/lib/model/ai-automation-draft.js.map +1 -0
- package/src/lib/model/ai-automation-outline.d.ts +50 -0
- package/src/lib/model/ai-automation-outline.js +262 -0
- package/src/lib/model/ai-automation-outline.js.map +1 -0
- package/src/lib/model/ai-build-plan.d.ts +197 -0
- package/src/lib/model/ai-build-plan.js +438 -0
- package/src/lib/model/ai-build-plan.js.map +1 -0
- package/src/lib/model/ai-crm.d.ts +237 -0
- package/src/lib/model/ai-crm.js +225 -0
- package/src/lib/model/ai-crm.js.map +1 -0
- package/src/lib/model/ai-experiment-proposal.d.ts +68 -0
- package/src/lib/model/ai-experiment-proposal.js +146 -0
- package/src/lib/model/ai-experiment-proposal.js.map +1 -0
- package/src/lib/model/ai-experiment.d.ts +309 -0
- package/src/lib/model/ai-experiment.js +395 -0
- package/src/lib/model/ai-experiment.js.map +1 -0
- package/src/lib/model/ai-insight.d.ts +178 -0
- package/src/lib/model/ai-insight.js +201 -0
- package/src/lib/model/ai-insight.js.map +1 -0
- package/src/lib/model/ai-jobs.types.d.ts +412 -0
- package/src/lib/model/ai-jobs.types.js +42 -0
- package/src/lib/model/ai-jobs.types.js.map +1 -0
- package/src/lib/model/ai-page-job.d.ts +92 -0
- package/src/lib/model/ai-page-job.js +159 -0
- package/src/lib/model/ai-page-job.js.map +1 -0
- package/src/lib/model/ai-permissions.d.ts +49 -0
- package/src/lib/model/ai-permissions.js +97 -0
- package/src/lib/model/ai-permissions.js.map +1 -0
- package/src/lib/model/ai-plan-capabilities.d.ts +139 -0
- package/src/lib/model/ai-plan-capabilities.js +149 -0
- package/src/lib/model/ai-plan-capabilities.js.map +1 -0
- package/src/lib/model/ai-products.d.ts +251 -0
- package/src/lib/model/ai-products.js +253 -0
- package/src/lib/model/ai-products.js.map +1 -0
- package/src/lib/model/ai-seo.d.ts +208 -0
- package/src/lib/model/ai-seo.js +150 -0
- package/src/lib/model/ai-seo.js.map +1 -0
- package/src/lib/model/ai-site-inventory.d.ts +164 -0
- package/src/lib/model/ai-site-inventory.js +145 -0
- package/src/lib/model/ai-site-inventory.js.map +1 -0
- package/src/lib/model/ai-site-job.d.ts +247 -0
- package/src/lib/model/ai-site-job.js +314 -0
- package/src/lib/model/ai-site-job.js.map +1 -0
- package/src/lib/model/ai-site-start-seo.d.ts +103 -0
- package/src/lib/model/ai-site-start-seo.js +154 -0
- package/src/lib/model/ai-site-start-seo.js.map +1 -0
- package/src/lib/model/ai-site-start.d.ts +122 -0
- package/src/lib/model/ai-site-start.js +159 -0
- package/src/lib/model/ai-site-start.js.map +1 -0
- package/src/lib/model/ai-site-switch.d.ts +56 -0
- package/src/lib/model/ai-site-switch.js +73 -0
- package/src/lib/model/ai-site-switch.js.map +1 -0
- package/src/lib/model/ai-storefront-claims.d.ts +70 -0
- package/src/lib/model/ai-storefront-claims.js +130 -0
- package/src/lib/model/ai-storefront-claims.js.map +1 -0
- package/src/lib/model/ai-template-subjects.d.ts +82 -0
- package/src/lib/model/ai-template-subjects.js +136 -0
- package/src/lib/model/ai-template-subjects.js.map +1 -0
- package/src/lib/model/ai-theme-proposal.d.ts +210 -0
- package/src/lib/model/ai-theme-proposal.js +506 -0
- package/src/lib/model/ai-theme-proposal.js.map +1 -0
- package/src/lib/model/ai-tokens.d.ts +96 -0
- package/src/lib/model/ai-tokens.js +117 -0
- package/src/lib/model/ai-tokens.js.map +1 -0
- package/src/lib/model/ai-usage-by-user.d.ts +120 -0
- package/src/lib/model/ai-usage-by-user.js +139 -0
- package/src/lib/model/ai-usage-by-user.js.map +1 -0
- package/src/lib/model/ai-workflow-job.d.ts +111 -0
- package/src/lib/model/ai-workflow-job.js +183 -0
- package/src/lib/model/ai-workflow-job.js.map +1 -0
- package/src/lib/model/assist-edit.d.ts +261 -0
- package/src/lib/model/assist-edit.js +175 -0
- package/src/lib/model/assist-edit.js.map +1 -0
- package/src/lib/plugin-config.d.ts +33 -0
- package/src/lib/plugin-config.js +118 -0
- package/src/lib/plugin-config.js.map +1 -0
- package/src/lib/plugin.d.ts +30 -0
- package/src/lib/plugin.js +525 -0
- package/src/lib/plugin.js.map +1 -0
- package/src/lib/providers/anthropic.d.ts +84 -0
- package/src/lib/providers/anthropic.js +432 -0
- package/src/lib/providers/anthropic.js.map +1 -0
- package/src/lib/providers/catalog.d.ts +197 -0
- package/src/lib/providers/catalog.js +312 -0
- package/src/lib/providers/catalog.js.map +1 -0
- package/src/lib/providers/contract.d.ts +464 -0
- package/src/lib/providers/contract.js +274 -0
- package/src/lib/providers/contract.js.map +1 -0
- package/src/lib/providers/model-choice.d.ts +119 -0
- package/src/lib/providers/model-choice.js +416 -0
- package/src/lib/providers/model-choice.js.map +1 -0
- package/src/lib/providers/openai-compatible.d.ts +58 -0
- package/src/lib/providers/openai-compatible.js +361 -0
- package/src/lib/providers/openai-compatible.js.map +1 -0
- package/src/lib/providers/registry.d.ts +49 -0
- package/src/lib/providers/registry.js +71 -0
- package/src/lib/providers/registry.js.map +1 -0
- package/src/lib/providers/routing.d.ts +98 -0
- package/src/lib/providers/routing.js +450 -0
- package/src/lib/providers/routing.js.map +1 -0
- package/src/lib/runtime/ai-abuse-guards.d.ts +113 -0
- package/src/lib/runtime/ai-abuse-guards.js +148 -0
- package/src/lib/runtime/ai-abuse-guards.js.map +1 -0
- package/src/lib/runtime/ai-component-bindings.d.ts +67 -0
- package/src/lib/runtime/ai-component-bindings.js +106 -0
- package/src/lib/runtime/ai-component-bindings.js.map +1 -0
- package/src/lib/runtime/ai-device-audit.d.ts +109 -0
- package/src/lib/runtime/ai-device-audit.js +97 -0
- package/src/lib/runtime/ai-device-audit.js.map +1 -0
- package/src/lib/runtime/ai-doctrine-validators.d.ts +720 -0
- package/src/lib/runtime/ai-doctrine-validators.js +3133 -0
- package/src/lib/runtime/ai-doctrine-validators.js.map +1 -0
- package/src/lib/runtime/ai-doctrine.d.ts +372 -0
- package/src/lib/runtime/ai-doctrine.js +944 -0
- package/src/lib/runtime/ai-doctrine.js.map +1 -0
- package/src/lib/runtime/ai-eval-live.d.ts +321 -0
- package/src/lib/runtime/ai-eval-live.js +1257 -0
- package/src/lib/runtime/ai-eval-live.js.map +1 -0
- package/src/lib/runtime/ai-eval-memory-firestore.d.ts +51 -0
- package/src/lib/runtime/ai-eval-memory-firestore.js +183 -0
- package/src/lib/runtime/ai-eval-memory-firestore.js.map +1 -0
- package/src/lib/runtime/ai-eval.d.ts +441 -0
- package/src/lib/runtime/ai-eval.js +1151 -0
- package/src/lib/runtime/ai-eval.js.map +1 -0
- package/src/lib/runtime/ai-gate.d.ts +130 -0
- package/src/lib/runtime/ai-gate.js +272 -0
- package/src/lib/runtime/ai-gate.js.map +1 -0
- package/src/lib/runtime/ai-generation-bounds.d.ts +24 -0
- package/src/lib/runtime/ai-generation-bounds.js +23 -0
- package/src/lib/runtime/ai-generation-bounds.js.map +1 -0
- package/src/lib/runtime/ai-insight-check.d.ts +76 -0
- package/src/lib/runtime/ai-insight-check.js +281 -0
- package/src/lib/runtime/ai-insight-check.js.map +1 -0
- package/src/lib/runtime/ai-node-tree.d.ts +181 -0
- package/src/lib/runtime/ai-node-tree.js +931 -0
- package/src/lib/runtime/ai-node-tree.js.map +1 -0
- package/src/lib/runtime/ai-page-links.d.ts +79 -0
- package/src/lib/runtime/ai-page-links.js +135 -0
- package/src/lib/runtime/ai-page-links.js.map +1 -0
- package/src/lib/runtime/ai-palette.d.ts +252 -0
- package/src/lib/runtime/ai-palette.generated.d.ts +34 -0
- package/src/lib/runtime/ai-palette.generated.js +5263 -0
- package/src/lib/runtime/ai-palette.generated.js.map +1 -0
- package/src/lib/runtime/ai-palette.js +187 -0
- package/src/lib/runtime/ai-palette.js.map +1 -0
- package/src/lib/runtime/ai-products-generation.d.ts +107 -0
- package/src/lib/runtime/ai-products-generation.js +250 -0
- package/src/lib/runtime/ai-products-generation.js.map +1 -0
- package/src/lib/runtime/ai-repeated-items.d.ts +95 -0
- package/src/lib/runtime/ai-repeated-items.js +397 -0
- package/src/lib/runtime/ai-repeated-items.js.map +1 -0
- package/src/lib/runtime/ai-runtime.d.ts +148 -0
- package/src/lib/runtime/ai-runtime.js +237 -0
- package/src/lib/runtime/ai-runtime.js.map +1 -0
- package/src/lib/runtime/ai-template-examples.d.ts +71 -0
- package/src/lib/runtime/ai-template-examples.js +135 -0
- package/src/lib/runtime/ai-template-examples.js.map +1 -0
- package/src/lib/runtime/assist-answer-cache.d.ts +80 -0
- package/src/lib/runtime/assist-answer-cache.js +184 -0
- package/src/lib/runtime/assist-answer-cache.js.map +1 -0
- package/src/lib/runtime/seo-audit.d.ts +93 -0
- package/src/lib/runtime/seo-audit.js +260 -0
- package/src/lib/runtime/seo-audit.js.map +1 -0
- package/src/lib/runtime/seo-content-fixes.d.ts +41 -0
- package/src/lib/runtime/seo-content-fixes.js +168 -0
- package/src/lib/runtime/seo-content-fixes.js.map +1 -0
- package/src/lib/runtime/seo-fields.d.ts +152 -0
- package/src/lib/runtime/seo-fields.js +215 -0
- package/src/lib/runtime/seo-fields.js.map +1 -0
- package/src/lib/runtime/seo-page-facts.d.ts +61 -0
- package/src/lib/runtime/seo-page-facts.js +150 -0
- package/src/lib/runtime/seo-page-facts.js.map +1 -0
- package/src/lib/runtime/site-inventory.d.ts +63 -0
- package/src/lib/runtime/site-inventory.js +230 -0
- package/src/lib/runtime/site-inventory.js.map +1 -0
- package/src/lib/server/ai-admin-org.d.ts +33 -0
- package/src/lib/server/ai-admin-org.js +381 -0
- package/src/lib/server/ai-admin-org.js.map +1 -0
- package/src/lib/server/ai-admin-orgs-spend.d.ts +40 -0
- package/src/lib/server/ai-admin-orgs-spend.js +129 -0
- package/src/lib/server/ai-admin-orgs-spend.js.map +1 -0
- package/src/lib/server/ai-admin-overage.d.ts +19 -0
- package/src/lib/server/ai-admin-overage.js +246 -0
- package/src/lib/server/ai-admin-overage.js.map +1 -0
- package/src/lib/server/ai-admin-signals.d.ts +34 -0
- package/src/lib/server/ai-admin-signals.js +330 -0
- package/src/lib/server/ai-admin-signals.js.map +1 -0
- package/src/lib/server/ai-admin-user.d.ts +27 -0
- package/src/lib/server/ai-admin-user.js +128 -0
- package/src/lib/server/ai-admin-user.js.map +1 -0
- package/src/lib/server/ai-allotments.d.ts +27 -0
- package/src/lib/server/ai-allotments.js +544 -0
- package/src/lib/server/ai-allotments.js.map +1 -0
- package/src/lib/server/ai-assist-prompts.d.ts +102 -0
- package/src/lib/server/ai-assist-prompts.js +207 -0
- package/src/lib/server/ai-assist-prompts.js.map +1 -0
- package/src/lib/server/ai-assist.d.ts +119 -0
- package/src/lib/server/ai-assist.js +517 -0
- package/src/lib/server/ai-assist.js.map +1 -0
- package/src/lib/server/ai-crm-answer.d.ts +30 -0
- package/src/lib/server/ai-crm-answer.js +98 -0
- package/src/lib/server/ai-crm-answer.js.map +1 -0
- package/src/lib/server/ai-generate-component.d.ts +111 -0
- package/src/lib/server/ai-generate-component.js +643 -0
- package/src/lib/server/ai-generate-component.js.map +1 -0
- package/src/lib/server/ai-host-permissions.d.ts +46 -0
- package/src/lib/server/ai-host-permissions.js +204 -0
- package/src/lib/server/ai-host-permissions.js.map +1 -0
- package/src/lib/server/ai-insight-answer.d.ts +30 -0
- package/src/lib/server/ai-insight-answer.js +83 -0
- package/src/lib/server/ai-insight-answer.js.map +1 -0
- package/src/lib/server/ai-insight-digest-route.d.ts +30 -0
- package/src/lib/server/ai-insight-digest-route.js +156 -0
- package/src/lib/server/ai-insight-digest-route.js.map +1 -0
- package/src/lib/server/ai-jobs-batch.d.ts +48 -0
- package/src/lib/server/ai-jobs-batch.js +306 -0
- package/src/lib/server/ai-jobs-batch.js.map +1 -0
- package/src/lib/server/ai-jobs-beat-route.d.ts +36 -0
- package/src/lib/server/ai-jobs-beat-route.js +86 -0
- package/src/lib/server/ai-jobs-beat-route.js.map +1 -0
- package/src/lib/server/ai-jobs-cancel.d.ts +30 -0
- package/src/lib/server/ai-jobs-cancel.js +74 -0
- package/src/lib/server/ai-jobs-cancel.js.map +1 -0
- package/src/lib/server/ai-jobs-events-route.d.ts +31 -0
- package/src/lib/server/ai-jobs-events-route.js +51 -0
- package/src/lib/server/ai-jobs-events-route.js.map +1 -0
- package/src/lib/server/ai-jobs-events.d.ts +55 -0
- package/src/lib/server/ai-jobs-events.js +144 -0
- package/src/lib/server/ai-jobs-events.js.map +1 -0
- package/src/lib/server/ai-jobs-gate.d.ts +47 -0
- package/src/lib/server/ai-jobs-gate.js +106 -0
- package/src/lib/server/ai-jobs-gate.js.map +1 -0
- package/src/lib/server/ai-jobs-resume.d.ts +23 -0
- package/src/lib/server/ai-jobs-resume.js +209 -0
- package/src/lib/server/ai-jobs-resume.js.map +1 -0
- package/src/lib/server/ai-jobs-route.d.ts +32 -0
- package/src/lib/server/ai-jobs-route.js +307 -0
- package/src/lib/server/ai-jobs-route.js.map +1 -0
- package/src/lib/server/ai-models.d.ts +18 -0
- package/src/lib/server/ai-models.js +134 -0
- package/src/lib/server/ai-models.js.map +1 -0
- package/src/lib/server/ai-seo-apply.d.ts +53 -0
- package/src/lib/server/ai-seo-apply.js +294 -0
- package/src/lib/server/ai-seo-apply.js.map +1 -0
- package/src/lib/server/ai-usage.d.ts +18 -0
- package/src/lib/server/ai-usage.js +220 -0
- package/src/lib/server/ai-usage.js.map +1 -0
- package/src/lib/server/assist-chat.d.ts +234 -0
- package/src/lib/server/assist-chat.js +1446 -0
- package/src/lib/server/assist-chat.js.map +1 -0
- package/src/lib/server/assist-edit-applied.d.ts +22 -0
- package/src/lib/server/assist-edit-applied.js +239 -0
- package/src/lib/server/assist-edit-applied.js.map +1 -0
- package/src/lib/server/assist-edit.d.ts +124 -0
- package/src/lib/server/assist-edit.js +1000 -0
- package/src/lib/server/assist-edit.js.map +1 -0
- package/src/lib/server/assist-feedback.d.ts +31 -0
- package/src/lib/server/assist-feedback.js +115 -0
- package/src/lib/server/assist-feedback.js.map +1 -0
- package/src/lib/server/assist-view-context.d.ts +343 -0
- package/src/lib/server/assist-view-context.js +690 -0
- package/src/lib/server/assist-view-context.js.map +1 -0
- package/src/lib/server/billing-credits.d.ts +59 -0
- package/src/lib/server/billing-credits.js +146 -0
- package/src/lib/server/billing-credits.js.map +1 -0
- package/src/lib/server/billing-overage.d.ts +19 -0
- package/src/lib/server/billing-overage.js +337 -0
- package/src/lib/server/billing-overage.js.map +1 -0
- package/src/lib/server.d.ts +32 -0
- package/src/lib/server.js +265 -0
- package/src/lib/server.js.map +1 -0
- package/src/lib/subprocessors.d.ts +18 -0
- package/src/lib/subprocessors.js +52 -0
- package/src/lib/subprocessors.js.map +1 -0
- package/src/lib/tools/ai-component-tool.d.ts +99 -0
- package/src/lib/tools/ai-component-tool.js +369 -0
- package/src/lib/tools/ai-component-tool.js.map +1 -0
- package/src/lib/tools/ai-crm-tool.d.ts +106 -0
- package/src/lib/tools/ai-crm-tool.js +488 -0
- package/src/lib/tools/ai-crm-tool.js.map +1 -0
- package/src/lib/tools/ai-duplicate-resource-tool.d.ts +71 -0
- package/src/lib/tools/ai-duplicate-resource-tool.js +164 -0
- package/src/lib/tools/ai-duplicate-resource-tool.js.map +1 -0
- package/src/lib/tools/ai-experiment-tool.d.ts +40 -0
- package/src/lib/tools/ai-experiment-tool.js +155 -0
- package/src/lib/tools/ai-experiment-tool.js.map +1 -0
- package/src/lib/tools/ai-insight-tool.d.ts +46 -0
- package/src/lib/tools/ai-insight-tool.js +200 -0
- package/src/lib/tools/ai-insight-tool.js.map +1 -0
- package/src/lib/tools/ai-inventory-lookup-tool.d.ts +86 -0
- package/src/lib/tools/ai-inventory-lookup-tool.js +164 -0
- package/src/lib/tools/ai-inventory-lookup-tool.js.map +1 -0
- package/src/lib/tools/ai-products-tool.d.ts +65 -0
- package/src/lib/tools/ai-products-tool.js +644 -0
- package/src/lib/tools/ai-products-tool.js.map +1 -0
- package/src/lib/tools/ai-seo-tool.d.ts +162 -0
- package/src/lib/tools/ai-seo-tool.js +546 -0
- package/src/lib/tools/ai-seo-tool.js.map +1 -0
- package/src/lib/tools/ai-theme-tool.d.ts +101 -0
- package/src/lib/tools/ai-theme-tool.js +562 -0
- package/src/lib/tools/ai-theme-tool.js.map +1 -0
- package/src/lib/tools/ai-workflow-tool.d.ts +166 -0
- package/src/lib/tools/ai-workflow-tool.js +860 -0
- package/src/lib/tools/ai-workflow-tool.js.map +1 -0
- package/src/lib/usage/ai-allotment-alerts.d.ts +72 -0
- package/src/lib/usage/ai-allotment-alerts.js +157 -0
- package/src/lib/usage/ai-allotment-alerts.js.map +1 -0
- package/src/lib/usage/ai-allotments.d.ts +125 -0
- package/src/lib/usage/ai-allotments.js +239 -0
- package/src/lib/usage/ai-allotments.js.map +1 -0
- package/src/lib/usage/ai-model-sample.d.ts +36 -0
- package/src/lib/usage/ai-model-sample.js +68 -0
- package/src/lib/usage/ai-model-sample.js.map +1 -0
- package/src/lib/usage/ai-usage-alerts.d.ts +55 -0
- package/src/lib/usage/ai-usage-alerts.js +114 -0
- package/src/lib/usage/ai-usage-alerts.js.map +1 -0
- package/src/lib/usage/ai-usage-by-user.d.ts +161 -0
- package/src/lib/usage/ai-usage-by-user.js +211 -0
- package/src/lib/usage/ai-usage-by-user.js.map +1 -0
- package/src/lib/usage/ai-usage-eraser.d.ts +29 -0
- package/src/lib/usage/ai-usage-eraser.js +40 -0
- package/src/lib/usage/ai-usage-eraser.js.map +1 -0
- package/src/lib/usage/ai-usage-meter.d.ts +39 -0
- package/src/lib/usage/ai-usage-meter.js +85 -0
- package/src/lib/usage/ai-usage-meter.js.map +1 -0
- package/src/lib/usage/ai-usage-wire.d.ts +184 -0
- package/src/lib/usage/ai-usage-wire.js +98 -0
- package/src/lib/usage/ai-usage-wire.js.map +1 -0
- package/src/lib/usage/assist-ceiling.d.ts +87 -0
- package/src/lib/usage/assist-ceiling.js +110 -0
- package/src/lib/usage/assist-ceiling.js.map +1 -0
- package/src/lib/usage/assist-free-taste.d.ts +225 -0
- package/src/lib/usage/assist-free-taste.js +308 -0
- package/src/lib/usage/assist-free-taste.js.map +1 -0
- package/src/lib/usage/assist-refusals.d.ts +69 -0
- package/src/lib/usage/assist-refusals.js +79 -0
- package/src/lib/usage/assist-refusals.js.map +1 -0
- package/src/lib/usage/assist-signal-mining.d.ts +375 -0
- package/src/lib/usage/assist-signal-mining.js +344 -0
- package/src/lib/usage/assist-signal-mining.js.map +1 -0
- package/src/lib/usage/assist-usage.d.ts +571 -0
- package/src/lib/usage/assist-usage.js +978 -0
- package/src/lib/usage/assist-usage.js.map +1 -0
- package/src/lib/usage/staff-org-ai.d.ts +242 -0
- package/src/lib/usage/staff-org-ai.js +173 -0
- package/src/lib/usage/staff-org-ai.js.map +1 -0
- package/src/lib/usage/staff-org-usage-ai.d.ts +83 -0
- package/src/lib/usage/staff-org-usage-ai.js +59 -0
- package/src/lib/usage/staff-org-usage-ai.js.map +1 -0
- package/src/lib/usage/staff-orgs-ai-spend.d.ts +83 -0
- package/src/lib/usage/staff-orgs-ai-spend.js +114 -0
- package/src/lib/usage/staff-orgs-ai-spend.js.map +1 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/activity/ai-activity-actions.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * The AI actions an activity log can carry (AGL-2929).\n *\n * Every other action in `orgs/{orgId}/activity` and `hosts/{hostId}/activity`\n * is a prose sentence written at the call site — \"Saved the screen\". The AI\n * rows are CODES instead, because they are read by more than a person: the\n * org feed's \"AI\" chip, the staff audit facet and the actor table all need\n * to recognize an AI row without parsing a sentence, and a sentence that\n * three writers phrase three ways is three rows that look unrelated.\n *\n * One list, so the writers in `ai-activity.ts`, the feed presenter and the\n * staff facet cannot disagree about what counts as AI. A code missing from\n * `AI_ACTIVITY_ACTION_LABELS` fails the type, not the reader.\n */\n\nimport type { AiJobOutputResource } from '../model/ai-jobs.types'\nimport {\n pluginStaffAuditActionGroup,\n pluginStaffAuditActionGroupLabel,\n registerPluginActivityActions,\n type PluginActivityScope,\n} from '@aglyn/aglyn/plugin-manager/plugin-activity-actions'\n\n/** The action code each AI writer stores. */\nexport const AI_ACTIVITY_ACTIONS = {\n jobCreated: 'ai.job.created',\n jobOutput: 'ai.job.output',\n jobCanceled: 'ai.job.canceled',\n jobNeedsInput: 'ai.job.needs_input',\n editApplied: 'ai.edit.applied',\n seoApplied: 'ai.seo.applied',\n assistSection: 'ai.assist.section',\n overageHardCap: 'ai.overage.hardCap',\n overageCap: 'ai.overage.cap',\n allotmentChanged: 'ai.allotment.changed',\n permissionChanged: 'ai.permission.changed',\n addonPurchased: 'ai.addon.purchased',\n addonRemoved: 'ai.addon.removed',\n} as const\n\nexport type AiActivityAction =\n (typeof AI_ACTIVITY_ACTIONS)[keyof typeof AI_ACTIVITY_ACTIONS]\n\n/** What a person reads for each code, in the feed and the actor table. */\nexport const AI_ACTIVITY_ACTION_LABELS: Record<AiActivityAction, string> = {\n 'ai.job.created': 'Started an AI generation',\n 'ai.job.output': 'AI generated',\n 'ai.job.canceled': 'Canceled an AI generation',\n 'ai.job.needs_input': 'AI generation paused for input',\n 'ai.edit.applied': 'Applied AI edits',\n 'ai.seo.applied': 'Applied AI SEO fixes as drafts',\n 'ai.assist.section': 'AI generated a section',\n 'ai.overage.hardCap': 'AI stop-at-band switch',\n 'ai.overage.cap': 'AI overage ceiling',\n 'ai.allotment.changed': 'AI allotment changed',\n 'ai.permission.changed': 'AI permission changed',\n 'ai.addon.purchased': 'Added the AI add-on',\n 'ai.addon.removed': 'Removed the AI add-on',\n}\n\n/** Every code, in catalog order — what a filter sends as `isAnyOf`. */\nexport const AI_ACTIVITY_ACTION_LIST: readonly AiActivityAction[] =\n Object.values(AI_ACTIVITY_ACTIONS)\n\n/** The feed's filter chip and the staff facet's group, by one name. */\nexport const AI_ACTIVITY_FILTER_LABEL = 'AI'\n\n/**\n * Why a generation stopped and asked for a person (AGL-2904): the plan's\n * band ran out, the org's own ceiling refused, the monthly message cap or\n * the job's own token budget did — or, on the Free taste (AGL-2925), one of\n * its own precautions: the account's credits, its daily request cap, a\n * pause after declined briefs, or the platform's day of free spend. Those\n * are the meter's `AssistRefusedBy` less its `null`, so a ceiling the meter\n * can name is one the feed can label. The last three are the job's own: its\n * plan is ready for review, or an answer broke a building rule on its re-ask\n * (AGL-2935), or the site is at an allowance its plan sets for what the job\n * writes (AGL-2909).\n */\nexport type AiJobNeedsInputReason =\n | 'band'\n | 'cap'\n | 'messages'\n | 'budget'\n | 'allotment'\n | 'account'\n | 'requests'\n | 'refusals'\n | 'platform'\n | 'plan'\n | 'doctrine'\n | 'limit'\n\nexport const AI_JOB_NEEDS_INPUT_REASON_LABELS: Record<\n AiJobNeedsInputReason,\n string\n> = {\n plan: 'its plan is ready for review',\n doctrine: 'its answer broke a building rule twice',\n limit: 'the site reached an allowance of its plan',\n band: 'the included AI band is used up',\n cap: 'the overage ceiling was reached',\n messages: 'the monthly message cap was reached',\n budget: 'the job budget was reached',\n allotment: 'the creator’s or the site’s AI allotment is used up',\n account: 'the account’s free AI credits are used up',\n requests: 'the daily free request cap was reached',\n refusals: 'free generation is paused for the day after declined briefs',\n platform: 'free AI generation is paused for the day',\n}\n\n/**\n * The feed target types a generation job's output can be filed under: the\n * kinds both activity logs know, so the org row and its host copy share a\n * shape.\n */\nexport type AiOutputTargetType =\n | 'screen'\n | 'layout'\n | 'component'\n | 'template'\n | 'workflow'\n | 'content'\n | 'theme'\n\n/**\n * Where the feed files each resource kind a job can write (AGL-2904).\n *\n * A job names its output by the resource it wrote, and the activity logs\n * know a narrower set of targets. The map is total, so a resource kind\n * added to the job document must say where the feed shows it before the\n * machine can log it. `reusableComponent` is the feed's `component`; a\n * `text` output is copy, which the feed files as `content`; a `theme`\n * proposal is filed under the site's theme, which the host feed links to the\n * Theme section (AGL-2938); the kinds whose runners have not shipped are\n * content of the site too, and are filed there until a target of their own\n * exists.\n */\nconst AI_OUTPUT_TARGET_TYPES: Record<AiJobOutputResource, AiOutputTargetType> = {\n screen: 'screen',\n reusableComponent: 'component',\n layout: 'layout',\n template: 'template',\n form: 'content',\n emailScreen: 'content',\n campaign: 'content',\n product: 'content',\n experiment: 'content',\n workflow: 'workflow',\n // An SEO proposal (AGL-2910) is about the site's content, and is filed there.\n seo: 'content',\n text: 'content',\n theme: 'theme',\n // An insight answer (AGL-2915) is about the site's figures; the feed row\n // names it and never what it says.\n insight: 'content',\n // A CRM proposal (AGL-2917) writes nothing; the feed files it with content.\n crm: 'content',\n}\n\nexport function aiOutputTargetType(resource: AiJobOutputResource): AiOutputTargetType {\n return AI_OUTPUT_TARGET_TYPES[resource]\n}\n\n/** Whether a stored action is one of the AI codes above. */\nexport function isAiActivityAction(action: unknown): action is AiActivityAction {\n return (\n typeof action === 'string' &&\n (AI_ACTIVITY_ACTION_LIST as readonly string[]).includes(action)\n )\n}\n\n/** The readable label for an AI code; `undefined` for any other action. */\nexport function aiActivityActionLabel(action: unknown): string | undefined {\n return isAiActivityAction(action)\n ? AI_ACTIVITY_ACTION_LABELS[action]\n : undefined\n}\n\n/**\n * Staff audit rows that are ABOUT AI without carrying an `ai.` code: the\n * customer's overage controls already write `billing.assistOverage.*`, and\n * the platform's free-spend auto-pause writes `platform.aiFreeSpend.*`\n * (AGL-2925). The audit page's facet folds them under the same group as the\n * codes, because \"what did we do about AI this week\" is one question.\n */\nexport const AI_STAFF_AUDIT_ACTION_PREFIXES: readonly string[] = [\n 'ai.',\n 'billing.assistOverage.',\n 'platform.aiFreeSpend.',\n]\n\n/** The facet group an `adminAudit` action belongs to. */\nexport const STAFF_AUDIT_AI_GROUP = 'ai'\n\n/**\n * Which log each code is written to. The job and edit codes land in both\n * the org feed and the host's copy; the billing and permission codes are\n * org-level facts and land in the org feed alone.\n */\nconst AI_ACTIVITY_ACTION_SCOPES: Record<\n AiActivityAction,\n PluginActivityScope | readonly PluginActivityScope[]\n> = {\n 'ai.job.created': ['org', 'host'],\n 'ai.job.output': ['org', 'host'],\n 'ai.job.canceled': ['org', 'host'],\n 'ai.job.needs_input': ['org', 'host'],\n 'ai.edit.applied': ['org', 'host'],\n 'ai.seo.applied': ['org', 'host'],\n 'ai.assist.section': ['org', 'host'],\n 'ai.overage.hardCap': 'org',\n 'ai.overage.cap': 'org',\n 'ai.allotment.changed': 'org',\n 'ai.permission.changed': 'org',\n 'ai.addon.purchased': 'org',\n 'ai.addon.removed': 'org',\n}\n\n/**\n * The catalog, declared through the generic activity-action seam\n * (AGL-2940) so the feed's chip, the actor table's filter and the staff\n * facet read it from the registry beside every other plugin's codes.\n * `registerAiDeclarations` calls it, in both apps and in the browser.\n */\nexport function registerAiActivityActions(): void {\n registerPluginActivityActions({\n pluginId: 'ai',\n group: {\n id: STAFF_AUDIT_AI_GROUP,\n label: AI_ACTIVITY_FILTER_LABEL,\n staffAuditPrefixes: AI_STAFF_AUDIT_ACTION_PREFIXES.filter(\n (prefix) => prefix !== 'ai.',\n ),\n // The staff cards opening on an org (AGL-2930) and on one account\n // (AGL-2928): reads of spend and attribution, and nothing altered.\n staffAuditAccessActions: ['org.ai-viewed', 'user.ai-usage-viewed'],\n },\n actions: AI_ACTIVITY_ACTION_LIST.map((key) => ({\n key,\n label: AI_ACTIVITY_ACTION_LABELS[key],\n scope: AI_ACTIVITY_ACTION_SCOPES[key],\n })),\n })\n}\n\n/**\n * The group the staff audit facet files an action under: `ai` for every\n * AI row, otherwise the action's leading namespace (`billing`, `org`,\n * `plugins`). Roughly seventy distinct actions write to `adminAudit`, so\n * the facet offers namespaces rather than a seventy-entry menu. Answered\n * by the registry, so every plugin's group is filed the same way.\n */\nexport function staffAuditActionGroup(action: unknown): string {\n return pluginStaffAuditActionGroup(action)\n}\n\n/** How a facet group reads in the menu: `ai` → `AI`, `billing` → `billing`. */\nexport function staffAuditActionGroupLabel(group: string): string {\n return pluginStaffAuditActionGroupLabel(group)\n}\n"],"names":["pluginStaffAuditActionGroup","pluginStaffAuditActionGroupLabel","registerPluginActivityActions","AI_ACTIVITY_ACTIONS","jobCreated","jobOutput","jobCanceled","jobNeedsInput","editApplied","seoApplied","assistSection","overageHardCap","overageCap","allotmentChanged","permissionChanged","addonPurchased","addonRemoved","AI_ACTIVITY_ACTION_LABELS","AI_ACTIVITY_ACTION_LIST","Object","values","AI_ACTIVITY_FILTER_LABEL","AI_JOB_NEEDS_INPUT_REASON_LABELS","plan","doctrine","limit","band","cap","messages","budget","allotment","account","requests","refusals","platform","AI_OUTPUT_TARGET_TYPES","screen","reusableComponent","layout","template","form","emailScreen","campaign","product","experiment","workflow","seo","text","theme","insight","crm","aiOutputTargetType","resource","isAiActivityAction","action","includes","aiActivityActionLabel","undefined","AI_STAFF_AUDIT_ACTION_PREFIXES","STAFF_AUDIT_AI_GROUP","AI_ACTIVITY_ACTION_SCOPES","registerAiActivityActions","pluginId","group","id","label","staffAuditPrefixes","filter","prefix","staffAuditAccessActions","actions","map","key","scope","staffAuditActionGroup","staffAuditActionGroupLabel"],"mappings":"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"}
|
|
@@ -0,0 +1,219 @@
|
|
|
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 AI writers over the two customer-visible activity logs (AGL-2929).
|
|
19
|
+
*
|
|
20
|
+
* Every generation, applied edit and control change lands in
|
|
21
|
+
* `orgs/{orgId}/activity` (and, for a host-scoped output, in
|
|
22
|
+
* `hosts/{hostId}/activity`) through {@link logOrgActivity} and
|
|
23
|
+
* {@link logHostActivity} — never a collection of its own, so the retention
|
|
24
|
+
* `docs/DATA_RETENTION.md` already promises for the activity logs covers
|
|
25
|
+
* these rows without a new entry, and the one permission-gated route that
|
|
26
|
+
* serves the org feed serves them.
|
|
27
|
+
*
|
|
28
|
+
* Each helper owns ONE action code from `AI_ACTIVITY_ACTIONS` and the shape
|
|
29
|
+
* of its target, so a caller cannot store a code the viewers do not know or
|
|
30
|
+
* a target the presenter cannot label. What varies per row is folded into
|
|
31
|
+
* `target.name`, which is the only free text the row carries: the feed reads
|
|
32
|
+
* `<label> — <name>`, and a name like `screen · 240-character brief · Acme`
|
|
33
|
+
* is what makes two jobs distinguishable in a list of them.
|
|
34
|
+
*
|
|
35
|
+
* Attribution follows `logOrgActivity`'s rule: `uid` is nullable because
|
|
36
|
+
* some of these acts HAVE no actor — a job paused by the band with nobody
|
|
37
|
+
* present, an add-on Stripe removed at the period end — and naming the last
|
|
38
|
+
* person who touched the thing would file an act under someone who did not
|
|
39
|
+
* perform it. A caller passes what it verified and nothing more.
|
|
40
|
+
*
|
|
41
|
+
* The control-change writers answer whether a row was written: a control set
|
|
42
|
+
* to the value it already had is not a change, and a feed that said "AI
|
|
43
|
+
* overage ceiling — $25" twice for one decision would read as two decisions.
|
|
44
|
+
*/
|
|
45
|
+
import type { HostActivityActor } from '@aglyn/aglyn/app-utils/activity-presenter';
|
|
46
|
+
import { type AiJobNeedsInputReason } from './ai-activity-actions';
|
|
47
|
+
import type { OrgSeatAddons } from '@aglyn/aglyn/server';
|
|
48
|
+
import { type HostActivityTarget, type OrgActivityTarget } from '@aglyn/tenant-data-admin/server/organizations';
|
|
49
|
+
/** Who performed the act — `uid: null` when nobody was present. */
|
|
50
|
+
export interface AiActivityActor {
|
|
51
|
+
uid: string | null;
|
|
52
|
+
email?: string | null;
|
|
53
|
+
}
|
|
54
|
+
/** The resource kinds a generation job can produce. */
|
|
55
|
+
export type AiOutputResourceType = Extract<OrgActivityTarget['type'], HostActivityTarget['type']>;
|
|
56
|
+
/**
|
|
57
|
+
* `ai.job.created` — a generation job was briefed (AGL-2904).
|
|
58
|
+
*
|
|
59
|
+
* Names the job's kind, how long the brief was and the site it targets, so
|
|
60
|
+
* the row says what was asked for without storing the brief itself.
|
|
61
|
+
*/
|
|
62
|
+
export declare function logAiJobCreated(orgId: string, actor: AiActivityActor, job: {
|
|
63
|
+
jobId: string;
|
|
64
|
+
/** What the job builds — a screen, a site, a section. */
|
|
65
|
+
kind: string;
|
|
66
|
+
briefLength: number;
|
|
67
|
+
hostId?: string | null;
|
|
68
|
+
hostName?: string | null;
|
|
69
|
+
}): Promise<void>;
|
|
70
|
+
/**
|
|
71
|
+
* `ai.job.output` — one resource a job produced, one row per output.
|
|
72
|
+
*
|
|
73
|
+
* The org row names the resource, and a host-scoped output is copied into
|
|
74
|
+
* the site's own feed so a site's activity shows what was generated on it.
|
|
75
|
+
* The copy needs a uid: the host log's contract has no anonymous actor, so a
|
|
76
|
+
* job that finished with nobody present still lands in the org feed and
|
|
77
|
+
* only there.
|
|
78
|
+
*/
|
|
79
|
+
export declare function logAiJobOutput(orgId: string, actor: AiActivityActor, output: {
|
|
80
|
+
jobId: string;
|
|
81
|
+
hostId?: string | null;
|
|
82
|
+
resource: {
|
|
83
|
+
type: AiOutputResourceType;
|
|
84
|
+
id: string;
|
|
85
|
+
name?: string | null;
|
|
86
|
+
versionId?: string | null;
|
|
87
|
+
};
|
|
88
|
+
}): Promise<void>;
|
|
89
|
+
/** `ai.job.canceled` — a job was stopped before it finished. */
|
|
90
|
+
export declare function logAiJobCanceled(orgId: string, actor: AiActivityActor, job: {
|
|
91
|
+
jobId: string;
|
|
92
|
+
kind?: string | null;
|
|
93
|
+
name?: string | null;
|
|
94
|
+
}): Promise<void>;
|
|
95
|
+
/**
|
|
96
|
+
* `ai.job.needs_input` — a job stopped and asked for a person, and why.
|
|
97
|
+
* Usually actorless: the band, the ceiling or the budget stopped it, not a
|
|
98
|
+
* member.
|
|
99
|
+
*/
|
|
100
|
+
export declare function logAiJobNeedsInput(orgId: string, actor: AiActivityActor, job: {
|
|
101
|
+
jobId: string;
|
|
102
|
+
kind?: string | null;
|
|
103
|
+
reason: AiJobNeedsInputReason;
|
|
104
|
+
}): Promise<void>;
|
|
105
|
+
/**
|
|
106
|
+
* `ai.edit.applied` — a proposal's edits landed on a besigner document
|
|
107
|
+
* (AGL-2906).
|
|
108
|
+
*
|
|
109
|
+
* The edits are applied in the author's own editor, as unsaved changes, so
|
|
110
|
+
* no server sees them land. The row is written by the door the editor
|
|
111
|
+
* reports the apply to, and only once that door has found the proposal on an
|
|
112
|
+
* exchange the same member had about the same document — so it stands on a
|
|
113
|
+
* proposal the server issued rather than on the client's word alone. Op
|
|
114
|
+
* counts are folded into the name (`Home · 3 set, 1 insert`); the edits
|
|
115
|
+
* themselves are the site's content and are not logged.
|
|
116
|
+
*/
|
|
117
|
+
export declare function logAiEditApplied(hostId: string, actor: HostActivityActor, edit: {
|
|
118
|
+
/** The kind of document the edits landed on. */
|
|
119
|
+
type: 'screen' | 'component' | 'layout';
|
|
120
|
+
id: string;
|
|
121
|
+
name?: string | null;
|
|
122
|
+
versionId: string;
|
|
123
|
+
/** Edits applied, by operation — `{ set: 3, insert: 1 }`. */
|
|
124
|
+
opCounts: Record<string, number>;
|
|
125
|
+
}): Promise<void>;
|
|
126
|
+
/**
|
|
127
|
+
* `ai.seo.applied` — a site audit's fixes were applied as drafts (AGL-2910).
|
|
128
|
+
*
|
|
129
|
+
* Written by the door that applied them. The name carries the counts — new
|
|
130
|
+
* unpublished versions, listings staged for a person to save — and never
|
|
131
|
+
* the text proposed, which is the site's content. Org feed, and the site's
|
|
132
|
+
* own feed when a person is named.
|
|
133
|
+
*/
|
|
134
|
+
export declare function logAiSeoApplied(orgId: string, actor: AiActivityActor, apply: {
|
|
135
|
+
jobId: string;
|
|
136
|
+
hostId: string;
|
|
137
|
+
hostName?: string | null;
|
|
138
|
+
versions: number;
|
|
139
|
+
staged: number;
|
|
140
|
+
}): Promise<void>;
|
|
141
|
+
/**
|
|
142
|
+
* `ai.assist.section` — the assist door returned a section subtree.
|
|
143
|
+
*
|
|
144
|
+
* Into the site's feed when the request named a site, else the org's, so
|
|
145
|
+
* the act is never unlogged for want of a host. Element rewrites are not
|
|
146
|
+
* logged here at all — too chatty — and the per-user rollup carries their
|
|
147
|
+
* count. The instruction is the customer's own copy and is not stored.
|
|
148
|
+
*/
|
|
149
|
+
export declare function logAiAssistSection(actor: AiActivityActor, section: {
|
|
150
|
+
orgId: string;
|
|
151
|
+
hostId?: string | null;
|
|
152
|
+
hostName?: string | null;
|
|
153
|
+
nodeCount: number;
|
|
154
|
+
}): Promise<void>;
|
|
155
|
+
/** The two overage controls a customer holds (AGL-2653, AGL-2898). */
|
|
156
|
+
export type AiOverageControlChange = {
|
|
157
|
+
control: 'hardCap';
|
|
158
|
+
before: boolean;
|
|
159
|
+
after: boolean;
|
|
160
|
+
} | {
|
|
161
|
+
control: 'cap';
|
|
162
|
+
before: number | null;
|
|
163
|
+
after: number | null;
|
|
164
|
+
};
|
|
165
|
+
/**
|
|
166
|
+
* `ai.overage.hardCap` / `ai.overage.cap` — a control moved.
|
|
167
|
+
*
|
|
168
|
+
* The routes already write `adminAudit`; this is the org-feed row that
|
|
169
|
+
* lets the customer see who set the control. Answers `false`, and writes
|
|
170
|
+
* nothing, when the value did not move.
|
|
171
|
+
*/
|
|
172
|
+
export declare function logAiOverageControl(orgId: string, actor: AiActivityActor, change: AiOverageControlChange): Promise<boolean>;
|
|
173
|
+
/**
|
|
174
|
+
* `ai.allotment.changed` — a manager set, changed or removed an AI allotment
|
|
175
|
+
* (AGL-2942): a member's, a collaborator's on one site, a site's, or the
|
|
176
|
+
* org-wide model restriction. The subject is the row's target; what it was
|
|
177
|
+
* set to is the name, in credits, never dollars.
|
|
178
|
+
*/
|
|
179
|
+
export declare function logAiAllotmentChanged(orgId: string, actor: AiActivityActor, change: {
|
|
180
|
+
subject: {
|
|
181
|
+
type: 'org' | 'member' | 'host';
|
|
182
|
+
id?: string | null;
|
|
183
|
+
name?: string | null;
|
|
184
|
+
};
|
|
185
|
+
/** `null` when the allotment was removed. */
|
|
186
|
+
after: {
|
|
187
|
+
credits: number | null;
|
|
188
|
+
mode: 'hard' | 'soft';
|
|
189
|
+
models: readonly string[] | null;
|
|
190
|
+
} | null;
|
|
191
|
+
}): Promise<void>;
|
|
192
|
+
/**
|
|
193
|
+
* `ai.permission.changed` — an AI permission moved on a role, a member's
|
|
194
|
+
* override, a collaborator's site toggle or the org's default. The subject
|
|
195
|
+
* is the row's target; the permission and its direction are the name.
|
|
196
|
+
*/
|
|
197
|
+
export declare function logAiPermissionChanged(orgId: string, actor: AiActivityActor, change: {
|
|
198
|
+
subject: {
|
|
199
|
+
type: 'org' | 'role' | 'member' | 'host';
|
|
200
|
+
id?: string | null;
|
|
201
|
+
name?: string | null;
|
|
202
|
+
};
|
|
203
|
+
/** The permission key that moved — `ai.assist`, `ai.generate`. */
|
|
204
|
+
permission: string;
|
|
205
|
+
granted: boolean;
|
|
206
|
+
}): Promise<void>;
|
|
207
|
+
/**
|
|
208
|
+
* `ai.addon.purchased` / `ai.addon.removed` — the AI add-on came or went.
|
|
209
|
+
*
|
|
210
|
+
* Decided off the mirrored `seatAddons` maps rather than told, because the
|
|
211
|
+
* add-ons route mirrors the purchase at once and the webhook re-derives the
|
|
212
|
+
* same map on every subscription event: comparing before and after is what
|
|
213
|
+
* keeps a redelivery, or the webhook confirming a purchase the route already
|
|
214
|
+
* logged, from writing the row twice. Answers `false` when nothing moved.
|
|
215
|
+
*/
|
|
216
|
+
export declare function logAiAddonChanged(orgId: string, actor: AiActivityActor, change: {
|
|
217
|
+
before: OrgSeatAddons | null | undefined;
|
|
218
|
+
after: OrgSeatAddons | null | undefined;
|
|
219
|
+
}): Promise<boolean>;
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/ /**
|
|
17
|
+
* The AI writers over the two customer-visible activity logs (AGL-2929).
|
|
18
|
+
*
|
|
19
|
+
* Every generation, applied edit and control change lands in
|
|
20
|
+
* `orgs/{orgId}/activity` (and, for a host-scoped output, in
|
|
21
|
+
* `hosts/{hostId}/activity`) through {@link logOrgActivity} and
|
|
22
|
+
* {@link logHostActivity} — never a collection of its own, so the retention
|
|
23
|
+
* `docs/DATA_RETENTION.md` already promises for the activity logs covers
|
|
24
|
+
* these rows without a new entry, and the one permission-gated route that
|
|
25
|
+
* serves the org feed serves them.
|
|
26
|
+
*
|
|
27
|
+
* Each helper owns ONE action code from `AI_ACTIVITY_ACTIONS` and the shape
|
|
28
|
+
* of its target, so a caller cannot store a code the viewers do not know or
|
|
29
|
+
* a target the presenter cannot label. What varies per row is folded into
|
|
30
|
+
* `target.name`, which is the only free text the row carries: the feed reads
|
|
31
|
+
* `<label> — <name>`, and a name like `screen · 240-character brief · Acme`
|
|
32
|
+
* is what makes two jobs distinguishable in a list of them.
|
|
33
|
+
*
|
|
34
|
+
* Attribution follows `logOrgActivity`'s rule: `uid` is nullable because
|
|
35
|
+
* some of these acts HAVE no actor — a job paused by the band with nobody
|
|
36
|
+
* present, an add-on Stripe removed at the period end — and naming the last
|
|
37
|
+
* person who touched the thing would file an act under someone who did not
|
|
38
|
+
* perform it. A caller passes what it verified and nothing more.
|
|
39
|
+
*
|
|
40
|
+
* The control-change writers answer whether a row was written: a control set
|
|
41
|
+
* to the value it already had is not a change, and a feed that said "AI
|
|
42
|
+
* overage ceiling — $25" twice for one decision would read as two decisions.
|
|
43
|
+
*/ import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
44
|
+
import { AI_ACTIVITY_ACTIONS, AI_JOB_NEEDS_INPUT_REASON_LABELS } from "./ai-activity-actions.js";
|
|
45
|
+
import { aiAddonName, aiAddonUnits } from "@aglyn/aglyn/app-utils/plan-entitlements";
|
|
46
|
+
import { logHostActivity, logOrgActivity } from "@aglyn/tenant-data-admin/server/organizations";
|
|
47
|
+
/** The pieces a target name is built from, blanks dropped. */ const named = (...parts)=>parts.map((part)=>part === null || part === undefined ? '' : String(part).trim()).filter(Boolean).join(' · ');
|
|
48
|
+
/** A verified uid, or nothing: the host log has no anonymous actor. */ const hostActor = (actor)=>{
|
|
49
|
+
var _actor_email;
|
|
50
|
+
return actor.uid ? {
|
|
51
|
+
uid: actor.uid,
|
|
52
|
+
email: (_actor_email = actor.email) != null ? _actor_email : null
|
|
53
|
+
} : null;
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* `ai.job.created` — a generation job was briefed (AGL-2904).
|
|
57
|
+
*
|
|
58
|
+
* Names the job's kind, how long the brief was and the site it targets, so
|
|
59
|
+
* the row says what was asked for without storing the brief itself.
|
|
60
|
+
*/ export async function logAiJobCreated(orgId, actor, job) {
|
|
61
|
+
var _job_hostName;
|
|
62
|
+
await logOrgActivity(orgId, actor, AI_ACTIVITY_ACTIONS.jobCreated, {
|
|
63
|
+
type: 'aiJob',
|
|
64
|
+
id: job.jobId,
|
|
65
|
+
name: named(job.kind, `${Math.max(0, Math.floor(job.briefLength))}-character brief`, (_job_hostName = job.hostName) != null ? _job_hostName : job.hostId)
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* `ai.job.output` — one resource a job produced, one row per output.
|
|
70
|
+
*
|
|
71
|
+
* The org row names the resource, and a host-scoped output is copied into
|
|
72
|
+
* the site's own feed so a site's activity shows what was generated on it.
|
|
73
|
+
* The copy needs a uid: the host log's contract has no anonymous actor, so a
|
|
74
|
+
* job that finished with nobody present still lands in the org feed and
|
|
75
|
+
* only there.
|
|
76
|
+
*/ export async function logAiJobOutput(orgId, actor, output) {
|
|
77
|
+
const target = _extends({
|
|
78
|
+
type: output.resource.type,
|
|
79
|
+
id: output.resource.id
|
|
80
|
+
}, output.resource.name ? {
|
|
81
|
+
name: output.resource.name
|
|
82
|
+
} : {}, output.resource.versionId ? {
|
|
83
|
+
versionId: output.resource.versionId
|
|
84
|
+
} : {});
|
|
85
|
+
await logOrgActivity(orgId, actor, AI_ACTIVITY_ACTIONS.jobOutput, target);
|
|
86
|
+
const onHost = hostActor(actor);
|
|
87
|
+
if (output.hostId && onHost) {
|
|
88
|
+
await logHostActivity(output.hostId, onHost, AI_ACTIVITY_ACTIONS.jobOutput, target);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/** `ai.job.canceled` — a job was stopped before it finished. */ export async function logAiJobCanceled(orgId, actor, job) {
|
|
92
|
+
await logOrgActivity(orgId, actor, AI_ACTIVITY_ACTIONS.jobCanceled, _extends({
|
|
93
|
+
type: 'aiJob',
|
|
94
|
+
id: job.jobId
|
|
95
|
+
}, named(job.kind, job.name) ? {
|
|
96
|
+
name: named(job.kind, job.name)
|
|
97
|
+
} : {}));
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* `ai.job.needs_input` — a job stopped and asked for a person, and why.
|
|
101
|
+
* Usually actorless: the band, the ceiling or the budget stopped it, not a
|
|
102
|
+
* member.
|
|
103
|
+
*/ export async function logAiJobNeedsInput(orgId, actor, job) {
|
|
104
|
+
await logOrgActivity(orgId, actor, AI_ACTIVITY_ACTIONS.jobNeedsInput, {
|
|
105
|
+
type: 'aiJob',
|
|
106
|
+
id: job.jobId,
|
|
107
|
+
name: named(job.kind, AI_JOB_NEEDS_INPUT_REASON_LABELS[job.reason])
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* `ai.edit.applied` — a proposal's edits landed on a besigner document
|
|
112
|
+
* (AGL-2906).
|
|
113
|
+
*
|
|
114
|
+
* The edits are applied in the author's own editor, as unsaved changes, so
|
|
115
|
+
* no server sees them land. The row is written by the door the editor
|
|
116
|
+
* reports the apply to, and only once that door has found the proposal on an
|
|
117
|
+
* exchange the same member had about the same document — so it stands on a
|
|
118
|
+
* proposal the server issued rather than on the client's word alone. Op
|
|
119
|
+
* counts are folded into the name (`Home · 3 set, 1 insert`); the edits
|
|
120
|
+
* themselves are the site's content and are not logged.
|
|
121
|
+
*/ export async function logAiEditApplied(hostId, actor, edit) {
|
|
122
|
+
const counts = Object.entries(edit.opCounts).filter(([, count])=>Number.isFinite(count) && count > 0).map(([op, count])=>`${Math.floor(count)} ${op}`).join(', ');
|
|
123
|
+
await logHostActivity(hostId, actor, AI_ACTIVITY_ACTIONS.editApplied, {
|
|
124
|
+
type: edit.type,
|
|
125
|
+
id: edit.id,
|
|
126
|
+
name: named(edit.name, counts),
|
|
127
|
+
versionId: edit.versionId
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* `ai.seo.applied` — a site audit's fixes were applied as drafts (AGL-2910).
|
|
132
|
+
*
|
|
133
|
+
* Written by the door that applied them. The name carries the counts — new
|
|
134
|
+
* unpublished versions, listings staged for a person to save — and never
|
|
135
|
+
* the text proposed, which is the site's content. Org feed, and the site's
|
|
136
|
+
* own feed when a person is named.
|
|
137
|
+
*/ export async function logAiSeoApplied(orgId, actor, apply) {
|
|
138
|
+
var _apply_hostName;
|
|
139
|
+
const versions = Math.max(0, Math.floor(apply.versions));
|
|
140
|
+
const staged = Math.max(0, Math.floor(apply.staged));
|
|
141
|
+
const target = {
|
|
142
|
+
type: 'aiJob',
|
|
143
|
+
id: apply.jobId,
|
|
144
|
+
name: named((_apply_hostName = apply.hostName) != null ? _apply_hostName : apply.hostId, `${versions} draft ${versions === 1 ? 'version' : 'versions'}`, `${staged} ${staged === 1 ? 'listing' : 'listings'} to review`)
|
|
145
|
+
};
|
|
146
|
+
await logOrgActivity(orgId, actor, AI_ACTIVITY_ACTIONS.seoApplied, target);
|
|
147
|
+
const onHost = hostActor(actor);
|
|
148
|
+
if (onHost) {
|
|
149
|
+
await logHostActivity(apply.hostId, onHost, AI_ACTIVITY_ACTIONS.seoApplied, {
|
|
150
|
+
type: 'host',
|
|
151
|
+
id: apply.hostId,
|
|
152
|
+
name: target.name
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* `ai.assist.section` — the assist door returned a section subtree.
|
|
158
|
+
*
|
|
159
|
+
* Into the site's feed when the request named a site, else the org's, so
|
|
160
|
+
* the act is never unlogged for want of a host. Element rewrites are not
|
|
161
|
+
* logged here at all — too chatty — and the per-user rollup carries their
|
|
162
|
+
* count. The instruction is the customer's own copy and is not stored.
|
|
163
|
+
*/ export async function logAiAssistSection(actor, section) {
|
|
164
|
+
var _section_hostName;
|
|
165
|
+
const nodes = Math.max(0, Math.floor(section.nodeCount));
|
|
166
|
+
const size = `${nodes} ${nodes === 1 ? 'element' : 'elements'}`;
|
|
167
|
+
const onHost = hostActor(actor);
|
|
168
|
+
if (section.hostId && onHost) {
|
|
169
|
+
await logHostActivity(section.hostId, onHost, AI_ACTIVITY_ACTIONS.assistSection, {
|
|
170
|
+
type: 'host',
|
|
171
|
+
id: section.hostId,
|
|
172
|
+
name: named(section.hostName, size)
|
|
173
|
+
});
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
await logOrgActivity(section.orgId, actor, AI_ACTIVITY_ACTIONS.assistSection, {
|
|
177
|
+
type: 'org',
|
|
178
|
+
name: named((_section_hostName = section.hostName) != null ? _section_hostName : section.hostId, size)
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
const usd = (value)=>`$${value.toLocaleString('en-US')}`;
|
|
182
|
+
/**
|
|
183
|
+
* `ai.overage.hardCap` / `ai.overage.cap` — a control moved.
|
|
184
|
+
*
|
|
185
|
+
* The routes already write `adminAudit`; this is the org-feed row that
|
|
186
|
+
* lets the customer see who set the control. Answers `false`, and writes
|
|
187
|
+
* nothing, when the value did not move.
|
|
188
|
+
*/ export async function logAiOverageControl(orgId, actor, change) {
|
|
189
|
+
if (change.before === change.after) return false;
|
|
190
|
+
if (change.control === 'hardCap') {
|
|
191
|
+
await logOrgActivity(orgId, actor, AI_ACTIVITY_ACTIONS.overageHardCap, {
|
|
192
|
+
type: 'org',
|
|
193
|
+
name: change.after ? 'On' : 'Off'
|
|
194
|
+
});
|
|
195
|
+
return true;
|
|
196
|
+
}
|
|
197
|
+
await logOrgActivity(orgId, actor, AI_ACTIVITY_ACTIONS.overageCap, {
|
|
198
|
+
type: 'org',
|
|
199
|
+
name: change.after === null ? 'Cleared' : usd(change.after)
|
|
200
|
+
});
|
|
201
|
+
return true;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* `ai.allotment.changed` — a manager set, changed or removed an AI allotment
|
|
205
|
+
* (AGL-2942): a member's, a collaborator's on one site, a site's, or the
|
|
206
|
+
* org-wide model restriction. The subject is the row's target; what it was
|
|
207
|
+
* set to is the name, in credits, never dollars.
|
|
208
|
+
*/ export async function logAiAllotmentChanged(orgId, actor, change) {
|
|
209
|
+
var _after_models;
|
|
210
|
+
const after = change.after;
|
|
211
|
+
await logOrgActivity(orgId, actor, AI_ACTIVITY_ACTIONS.allotmentChanged, _extends({
|
|
212
|
+
type: change.subject.type
|
|
213
|
+
}, change.subject.id ? {
|
|
214
|
+
id: change.subject.id
|
|
215
|
+
} : {}, {
|
|
216
|
+
name: named(change.subject.name, after === null ? 'removed' : after.credits === null ? null : `${after.credits.toLocaleString('en-US')} credits a month (${after.mode})`, (after == null ? void 0 : (_after_models = after.models) == null ? void 0 : _after_models.length) ? `${after.models.length} models allowed` : null)
|
|
217
|
+
}));
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* `ai.permission.changed` — an AI permission moved on a role, a member's
|
|
221
|
+
* override, a collaborator's site toggle or the org's default. The subject
|
|
222
|
+
* is the row's target; the permission and its direction are the name.
|
|
223
|
+
*/ export async function logAiPermissionChanged(orgId, actor, change) {
|
|
224
|
+
await logOrgActivity(orgId, actor, AI_ACTIVITY_ACTIONS.permissionChanged, _extends({
|
|
225
|
+
type: change.subject.type
|
|
226
|
+
}, change.subject.id ? {
|
|
227
|
+
id: change.subject.id
|
|
228
|
+
} : {}, {
|
|
229
|
+
name: named(change.subject.name, `${change.permission} ${change.granted ? 'granted' : 'revoked'}`)
|
|
230
|
+
}));
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* `ai.addon.purchased` / `ai.addon.removed` — the AI add-on came or went.
|
|
234
|
+
*
|
|
235
|
+
* Decided off the mirrored `seatAddons` maps rather than told, because the
|
|
236
|
+
* add-ons route mirrors the purchase at once and the webhook re-derives the
|
|
237
|
+
* same map on every subscription event: comparing before and after is what
|
|
238
|
+
* keeps a redelivery, or the webhook confirming a purchase the route already
|
|
239
|
+
* logged, from writing the row twice. Answers `false` when nothing moved.
|
|
240
|
+
*/ export async function logAiAddonChanged(orgId, actor, change) {
|
|
241
|
+
const before = aiAddonUnits(change.before);
|
|
242
|
+
const after = aiAddonUnits(change.after);
|
|
243
|
+
if (before === after) return false;
|
|
244
|
+
await logOrgActivity(orgId, actor, after === 1 ? AI_ACTIVITY_ACTIONS.addonPurchased : AI_ACTIVITY_ACTIONS.addonRemoved, {
|
|
245
|
+
type: 'subscription',
|
|
246
|
+
name: aiAddonName()
|
|
247
|
+
});
|
|
248
|
+
return true;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
//# sourceMappingURL=ai-activity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/activity/ai-activity.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * The AI writers over the two customer-visible activity logs (AGL-2929).\n *\n * Every generation, applied edit and control change lands in\n * `orgs/{orgId}/activity` (and, for a host-scoped output, in\n * `hosts/{hostId}/activity`) through {@link logOrgActivity} and\n * {@link logHostActivity} — never a collection of its own, so the retention\n * `docs/DATA_RETENTION.md` already promises for the activity logs covers\n * these rows without a new entry, and the one permission-gated route that\n * serves the org feed serves them.\n *\n * Each helper owns ONE action code from `AI_ACTIVITY_ACTIONS` and the shape\n * of its target, so a caller cannot store a code the viewers do not know or\n * a target the presenter cannot label. What varies per row is folded into\n * `target.name`, which is the only free text the row carries: the feed reads\n * `<label> — <name>`, and a name like `screen · 240-character brief · Acme`\n * is what makes two jobs distinguishable in a list of them.\n *\n * Attribution follows `logOrgActivity`'s rule: `uid` is nullable because\n * some of these acts HAVE no actor — a job paused by the band with nobody\n * present, an add-on Stripe removed at the period end — and naming the last\n * person who touched the thing would file an act under someone who did not\n * perform it. A caller passes what it verified and nothing more.\n *\n * The control-change writers answer whether a row was written: a control set\n * to the value it already had is not a change, and a feed that said \"AI\n * overage ceiling — $25\" twice for one decision would read as two decisions.\n */\n\nimport type { HostActivityActor } from '@aglyn/aglyn/app-utils/activity-presenter'\nimport {\n AI_ACTIVITY_ACTIONS,\n AI_JOB_NEEDS_INPUT_REASON_LABELS,\n type AiJobNeedsInputReason,\n} from './ai-activity-actions'\nimport {\n aiAddonName,\n aiAddonUnits,\n} from '@aglyn/aglyn/app-utils/plan-entitlements'\nimport type { OrgSeatAddons } from '@aglyn/aglyn/server'\nimport {\n logHostActivity,\n logOrgActivity,\n type HostActivityTarget,\n type OrgActivityTarget,\n} from '@aglyn/tenant-data-admin/server/organizations'\n\n/** Who performed the act — `uid: null` when nobody was present. */\nexport interface AiActivityActor {\n uid: string | null\n email?: string | null\n}\n\n/** The resource kinds a generation job can produce. */\nexport type AiOutputResourceType = Extract<\n OrgActivityTarget['type'],\n HostActivityTarget['type']\n>\n\n/** The pieces a target name is built from, blanks dropped. */\nconst named = (...parts: Array<string | number | null | undefined>): string =>\n parts\n .map((part) => (part === null || part === undefined ? '' : String(part).trim()))\n .filter(Boolean)\n .join(' · ')\n\n/** A verified uid, or nothing: the host log has no anonymous actor. */\nconst hostActor = (actor: AiActivityActor): HostActivityActor | null =>\n actor.uid ? { uid: actor.uid, email: actor.email ?? null } : null\n\n/**\n * `ai.job.created` — a generation job was briefed (AGL-2904).\n *\n * Names the job's kind, how long the brief was and the site it targets, so\n * the row says what was asked for without storing the brief itself.\n */\nexport async function logAiJobCreated(\n orgId: string,\n actor: AiActivityActor,\n job: {\n jobId: string\n /** What the job builds — a screen, a site, a section. */\n kind: string\n briefLength: number\n hostId?: string | null\n hostName?: string | null\n },\n): Promise<void> {\n await logOrgActivity(orgId, actor, AI_ACTIVITY_ACTIONS.jobCreated, {\n type: 'aiJob',\n id: job.jobId,\n name: named(\n job.kind,\n `${Math.max(0, Math.floor(job.briefLength))}-character brief`,\n job.hostName ?? job.hostId,\n ),\n })\n}\n\n/**\n * `ai.job.output` — one resource a job produced, one row per output.\n *\n * The org row names the resource, and a host-scoped output is copied into\n * the site's own feed so a site's activity shows what was generated on it.\n * The copy needs a uid: the host log's contract has no anonymous actor, so a\n * job that finished with nobody present still lands in the org feed and\n * only there.\n */\nexport async function logAiJobOutput(\n orgId: string,\n actor: AiActivityActor,\n output: {\n jobId: string\n hostId?: string | null\n resource: {\n type: AiOutputResourceType\n id: string\n name?: string | null\n versionId?: string | null\n }\n },\n): Promise<void> {\n const target = {\n type: output.resource.type,\n id: output.resource.id,\n ...(output.resource.name ? { name: output.resource.name } : {}),\n ...(output.resource.versionId ? { versionId: output.resource.versionId } : {}),\n }\n await logOrgActivity(orgId, actor, AI_ACTIVITY_ACTIONS.jobOutput, target)\n const onHost = hostActor(actor)\n if (output.hostId && onHost) {\n await logHostActivity(output.hostId, onHost, AI_ACTIVITY_ACTIONS.jobOutput, target)\n }\n}\n\n/** `ai.job.canceled` — a job was stopped before it finished. */\nexport async function logAiJobCanceled(\n orgId: string,\n actor: AiActivityActor,\n job: { jobId: string; kind?: string | null; name?: string | null },\n): Promise<void> {\n await logOrgActivity(orgId, actor, AI_ACTIVITY_ACTIONS.jobCanceled, {\n type: 'aiJob',\n id: job.jobId,\n ...(named(job.kind, job.name) ? { name: named(job.kind, job.name) } : {}),\n })\n}\n\n/**\n * `ai.job.needs_input` — a job stopped and asked for a person, and why.\n * Usually actorless: the band, the ceiling or the budget stopped it, not a\n * member.\n */\nexport async function logAiJobNeedsInput(\n orgId: string,\n actor: AiActivityActor,\n job: { jobId: string; kind?: string | null; reason: AiJobNeedsInputReason },\n): Promise<void> {\n await logOrgActivity(orgId, actor, AI_ACTIVITY_ACTIONS.jobNeedsInput, {\n type: 'aiJob',\n id: job.jobId,\n name: named(job.kind, AI_JOB_NEEDS_INPUT_REASON_LABELS[job.reason]),\n })\n}\n\n/**\n * `ai.edit.applied` — a proposal's edits landed on a besigner document\n * (AGL-2906).\n *\n * The edits are applied in the author's own editor, as unsaved changes, so\n * no server sees them land. The row is written by the door the editor\n * reports the apply to, and only once that door has found the proposal on an\n * exchange the same member had about the same document — so it stands on a\n * proposal the server issued rather than on the client's word alone. Op\n * counts are folded into the name (`Home · 3 set, 1 insert`); the edits\n * themselves are the site's content and are not logged.\n */\nexport async function logAiEditApplied(\n hostId: string,\n actor: HostActivityActor,\n edit: {\n /** The kind of document the edits landed on. */\n type: 'screen' | 'component' | 'layout'\n id: string\n name?: string | null\n versionId: string\n /** Edits applied, by operation — `{ set: 3, insert: 1 }`. */\n opCounts: Record<string, number>\n },\n): Promise<void> {\n const counts = Object.entries(edit.opCounts)\n .filter(([, count]) => Number.isFinite(count) && count > 0)\n .map(([op, count]) => `${Math.floor(count)} ${op}`)\n .join(', ')\n await logHostActivity(hostId, actor, AI_ACTIVITY_ACTIONS.editApplied, {\n type: edit.type,\n id: edit.id,\n name: named(edit.name, counts),\n versionId: edit.versionId,\n })\n}\n\n/**\n * `ai.seo.applied` — a site audit's fixes were applied as drafts (AGL-2910).\n *\n * Written by the door that applied them. The name carries the counts — new\n * unpublished versions, listings staged for a person to save — and never\n * the text proposed, which is the site's content. Org feed, and the site's\n * own feed when a person is named.\n */\nexport async function logAiSeoApplied(\n orgId: string,\n actor: AiActivityActor,\n apply: {\n jobId: string\n hostId: string\n hostName?: string | null\n versions: number\n staged: number\n },\n): Promise<void> {\n const versions = Math.max(0, Math.floor(apply.versions))\n const staged = Math.max(0, Math.floor(apply.staged))\n const target = {\n type: 'aiJob' as const,\n id: apply.jobId,\n name: named(\n apply.hostName ?? apply.hostId,\n `${versions} draft ${versions === 1 ? 'version' : 'versions'}`,\n `${staged} ${staged === 1 ? 'listing' : 'listings'} to review`,\n ),\n }\n await logOrgActivity(orgId, actor, AI_ACTIVITY_ACTIONS.seoApplied, target)\n const onHost = hostActor(actor)\n if (onHost) {\n await logHostActivity(apply.hostId, onHost, AI_ACTIVITY_ACTIONS.seoApplied, {\n type: 'host',\n id: apply.hostId,\n name: target.name,\n })\n }\n}\n\n/**\n * `ai.assist.section` — the assist door returned a section subtree.\n *\n * Into the site's feed when the request named a site, else the org's, so\n * the act is never unlogged for want of a host. Element rewrites are not\n * logged here at all — too chatty — and the per-user rollup carries their\n * count. The instruction is the customer's own copy and is not stored.\n */\nexport async function logAiAssistSection(\n actor: AiActivityActor,\n section: {\n orgId: string\n hostId?: string | null\n hostName?: string | null\n nodeCount: number\n },\n): Promise<void> {\n const nodes = Math.max(0, Math.floor(section.nodeCount))\n const size = `${nodes} ${nodes === 1 ? 'element' : 'elements'}`\n const onHost = hostActor(actor)\n if (section.hostId && onHost) {\n await logHostActivity(section.hostId, onHost, AI_ACTIVITY_ACTIONS.assistSection, {\n type: 'host',\n id: section.hostId,\n name: named(section.hostName, size),\n })\n return\n }\n await logOrgActivity(section.orgId, actor, AI_ACTIVITY_ACTIONS.assistSection, {\n type: 'org',\n name: named(section.hostName ?? section.hostId, size),\n })\n}\n\n/** The two overage controls a customer holds (AGL-2653, AGL-2898). */\nexport type AiOverageControlChange =\n | { control: 'hardCap'; before: boolean; after: boolean }\n | { control: 'cap'; before: number | null; after: number | null }\n\nconst usd = (value: number): string => `$${value.toLocaleString('en-US')}`\n\n/**\n * `ai.overage.hardCap` / `ai.overage.cap` — a control moved.\n *\n * The routes already write `adminAudit`; this is the org-feed row that\n * lets the customer see who set the control. Answers `false`, and writes\n * nothing, when the value did not move.\n */\nexport async function logAiOverageControl(\n orgId: string,\n actor: AiActivityActor,\n change: AiOverageControlChange,\n): Promise<boolean> {\n if (change.before === change.after) return false\n if (change.control === 'hardCap') {\n await logOrgActivity(orgId, actor, AI_ACTIVITY_ACTIONS.overageHardCap, {\n type: 'org',\n name: change.after ? 'On' : 'Off',\n })\n return true\n }\n await logOrgActivity(orgId, actor, AI_ACTIVITY_ACTIONS.overageCap, {\n type: 'org',\n name: change.after === null ? 'Cleared' : usd(change.after),\n })\n return true\n}\n\n/**\n * `ai.allotment.changed` — a manager set, changed or removed an AI allotment\n * (AGL-2942): a member's, a collaborator's on one site, a site's, or the\n * org-wide model restriction. The subject is the row's target; what it was\n * set to is the name, in credits, never dollars.\n */\nexport async function logAiAllotmentChanged(\n orgId: string,\n actor: AiActivityActor,\n change: {\n subject: {\n type: 'org' | 'member' | 'host'\n id?: string | null\n name?: string | null\n }\n /** `null` when the allotment was removed. */\n after: {\n credits: number | null\n mode: 'hard' | 'soft'\n models: readonly string[] | null\n } | null\n },\n): Promise<void> {\n const after = change.after\n await logOrgActivity(orgId, actor, AI_ACTIVITY_ACTIONS.allotmentChanged, {\n type: change.subject.type,\n ...(change.subject.id ? { id: change.subject.id } : {}),\n name: named(\n change.subject.name,\n after === null\n ? 'removed'\n : after.credits === null\n ? null\n : `${after.credits.toLocaleString('en-US')} credits a month (${after.mode})`,\n after?.models?.length ? `${after.models.length} models allowed` : null,\n ),\n })\n}\n\n/**\n * `ai.permission.changed` — an AI permission moved on a role, a member's\n * override, a collaborator's site toggle or the org's default. The subject\n * is the row's target; the permission and its direction are the name.\n */\nexport async function logAiPermissionChanged(\n orgId: string,\n actor: AiActivityActor,\n change: {\n subject: {\n type: 'org' | 'role' | 'member' | 'host'\n id?: string | null\n name?: string | null\n }\n /** The permission key that moved — `ai.assist`, `ai.generate`. */\n permission: string\n granted: boolean\n },\n): Promise<void> {\n await logOrgActivity(orgId, actor, AI_ACTIVITY_ACTIONS.permissionChanged, {\n type: change.subject.type,\n ...(change.subject.id ? { id: change.subject.id } : {}),\n name: named(\n change.subject.name,\n `${change.permission} ${change.granted ? 'granted' : 'revoked'}`,\n ),\n })\n}\n\n/**\n * `ai.addon.purchased` / `ai.addon.removed` — the AI add-on came or went.\n *\n * Decided off the mirrored `seatAddons` maps rather than told, because the\n * add-ons route mirrors the purchase at once and the webhook re-derives the\n * same map on every subscription event: comparing before and after is what\n * keeps a redelivery, or the webhook confirming a purchase the route already\n * logged, from writing the row twice. Answers `false` when nothing moved.\n */\nexport async function logAiAddonChanged(\n orgId: string,\n actor: AiActivityActor,\n change: {\n before: OrgSeatAddons | null | undefined\n after: OrgSeatAddons | null | undefined\n },\n): Promise<boolean> {\n const before = aiAddonUnits(change.before)\n const after = aiAddonUnits(change.after)\n if (before === after) return false\n await logOrgActivity(\n orgId,\n actor,\n after === 1 ? AI_ACTIVITY_ACTIONS.addonPurchased : AI_ACTIVITY_ACTIONS.addonRemoved,\n { type: 'subscription', name: aiAddonName() },\n )\n return true\n}\n"],"names":["AI_ACTIVITY_ACTIONS","AI_JOB_NEEDS_INPUT_REASON_LABELS","aiAddonName","aiAddonUnits","logHostActivity","logOrgActivity","named","parts","map","part","undefined","String","trim","filter","Boolean","join","hostActor","actor","uid","email","logAiJobCreated","orgId","job","jobCreated","type","id","jobId","name","kind","Math","max","floor","briefLength","hostName","hostId","logAiJobOutput","output","target","resource","versionId","jobOutput","onHost","logAiJobCanceled","jobCanceled","logAiJobNeedsInput","jobNeedsInput","reason","logAiEditApplied","edit","counts","Object","entries","opCounts","count","Number","isFinite","op","editApplied","logAiSeoApplied","apply","versions","staged","seoApplied","logAiAssistSection","section","nodes","nodeCount","size","assistSection","usd","value","toLocaleString","logAiOverageControl","change","before","after","control","overageHardCap","overageCap","logAiAllotmentChanged","allotmentChanged","subject","credits","mode","models","length","logAiPermissionChanged","permissionChanged","permission","granted","logAiAddonChanged","addonPurchased","addonRemoved"],"mappings":"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"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
import { type AiOverageClaim, type AiOverageClaimRefusal } from './ai-overage-ledger';
|
|
18
|
+
import type { AiOverageOrg } from './ai-overage-standing';
|
|
19
|
+
/**
|
|
20
|
+
* The Stripe product the overage line is billed against.
|
|
21
|
+
*
|
|
22
|
+
* A product rather than a bare amount because the PRODUCT carries the tax
|
|
23
|
+
* code the account's automatic tax computes from. Created in test mode
|
|
24
|
+
* first and in live mode only with the owner's yes; until the variable is
|
|
25
|
+
* set, no charge is attempted and the reason says so rather than failing
|
|
26
|
+
* against Stripe.
|
|
27
|
+
*/
|
|
28
|
+
export declare const AI_OVERAGE_PRODUCT_ENV = "STRIPE_PRODUCT_AI_OVERAGE";
|
|
29
|
+
/** The metadata key the reconcile search matches a claim on. */
|
|
30
|
+
export declare const AI_OVERAGE_CHARGE_METADATA_KEY = "chargeId";
|
|
31
|
+
/** What one attempt did, for logs, the sweep's report and specs. */
|
|
32
|
+
export interface AiOverageChargeOutcome {
|
|
33
|
+
charged: boolean;
|
|
34
|
+
chargeId: string | null;
|
|
35
|
+
invoiceId: string | null;
|
|
36
|
+
/** Why nothing was charged, when nothing was. */
|
|
37
|
+
skipped: AiOverageClaimRefusal | 'before-cutover' | 'no-stripe-customer' | 'no-product' | null;
|
|
38
|
+
/** Stripe's message when a charge was attempted and failed. */
|
|
39
|
+
error: string | null;
|
|
40
|
+
}
|
|
41
|
+
/** What the caller must hand over; nothing here reads the org document. */
|
|
42
|
+
export interface AiOverageChargeRequest {
|
|
43
|
+
orgId: string;
|
|
44
|
+
org: AiOverageOrg;
|
|
45
|
+
month: string;
|
|
46
|
+
/** The workspace's Stripe customer, resolved by the caller from billing. */
|
|
47
|
+
stripeCustomerId: string | null;
|
|
48
|
+
now?: Date;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* The line as the customer reads it on the invoice.
|
|
52
|
+
*
|
|
53
|
+
* Credits and retail dollars only. Provider cost never reaches a customer
|
|
54
|
+
* surface, and an invoice is the most customer-facing surface there is.
|
|
55
|
+
*/
|
|
56
|
+
export declare function aiOverageInvoiceDescription(claim: AiOverageClaim): string;
|
|
57
|
+
/**
|
|
58
|
+
* Charges the workspace when its unbilled overage has reached the threshold.
|
|
59
|
+
*
|
|
60
|
+
* Called from `after()` once a metered turn's batch has committed, never on
|
|
61
|
+
* the request's await path: the tokens are already spent, and making a
|
|
62
|
+
* customer wait on a Stripe round trip to be handed an answer they have
|
|
63
|
+
* already paid for is the wrong trade. A charge that does not happen because
|
|
64
|
+
* the process ended is picked up by the reconcile sweep or by the next turn.
|
|
65
|
+
*/
|
|
66
|
+
export declare function maybeChargeAiOverage(firestore: FirebaseFirestore.Firestore, request: AiOverageChargeRequest): Promise<AiOverageChargeOutcome>;
|
|
67
|
+
/**
|
|
68
|
+
* Bills the remainder of a month that has ended.
|
|
69
|
+
*
|
|
70
|
+
* The month's last charge, and the only one that bills below the threshold —
|
|
71
|
+
* there is nothing more to accrue, so anything Stripe will accept is worth
|
|
72
|
+
* settling. A remainder under Stripe's minimum is left unbilled rather than
|
|
73
|
+
* sent as an invoice that can never be paid.
|
|
74
|
+
*/
|
|
75
|
+
export declare function closeOutAiOverage(firestore: FirebaseFirestore.Firestore, request: AiOverageChargeRequest): Promise<AiOverageChargeOutcome>;
|
|
76
|
+
/**
|
|
77
|
+
* Asks Stripe what became of a claim that never reported an outcome.
|
|
78
|
+
*
|
|
79
|
+
* The case is a process that died between claiming and charging, or between
|
|
80
|
+
* charging and recording. The claim id is on the invoice's metadata, so the
|
|
81
|
+
* question "did this claim ever become an invoice" has an answer even though
|
|
82
|
+
* this process never saw one.
|
|
83
|
+
*
|
|
84
|
+
* Stripe's search index is eventually consistent, so "not found" means NOT
|
|
85
|
+
* FOUND YET. A claim is only released after a grace period long enough for
|
|
86
|
+
* the index to have caught up; releasing early would create a second invoice
|
|
87
|
+
* for dollars that are already billed.
|
|
88
|
+
*/
|
|
89
|
+
export declare function reconcileAiOverageCharge(firestore: FirebaseFirestore.Firestore, request: {
|
|
90
|
+
orgId: string;
|
|
91
|
+
month: string;
|
|
92
|
+
chargeId: string;
|
|
93
|
+
claimedAgeMs: number;
|
|
94
|
+
}, options?: {
|
|
95
|
+
graceMs?: number;
|
|
96
|
+
}): Promise<{
|
|
97
|
+
resolved: boolean;
|
|
98
|
+
invoiceId: string | null;
|
|
99
|
+
released: boolean;
|
|
100
|
+
}>;
|
|
101
|
+
/** The path a claimed charge's audit row lives at, for the sweep's query. */
|
|
102
|
+
export declare function aiOverageChargesPath(orgId: string): string;
|