@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/insights/ai-insight-readers.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { checkEntitlement } from '@aglyn/aglyn/app-utils/plan-entitlements'\nimport { isHostPluginEnabled, isPluginEnabled } from '@aglyn/aglyn/plugin-manager/enabled-plugins'\nimport {\n listPluginFigureReaders,\n normalizePluginFigureTable,\n pluginFigureParams,\n pluginFigureReaderPlugin,\n type ResolvedPluginFigureReader,\n} from '@aglyn/aglyn/plugin-manager/plugin-figures'\nimport {\n AI_INSIGHT_MAX_READS,\n AI_INSIGHT_SURFACE_READERS,\n aiInsightCellText,\n type AiInsightSurface,\n type AiInsightTable,\n} from '../model/ai-insight'\nimport { filterEnabledPluginsByReleaseFlags } from '@aglyn/tenant-data-admin/server/release-flags'\nimport type { AiInsightReadRequest } from '../tools/ai-insight-tool'\nimport type { AiDatasetCatalogEntry } from './ai-figure-readers'\n\n/**\n * Which figure readers an insight job may read, and reading them (AGL-2915).\n *\n * The caller's half of the `plugin-figures` contract: the seam carries no\n * authorization, so before a reader is offered to the model — let alone read\n * — this establishes that the surface asks about its kind of figures, that\n * the workspace's plan includes the feature the figures are sold under, and\n * that the plugin whose records they are runs here: past its release flag,\n * on for the workspace and not switched off for the site. The site belonging\n * to the job's workspace, and the member's reach, are the job's own checks.\n */\n\n/** Which of a set of plugins are past their release flags for an org; the platform's flags by default. */\nexport type AiReleasedPlugins = (pluginIds: string[], orgId: string) => Promise<string[]>\n\nconst releasedByFlags: AiReleasedPlugins = (pluginIds, orgId) =>\n filterEnabledPluginsByReleaseFlags(pluginIds, { orgId, authorization: null })\n\nexport interface AiInsightReaderContext {\n orgId: string\n /** The site the figures are about; `null` for a workspace-level question. */\n hostId: string | null\n /** The org document the machine or the door read. */\n org: object | null\n /** The site's host document, already checked to belong to the org; `null` with no site. */\n host: Record<string, unknown> | null\n surface: AiInsightSurface\n released?: AiReleasedPlugins\n}\n\n/** The readers a job on this surface may read, ordered by id so a prompt lists them in the same order every time. */\nexport async function aiInsightReaders(context: AiInsightReaderContext): Promise<ResolvedPluginFigureReader[]> {\n const prefixes = AI_INSIGHT_SURFACE_READERS[context.surface]\n const org = context.org as { enabledPlugins?: string[] } | null\n const candidates = listPluginFigureReaders().filter(({ reader }) => {\n if (!prefixes.includes(reader.id.split('.')[0])) return false\n // A site reader needs a site; a workspace reader reads with or without one.\n if (reader.scope === 'site' && !context.hostId) return false\n return !reader.feature || checkEntitlement(org as never, reader.feature)\n })\n const plugins = [...new Set(candidates.map(pluginFigureReaderPlugin).filter((id): id is string => Boolean(id)))]\n const released = new Set(plugins.length ? await (context.released ?? releasedByFlags)(plugins, context.orgId) : [])\n return candidates.filter((resolved) => {\n const plugin = pluginFigureReaderPlugin(resolved)\n if (!plugin) return true\n if (!released.has(plugin)) return false\n return context.hostId\n ? isHostPluginEnabled(org, context.host as { disabledPlugins?: string[] } | null, plugin)\n : isPluginEnabled(org, plugin)\n })\n}\n\n/** The window a reader is read over: the one asked for when it covers it, else the nearest it does. */\nexport function aiInsightReaderDays(windows: readonly number[], asked: number): number {\n if (!windows.length) return 0\n if (windows.includes(asked)) return asked\n return [...windows].sort((a, b) => Math.abs(a - asked) - Math.abs(b - asked) || a - b)[0]\n}\n\n/** The readers as the read prompt lists them: id, what each answers, its windows and its parameters. */\nexport function aiInsightReaderCatalog(readers: readonly ResolvedPluginFigureReader[]): string {\n return readers\n .map(({ reader }) => {\n const windows = reader.windows.length\n ? ` Windows: ${reader.windows.join(', ')} days.`\n : ' Current totals, with no window: days 0.'\n const params = (reader.params ?? []).length\n ? ` Parameters: ${(reader.params ?? [])\n .map((param) => `${param.name} (${param.required ? 'required' : 'optional'}) — ${param.description}`)\n .join('; ')}`\n : ''\n return `- ${reader.id} — ${reader.label}: ${reader.description}${windows}${params}`\n })\n .join('\\n')\n}\n\n/** The datasets a datasets question may name, as the read prompt lists them. */\nexport function aiInsightDatasetCatalog(datasets: readonly AiDatasetCatalogEntry[]): string {\n if (!datasets.length) return 'There are no datasets you may read here.'\n return datasets\n .map(\n (dataset) =>\n `- ${dataset.name} (id ${dataset.id}): ${dataset.fields.map((field) => `${field.name} [${field.type}]`).join(', ') || 'no fields'}`,\n )\n .join('\\n')\n}\n\nexport interface AiInsightReadResult {\n tables: AiInsightTable[]\n /** Why a request that named a real reader was not read, in its owner's words, for the log. */\n refusals: string[]\n}\n\n/**\n * The tables for the reads a job asked for: each request held to the readers\n * this job may read, its window to that reader's, its parameters to those it\n * declares; each table held to the contract by `normalizePluginFigureTable`.\n * A reader asked for twice with the same window and parameters is read once.\n */\nexport async function readAiInsightTables(\n readers: readonly ResolvedPluginFigureReader[],\n requests: readonly AiInsightReadRequest[],\n base: { orgId: string; hostId: string | null; uid: string | null; now: Date },\n maxTables: number = AI_INSIGHT_MAX_READS,\n): Promise<AiInsightReadResult> {\n const tables: AiInsightTable[] = []\n const refusals: string[] = []\n const seen = new Set<string>()\n for (const request of requests) {\n if (tables.length === maxTables) break\n const resolved = readers.find(({ reader }) => reader.id === request.reader)\n if (!resolved) continue\n const { reader } = resolved\n const days = aiInsightReaderDays(reader.windows, request.days)\n const params = pluginFigureParams(reader, request.params)\n if (params.ok === false) {\n refusals.push(`${reader.id}: missing ${params.missing}`)\n continue\n }\n const key = JSON.stringify([reader.id, days, params.params])\n if (seen.has(key)) continue\n seen.add(key)\n try {\n const read = await reader.read({ ...base, days, params: params.params })\n if (read.ok === false) {\n refusals.push(`${reader.id}: ${read.error}`)\n continue\n }\n const table = normalizePluginFigureTable(read.table)\n if (!table) {\n refusals.push(`${reader.id}: not a table`)\n continue\n }\n tables.push({ ...table, ref: `t${tables.length + 1}`, reader: reader.id, days, scope: reader.scope })\n } catch (error) {\n // One reader's fault is not the answer's: the rest are still read.\n console.error('ai insight reader failed', { reader: reader.id, orgId: base.orgId, error })\n refusals.push(`${reader.id}: failed`)\n }\n }\n return { tables, refusals }\n}\n\n/** One table as the answer prompt shows it: a heading, the columns, numbered rows, and its notes. */\nexport function aiInsightTableText(table: AiInsightTable): string {\n const period = table.period ? ` · ${table.period.from} to ${table.period.to} (${table.period.days} days)` : ''\n const lines = [\n `${table.ref} · ${table.title} (${table.source.label})${period}`,\n `Columns: ${table.columns.map((column) => column.label).join(' | ')}`,\n ...table.rows.map(\n (row, index) =>\n `${index}: ${table.columns.map((column) => aiInsightCellText(table, column.key, row[column.key])).join(' | ')}`,\n ),\n ]\n if (!table.rows.length) lines.push('(no rows)')\n if (table.omitted) lines.push(`${table.omitted} more rows were left out of this table.`)\n for (const note of table.notes) lines.push(`Note: ${note}`)\n return lines.join('\\n')\n}\n"],"names":["checkEntitlement","isHostPluginEnabled","isPluginEnabled","listPluginFigureReaders","normalizePluginFigureTable","pluginFigureParams","pluginFigureReaderPlugin","AI_INSIGHT_MAX_READS","AI_INSIGHT_SURFACE_READERS","aiInsightCellText","filterEnabledPluginsByReleaseFlags","releasedByFlags","pluginIds","orgId","authorization","aiInsightReaders","context","prefixes","surface","org","candidates","filter","reader","includes","id","split","scope","hostId","feature","plugins","Set","map","Boolean","released","length","resolved","plugin","has","host","aiInsightReaderDays","windows","asked","sort","a","b","Math","abs","aiInsightReaderCatalog","readers","join","params","param","name","required","description","label","aiInsightDatasetCatalog","datasets","dataset","fields","field","type","readAiInsightTables","requests","base","maxTables","tables","refusals","seen","request","find","days","ok","push","missing","key","JSON","stringify","add","read","error","table","ref","console","aiInsightTableText","period","from","to","lines","title","source","columns","column","rows","row","index","omitted","note","notes"],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
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 ResolvedPluginRecordFactsReader } from '@aglyn/aglyn/plugin-manager/plugin-record-facts';
|
|
18
|
+
import { type AiCrmRequest } from '../model/ai-crm';
|
|
19
|
+
import type { AiJobAdmissionRefusal } from './ai-job-admission';
|
|
20
|
+
/**
|
|
21
|
+
* Who may read a CRM record for AI (AGL-2917), as the CRM decides it.
|
|
22
|
+
*
|
|
23
|
+
* Asked twice: by the `crm` kind's admission before a job exists, for the
|
|
24
|
+
* member creating it, and by the answer door before it serves a kept answer,
|
|
25
|
+
* for the member reading it — so a member who lost the record since, or a
|
|
26
|
+
* workspace that switched the CRM off, is not shown what was written from it.
|
|
27
|
+
* Apart from the step so the door reads it without the generator.
|
|
28
|
+
*/
|
|
29
|
+
export declare const AI_CRM_UNAVAILABLE_COPY = "Turn on the CRM for this site before using AI with it.";
|
|
30
|
+
/** How a resource's reader is found; the core's registry by default. */
|
|
31
|
+
export type AiCrmReaderLookup = (resource: string) => ResolvedPluginRecordFactsReader | null;
|
|
32
|
+
/** The resource a question's facts are read from, and the record's id there. */
|
|
33
|
+
export declare function aiCrmFactsResource(request: AiCrmRequest): {
|
|
34
|
+
resource: string;
|
|
35
|
+
id: string;
|
|
36
|
+
};
|
|
37
|
+
export interface AiCrmAccessInput {
|
|
38
|
+
firestore: FirebaseFirestore.Firestore;
|
|
39
|
+
orgId: string;
|
|
40
|
+
hostId: string | null;
|
|
41
|
+
resource: string;
|
|
42
|
+
id: string;
|
|
43
|
+
org: object | null;
|
|
44
|
+
/** The member to ask about; absent asks nothing of the reader. */
|
|
45
|
+
uid: string | null | undefined;
|
|
46
|
+
/** A verified staff caller, whom the CRM's reader lets read as it lets staff read a record. */
|
|
47
|
+
staff?: boolean;
|
|
48
|
+
readerFor?: AiCrmReaderLookup;
|
|
49
|
+
now?: Date;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Whether the CRM would let this member read this record here now; `null`
|
|
53
|
+
* admits them.
|
|
54
|
+
*
|
|
55
|
+
* First what an in-process read of the CRM skips of the plugin API
|
|
56
|
+
* dispatcher, in order: a named site is the org's; the CRM is released for
|
|
57
|
+
* the org, switched on where the read runs, and has registered its reader in
|
|
58
|
+
* this process. Then the CRM's own reader, which applies the member's reach,
|
|
59
|
+
* `data.manage`, the plan and the record's visibility, in the CRM's words.
|
|
60
|
+
*/
|
|
61
|
+
export declare function aiCrmAccessRefusal(input: AiCrmAccessInput): Promise<AiJobAdmissionRefusal | null>;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
2
|
+
/**
|
|
3
|
+
* @license
|
|
4
|
+
* Copyright 2026 Aglyn LLC
|
|
5
|
+
*
|
|
6
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
* you may not use this file except in compliance with the License.
|
|
8
|
+
* You may obtain a copy of the License at
|
|
9
|
+
*
|
|
10
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
*
|
|
12
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
* See the License for the specific language governing permissions and
|
|
16
|
+
* limitations under the License.
|
|
17
|
+
*/ import { isHostPluginEnabled, isPluginEnabled } from "@aglyn/aglyn/plugin-manager/enabled-plugins";
|
|
18
|
+
import { pluginRecordFactsReader } from "@aglyn/aglyn/plugin-manager/plugin-record-facts";
|
|
19
|
+
import { resolveOrgIdForHost } from "@aglyn/tenant-data-admin/server/organizations";
|
|
20
|
+
import { filterEnabledPluginsByReleaseFlags } from "@aglyn/tenant-data-admin/server/release-flags";
|
|
21
|
+
import { AI_CRM_FACTS_RESOURCES, AI_CRM_IMPORT_FACTS_RESOURCE, AI_CRM_PLUGIN_ID } from "../model/ai-crm.js";
|
|
22
|
+
/**
|
|
23
|
+
* Who may read a CRM record for AI (AGL-2917), as the CRM decides it.
|
|
24
|
+
*
|
|
25
|
+
* Asked twice: by the `crm` kind's admission before a job exists, for the
|
|
26
|
+
* member creating it, and by the answer door before it serves a kept answer,
|
|
27
|
+
* for the member reading it — so a member who lost the record since, or a
|
|
28
|
+
* workspace that switched the CRM off, is not shown what was written from it.
|
|
29
|
+
* Apart from the step so the door reads it without the generator.
|
|
30
|
+
*/ export const AI_CRM_UNAVAILABLE_COPY = 'Turn on the CRM for this site before using AI with it.';
|
|
31
|
+
/** The resource a question's facts are read from, and the record's id there. */ export function aiCrmFactsResource(request) {
|
|
32
|
+
return request.task === 'mapping' ? {
|
|
33
|
+
resource: AI_CRM_IMPORT_FACTS_RESOURCE,
|
|
34
|
+
id: request.collection
|
|
35
|
+
} : {
|
|
36
|
+
resource: AI_CRM_FACTS_RESOURCES[request.record.kind],
|
|
37
|
+
id: request.record.id
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Whether the CRM would let this member read this record here now; `null`
|
|
42
|
+
* admits them.
|
|
43
|
+
*
|
|
44
|
+
* First what an in-process read of the CRM skips of the plugin API
|
|
45
|
+
* dispatcher, in order: a named site is the org's; the CRM is released for
|
|
46
|
+
* the org, switched on where the read runs, and has registered its reader in
|
|
47
|
+
* this process. Then the CRM's own reader, which applies the member's reach,
|
|
48
|
+
* `data.manage`, the plan and the record's visibility, in the CRM's words.
|
|
49
|
+
*/ export async function aiCrmAccessRefusal(input) {
|
|
50
|
+
var _input_readerFor, _input_org, _input_now;
|
|
51
|
+
const org = input.org;
|
|
52
|
+
let host = null;
|
|
53
|
+
if (input.hostId) {
|
|
54
|
+
var _data;
|
|
55
|
+
const owner = await resolveOrgIdForHost(input.hostId);
|
|
56
|
+
if (!owner || owner !== input.orgId) return {
|
|
57
|
+
status: 404,
|
|
58
|
+
error: 'Unknown site'
|
|
59
|
+
};
|
|
60
|
+
host = (_data = (await input.firestore.collection('hosts').doc(input.hostId).get()).data()) != null ? _data : null;
|
|
61
|
+
}
|
|
62
|
+
const found = ((_input_readerFor = input.readerFor) != null ? _input_readerFor : pluginRecordFactsReader)(input.resource);
|
|
63
|
+
const released = (await filterEnabledPluginsByReleaseFlags([
|
|
64
|
+
AI_CRM_PLUGIN_ID
|
|
65
|
+
], {
|
|
66
|
+
orgId: input.orgId,
|
|
67
|
+
authorization: null
|
|
68
|
+
})).includes(AI_CRM_PLUGIN_ID);
|
|
69
|
+
const enabled = input.hostId ? isHostPluginEnabled(org, host, AI_CRM_PLUGIN_ID) : isPluginEnabled(org, AI_CRM_PLUGIN_ID);
|
|
70
|
+
if (!found || found.pluginId !== AI_CRM_PLUGIN_ID || !released || !enabled) {
|
|
71
|
+
return {
|
|
72
|
+
status: 403,
|
|
73
|
+
error: AI_CRM_UNAVAILABLE_COPY
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
if (!input.uid) return null;
|
|
77
|
+
const read = await found.reader.read(_extends({
|
|
78
|
+
orgId: input.orgId,
|
|
79
|
+
hostId: input.hostId,
|
|
80
|
+
id: input.id,
|
|
81
|
+
uid: input.uid
|
|
82
|
+
}, input.staff ? {
|
|
83
|
+
staff: true
|
|
84
|
+
} : {}, {
|
|
85
|
+
org: (_input_org = input.org) != null ? _input_org : null,
|
|
86
|
+
now: (_input_now = input.now) != null ? _input_now : new Date()
|
|
87
|
+
}));
|
|
88
|
+
return read.ok === false ? {
|
|
89
|
+
status: read.status,
|
|
90
|
+
error: read.error
|
|
91
|
+
} : null;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
//# sourceMappingURL=ai-crm-access.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/jobs/ai-crm-access.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { isHostPluginEnabled, isPluginEnabled } from '@aglyn/aglyn/plugin-manager/enabled-plugins'\nimport {\n pluginRecordFactsReader,\n type ResolvedPluginRecordFactsReader,\n} from '@aglyn/aglyn/plugin-manager/plugin-record-facts'\nimport { resolveOrgIdForHost } from '@aglyn/tenant-data-admin/server/organizations'\nimport { filterEnabledPluginsByReleaseFlags } from '@aglyn/tenant-data-admin/server/release-flags'\nimport {\n AI_CRM_FACTS_RESOURCES,\n AI_CRM_IMPORT_FACTS_RESOURCE,\n AI_CRM_PLUGIN_ID,\n type AiCrmRequest,\n} from '../model/ai-crm'\nimport type { AiJobAdmissionRefusal } from './ai-job-admission'\n\n/**\n * Who may read a CRM record for AI (AGL-2917), as the CRM decides it.\n *\n * Asked twice: by the `crm` kind's admission before a job exists, for the\n * member creating it, and by the answer door before it serves a kept answer,\n * for the member reading it — so a member who lost the record since, or a\n * workspace that switched the CRM off, is not shown what was written from it.\n * Apart from the step so the door reads it without the generator.\n */\n\nexport const AI_CRM_UNAVAILABLE_COPY = 'Turn on the CRM for this site before using AI with it.'\n\n/** How a resource's reader is found; the core's registry by default. */\nexport type AiCrmReaderLookup = (resource: string) => ResolvedPluginRecordFactsReader | null\n\n/** The resource a question's facts are read from, and the record's id there. */\nexport function aiCrmFactsResource(request: AiCrmRequest): { resource: string; id: string } {\n return request.task === 'mapping'\n ? { resource: AI_CRM_IMPORT_FACTS_RESOURCE, id: request.collection }\n : { resource: AI_CRM_FACTS_RESOURCES[request.record.kind], id: request.record.id }\n}\n\nexport interface AiCrmAccessInput {\n firestore: FirebaseFirestore.Firestore\n orgId: string\n hostId: string | null\n resource: string\n id: string\n org: object | null\n /** The member to ask about; absent asks nothing of the reader. */\n uid: string | null | undefined\n /** A verified staff caller, whom the CRM's reader lets read as it lets staff read a record. */\n staff?: boolean\n readerFor?: AiCrmReaderLookup\n now?: Date\n}\n\n/**\n * Whether the CRM would let this member read this record here now; `null`\n * admits them.\n *\n * First what an in-process read of the CRM skips of the plugin API\n * dispatcher, in order: a named site is the org's; the CRM is released for\n * the org, switched on where the read runs, and has registered its reader in\n * this process. Then the CRM's own reader, which applies the member's reach,\n * `data.manage`, the plan and the record's visibility, in the CRM's words.\n */\nexport async function aiCrmAccessRefusal(input: AiCrmAccessInput): Promise<AiJobAdmissionRefusal | null> {\n const org = input.org as { enabledPlugins?: string[] } | null\n let host: Record<string, unknown> | null = null\n if (input.hostId) {\n const owner = await resolveOrgIdForHost(input.hostId)\n if (!owner || owner !== input.orgId) return { status: 404, error: 'Unknown site' }\n host = (await input.firestore.collection('hosts').doc(input.hostId).get()).data() ?? null\n }\n const found = (input.readerFor ?? pluginRecordFactsReader)(input.resource)\n const released = (\n await filterEnabledPluginsByReleaseFlags([AI_CRM_PLUGIN_ID], { orgId: input.orgId, authorization: null })\n ).includes(AI_CRM_PLUGIN_ID)\n const enabled = input.hostId\n ? isHostPluginEnabled(org, host, AI_CRM_PLUGIN_ID)\n : isPluginEnabled(org, AI_CRM_PLUGIN_ID)\n if (!found || found.pluginId !== AI_CRM_PLUGIN_ID || !released || !enabled) {\n return { status: 403, error: AI_CRM_UNAVAILABLE_COPY }\n }\n if (!input.uid) return null\n const read = await found.reader.read({\n orgId: input.orgId,\n hostId: input.hostId,\n id: input.id,\n uid: input.uid,\n ...(input.staff ? { staff: true } : {}),\n org: (input.org as Record<string, unknown> | null) ?? null,\n now: input.now ?? new Date(),\n })\n return read.ok === false ? { status: read.status, error: read.error } : null\n}\n"],"names":["isHostPluginEnabled","isPluginEnabled","pluginRecordFactsReader","resolveOrgIdForHost","filterEnabledPluginsByReleaseFlags","AI_CRM_FACTS_RESOURCES","AI_CRM_IMPORT_FACTS_RESOURCE","AI_CRM_PLUGIN_ID","AI_CRM_UNAVAILABLE_COPY","aiCrmFactsResource","request","task","resource","id","collection","record","kind","aiCrmAccessRefusal","input","org","host","hostId","owner","orgId","status","error","firestore","doc","get","data","found","readerFor","released","authorization","includes","enabled","pluginId","uid","read","reader","staff","now","Date","ok"],"mappings":";AAAA;;;;;;;;;;;;;;;CAeC,GAED,SAASA,mBAAmB,EAAEC,eAAe,QAAQ,8CAA6C;AAClG,SACEC,uBAAuB,QAElB,kDAAiD;AACxD,SAASC,mBAAmB,QAAQ,gDAA+C;AACnF,SAASC,kCAAkC,QAAQ,gDAA+C;AAClG,SACEC,sBAAsB,EACtBC,4BAA4B,EAC5BC,gBAAgB,QAEX,qBAAiB;AAGxB;;;;;;;;CAQC,GAED,OAAO,MAAMC,0BAA0B,yDAAwD;AAK/F,8EAA8E,GAC9E,OAAO,SAASC,mBAAmBC,OAAqB;IACtD,OAAOA,QAAQC,IAAI,KAAK,YACpB;QAAEC,UAAUN;QAA8BO,IAAIH,QAAQI,UAAU;IAAC,IACjE;QAAEF,UAAUP,sBAAsB,CAACK,QAAQK,MAAM,CAACC,IAAI,CAAC;QAAEH,IAAIH,QAAQK,MAAM,CAACF,EAAE;IAAC;AACrF;AAiBA;;;;;;;;;CASC,GACD,OAAO,eAAeI,mBAAmBC,KAAuB;QAQ/CA,kBAiBPA,YACDA;IAzBP,MAAMC,MAAMD,MAAMC,GAAG;IACrB,IAAIC,OAAuC;IAC3C,IAAIF,MAAMG,MAAM,EAAE;YAGT;QAFP,MAAMC,QAAQ,MAAMnB,oBAAoBe,MAAMG,MAAM;QACpD,IAAI,CAACC,SAASA,UAAUJ,MAAMK,KAAK,EAAE,OAAO;YAAEC,QAAQ;YAAKC,OAAO;QAAe;QACjFL,QAAO,QAAA,AAAC,CAAA,MAAMF,MAAMQ,SAAS,CAACZ,UAAU,CAAC,SAASa,GAAG,CAACT,MAAMG,MAAM,EAAEO,GAAG,EAAC,EAAGC,IAAI,cAAxE,QAA8E;IACvF;IACA,MAAMC,QAAQ,EAACZ,mBAAAA,MAAMa,SAAS,YAAfb,mBAAmBhB,yBAAyBgB,MAAMN,QAAQ;IACzE,MAAMoB,WAAW,AACf,CAAA,MAAM5B,mCAAmC;QAACG;KAAiB,EAAE;QAAEgB,OAAOL,MAAMK,KAAK;QAAEU,eAAe;IAAK,EAAC,EACxGC,QAAQ,CAAC3B;IACX,MAAM4B,UAAUjB,MAAMG,MAAM,GACxBrB,oBAAoBmB,KAAKC,MAAMb,oBAC/BN,gBAAgBkB,KAAKZ;IACzB,IAAI,CAACuB,SAASA,MAAMM,QAAQ,KAAK7B,oBAAoB,CAACyB,YAAY,CAACG,SAAS;QAC1E,OAAO;YAAEX,QAAQ;YAAKC,OAAOjB;QAAwB;IACvD;IACA,IAAI,CAACU,MAAMmB,GAAG,EAAE,OAAO;IACvB,MAAMC,OAAO,MAAMR,MAAMS,MAAM,CAACD,IAAI,CAAC;QACnCf,OAAOL,MAAMK,KAAK;QAClBF,QAAQH,MAAMG,MAAM;QACpBR,IAAIK,MAAML,EAAE;QACZwB,KAAKnB,MAAMmB,GAAG;OACVnB,MAAMsB,KAAK,GAAG;QAAEA,OAAO;IAAK,IAAI,CAAC;QACrCrB,GAAG,GAAGD,aAAAA,MAAMC,GAAG,YAATD,aAAgD;QACtDuB,GAAG,GAAEvB,aAAAA,MAAMuB,GAAG,YAATvB,aAAa,IAAIwB;;IAExB,OAAOJ,KAAKK,EAAE,KAAK,QAAQ;QAAEnB,QAAQc,KAAKd,MAAM;QAAEC,OAAOa,KAAKb,KAAK;IAAC,IAAI;AAC1E"}
|
|
@@ -0,0 +1,97 @@
|
|
|
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 CampaignSendTimeSuggestion } from '@aglyn/shared-ui-email-campaigns/model/campaign-send-time';
|
|
18
|
+
/**
|
|
19
|
+
* What an email or campaign job binds and suggests WITHOUT the model
|
|
20
|
+
* (AGL-2912).
|
|
21
|
+
*
|
|
22
|
+
* What AI generation is published to send is the brief, a summary of the
|
|
23
|
+
* site and the content being worked on — not email lists, contacts,
|
|
24
|
+
* recipients, CRM records, product records or engagement statistics. So
|
|
25
|
+
* everything here that touches one of those runs in code, on the server, and
|
|
26
|
+
* hands the model at most a count:
|
|
27
|
+
*
|
|
28
|
+
* - PRODUCTS are bound by id: the ones the member picked for the job, else
|
|
29
|
+
* the ones the brief names by their exact name. The model learns only how
|
|
30
|
+
* many product blocks to place; the ids are set on those blocks after it
|
|
31
|
+
* answers, and the send fills each block's name, price and picture.
|
|
32
|
+
* - THE LIST a campaign is for is suggested when the brief names one of the
|
|
33
|
+
* org's lists by name, and is set on nothing: the drafted email is aimed at
|
|
34
|
+
* nobody until a person chooses.
|
|
35
|
+
* - THE SEND TIME is the shared rule over that list's past sends on this
|
|
36
|
+
* site — when each went out, how many were delivered and how many people
|
|
37
|
+
* opened it — and is said only in the output's note.
|
|
38
|
+
*/
|
|
39
|
+
type Firestore = FirebaseFirestore.Firestore;
|
|
40
|
+
/** The most products one email binds. */
|
|
41
|
+
export declare const AI_EMAIL_MAX_PRODUCTS = 6;
|
|
42
|
+
/** How many of a site's products are read for the names a brief might use. */
|
|
43
|
+
export declare const AI_EMAIL_PRODUCT_SCAN = 200;
|
|
44
|
+
/** How many of an org's lists are read: the composer's list picker window. */
|
|
45
|
+
export declare const AI_CAMPAIGN_LIST_SCAN = 50;
|
|
46
|
+
/** How many of a list's past sends on the site the send time is taken from. */
|
|
47
|
+
export declare const AI_CAMPAIGN_SEND_HISTORY_SCAN = 50;
|
|
48
|
+
/** A record a brief may name, by its id and its name. */
|
|
49
|
+
export interface AiNamedRecord {
|
|
50
|
+
id: string;
|
|
51
|
+
name: string;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* The records a text names by their whole name, in the order it names them.
|
|
55
|
+
* A name must stand as its own words ("Rye loaf" is not named by "rye
|
|
56
|
+
* loaves"), a longer name takes the words it shares with a shorter one ("Rye
|
|
57
|
+
* loaf" over "Rye"), and a name shorter than three characters names nothing.
|
|
58
|
+
*/
|
|
59
|
+
export declare function aiRecordsNamedIn(text: string, records: readonly AiNamedRecord[], max: number): AiNamedRecord[];
|
|
60
|
+
/**
|
|
61
|
+
* The product ids a member picked for the job, as the create door stores a
|
|
62
|
+
* scalar input: one string of ids separated by commas or spaces.
|
|
63
|
+
*/
|
|
64
|
+
export declare function aiEmailPickedProductIds(inputs: Readonly<Record<string, unknown>> | undefined): string[];
|
|
65
|
+
export interface AiEmailProductBinding {
|
|
66
|
+
/** The product ids bound, in the order the email's product blocks take them. */
|
|
67
|
+
ids: string[];
|
|
68
|
+
/** How many the member picked; 0 when the ids came from the brief. */
|
|
69
|
+
picked: number;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* The products an email binds: the member's picks that still exist, else the
|
|
73
|
+
* ones the brief names. Reads ids and names, and returns only ids.
|
|
74
|
+
*/
|
|
75
|
+
export declare function resolveAiEmailProducts(firestore: Firestore, input: {
|
|
76
|
+
hostId: string;
|
|
77
|
+
brief: string;
|
|
78
|
+
inputs: Readonly<Record<string, unknown>> | undefined;
|
|
79
|
+
}): Promise<AiEmailProductBinding>;
|
|
80
|
+
/**
|
|
81
|
+
* The org list a campaign's brief names, found the way the send path finds an
|
|
82
|
+
* org's lists; `null` when it names none.
|
|
83
|
+
*/
|
|
84
|
+
export declare function suggestAiCampaignList(input: {
|
|
85
|
+
hostId: string;
|
|
86
|
+
brief: string;
|
|
87
|
+
}): Promise<AiNamedRecord | null>;
|
|
88
|
+
/** The send time a list's past sends on this site suggest, or `null` with too little history. */
|
|
89
|
+
export declare function readAiListSendTime(firestore: Firestore, input: {
|
|
90
|
+
hostId: string;
|
|
91
|
+
listId: string;
|
|
92
|
+
}): Promise<CampaignSendTimeSuggestion | null>;
|
|
93
|
+
/** What an email's output says about its products; `null` when it binds none and none were picked. */
|
|
94
|
+
export declare function aiEmailProductNote(binding: AiEmailProductBinding): string | null;
|
|
95
|
+
/** What a campaign's output says about who it is for and when to send it. */
|
|
96
|
+
export declare function aiCampaignAudienceNote(list: AiNamedRecord | null, sendTime: CampaignSendTimeSuggestion | null): string;
|
|
97
|
+
export {};
|
|
@@ -0,0 +1,147 @@
|
|
|
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
|
+
*/ import { campaignSendTimeLabel, suggestCampaignSendTime } from "@aglyn/shared-ui-email-campaigns/model/campaign-send-time";
|
|
17
|
+
import { orgDataCollectionForHost } from "@aglyn/tenant-data-admin/server/organizations";
|
|
18
|
+
/** The most products one email binds. */ export const AI_EMAIL_MAX_PRODUCTS = 6;
|
|
19
|
+
/** How many of a site's products are read for the names a brief might use. */ export const AI_EMAIL_PRODUCT_SCAN = 200;
|
|
20
|
+
/** How many of an org's lists are read: the composer's list picker window. */ export const AI_CAMPAIGN_LIST_SCAN = 50;
|
|
21
|
+
/** How many of a list's past sends on the site the send time is taken from. */ export const AI_CAMPAIGN_SEND_HISTORY_SCAN = 50;
|
|
22
|
+
/** Lowercase words joined by single spaces, for matching a name inside text. */ function wordsOf(value) {
|
|
23
|
+
return value.toLowerCase().replace(RegExp("[^\\u0041-\\u005A\\u0061-\\u007A\\u00AA\\u00B5\\u00BA\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02C1\\u02C6-\\u02D1\\u02E0-\\u02E4\\u02EC\\u02EE\\u0370-\\u0374\\u0376-\\u0377\\u037A-\\u037D\\u037F\\u0386\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03F5\\u03F7-\\u0481\\u048A-\\u052F\\u0531-\\u0556\\u0559\\u0560-\\u0588\\u05D0-\\u05EA\\u05EF-\\u05F2\\u0620-\\u064A\\u066E-\\u066F\\u0671-\\u06D3\\u06D5\\u06E5-\\u06E6\\u06EE-\\u06EF\\u06FA-\\u06FC\\u06FF\\u0710\\u0712-\\u072F\\u074D-\\u07A5\\u07B1\\u07CA-\\u07EA\\u07F4-\\u07F5\\u07FA\\u0800-\\u0815\\u081A\\u0824\\u0828\\u0840-\\u0858\\u0860-\\u086A\\u0870-\\u0887\\u0889-\\u088F\\u08A0-\\u08C9\\u0904-\\u0939\\u093D\\u0950\\u0958-\\u0961\\u0971-\\u0980\\u0985-\\u098C\\u098F-\\u0990\\u0993-\\u09A8\\u09AA-\\u09B0\\u09B2\\u09B6-\\u09B9\\u09BD\\u09CE\\u09DC-\\u09DD\\u09DF-\\u09E1\\u09F0-\\u09F1\\u09FC\\u0A05-\\u0A0A\\u0A0F-\\u0A10\\u0A13-\\u0A28\\u0A2A-\\u0A30\\u0A32-\\u0A33\\u0A35-\\u0A36\\u0A38-\\u0A39\\u0A59-\\u0A5C\\u0A5E\\u0A72-\\u0A74\\u0A85-\\u0A8D\\u0A8F-\\u0A91\\u0A93-\\u0AA8\\u0AAA-\\u0AB0\\u0AB2-\\u0AB3\\u0AB5-\\u0AB9\\u0ABD\\u0AD0\\u0AE0-\\u0AE1\\u0AF9\\u0B05-\\u0B0C\\u0B0F-\\u0B10\\u0B13-\\u0B28\\u0B2A-\\u0B30\\u0B32-\\u0B33\\u0B35-\\u0B39\\u0B3D\\u0B5C-\\u0B5D\\u0B5F-\\u0B61\\u0B71\\u0B83\\u0B85-\\u0B8A\\u0B8E-\\u0B90\\u0B92-\\u0B95\\u0B99-\\u0B9A\\u0B9C\\u0B9E-\\u0B9F\\u0BA3-\\u0BA4\\u0BA8-\\u0BAA\\u0BAE-\\u0BB9\\u0BD0\\u0C05-\\u0C0C\\u0C0E-\\u0C10\\u0C12-\\u0C28\\u0C2A-\\u0C39\\u0C3D\\u0C58-\\u0C5A\\u0C5C-\\u0C5D\\u0C60-\\u0C61\\u0C80\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CBD\\u0CDC-\\u0CDE\\u0CE0-\\u0CE1\\u0CF1-\\u0CF2\\u0D04-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D3A\\u0D3D\\u0D4E\\u0D54-\\u0D56\\u0D5F-\\u0D61\\u0D7A-\\u0D7F\\u0D85-\\u0D96\\u0D9A-\\u0DB1\\u0DB3-\\u0DBB\\u0DBD\\u0DC0-\\u0DC6\\u0E01-\\u0E30\\u0E32-\\u0E33\\u0E40-\\u0E46\\u0E81-\\u0E82\\u0E84\\u0E86-\\u0E8A\\u0E8C-\\u0EA3\\u0EA5\\u0EA7-\\u0EB0\\u0EB2-\\u0EB3\\u0EBD\\u0EC0-\\u0EC4\\u0EC6\\u0EDC-\\u0EDF\\u0F00\\u0F40-\\u0F47\\u0F49-\\u0F6C\\u0F88-\\u0F8C\\u1000-\\u102A\\u103F\\u1050-\\u1055\\u105A-\\u105D\\u1061\\u1065-\\u1066\\u106E-\\u1070\\u1075-\\u1081\\u108E\\u10A0-\\u10C5\\u10C7\\u10CD\\u10D0-\\u10FA\\u10FC-\\u1248\\u124A-\\u124D\\u1250-\\u1256\\u1258\\u125A-\\u125D\\u1260-\\u1288\\u128A-\\u128D\\u1290-\\u12B0\\u12B2-\\u12B5\\u12B8-\\u12BE\\u12C0\\u12C2-\\u12C5\\u12C8-\\u12D6\\u12D8-\\u1310\\u1312-\\u1315\\u1318-\\u135A\\u1380-\\u138F\\u13A0-\\u13F5\\u13F8-\\u13FD\\u1401-\\u166C\\u166F-\\u167F\\u1681-\\u169A\\u16A0-\\u16EA\\u16F1-\\u16F8\\u1700-\\u1711\\u171F-\\u1731\\u1740-\\u1751\\u1760-\\u176C\\u176E-\\u1770\\u1780-\\u17B3\\u17D7\\u17DC\\u1820-\\u1878\\u1880-\\u1884\\u1887-\\u18A8\\u18AA\\u18B0-\\u18F5\\u1900-\\u191E\\u1950-\\u196D\\u1970-\\u1974\\u1980-\\u19AB\\u19B0-\\u19C9\\u1A00-\\u1A16\\u1A20-\\u1A54\\u1AA7\\u1B05-\\u1B33\\u1B45-\\u1B4C\\u1B83-\\u1BA0\\u1BAE-\\u1BAF\\u1BBA-\\u1BE5\\u1C00-\\u1C23\\u1C4D-\\u1C4F\\u1C5A-\\u1C7D\\u1C80-\\u1C8A\\u1C90-\\u1CBA\\u1CBD-\\u1CBF\\u1CE9-\\u1CEC\\u1CEE-\\u1CF3\\u1CF5-\\u1CF6\\u1CFA\\u1D00-\\u1DBF\\u1E00-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45\\u1F48-\\u1F4D\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F7D\\u1F80-\\u1FB4\\u1FB6-\\u1FBC\\u1FBE\\u1FC2-\\u1FC4\\u1FC6-\\u1FCC\\u1FD0-\\u1FD3\\u1FD6-\\u1FDB\\u1FE0-\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FFC\\u2071\\u207F\\u2090-\\u209C\\u2102\\u2107\\u210A-\\u2113\\u2115\\u2119-\\u211D\\u2124\\u2126\\u2128\\u212A-\\u212D\\u212F-\\u2139\\u213C-\\u213F\\u2145-\\u2149\\u214E\\u2183-\\u2184\\u2C00-\\u2CE4\\u2CEB-\\u2CEE\\u2CF2-\\u2CF3\\u2D00-\\u2D25\\u2D27\\u2D2D\\u2D30-\\u2D67\\u2D6F\\u2D80-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u2E2F\\u3005-\\u3006\\u3031-\\u3035\\u303B-\\u303C\\u3041-\\u3096\\u309D-\\u309F\\u30A1-\\u30FA\\u30FC-\\u30FF\\u3105-\\u312F\\u3131-\\u318E\\u31A0-\\u31BF\\u31F0-\\u31FF\\u3400-\\u4DBF\\u4E00-\\uA48C\\uA4D0-\\uA4FD\\uA500-\\uA60C\\uA610-\\uA61F\\uA62A-\\uA62B\\uA640-\\uA66E\\uA67F-\\uA69D\\uA6A0-\\uA6E5\\uA717-\\uA71F\\uA722-\\uA788\\uA78B-\\uA7DC\\uA7F1-\\uA801\\uA803-\\uA805\\uA807-\\uA80A\\uA80C-\\uA822\\uA840-\\uA873\\uA882-\\uA8B3\\uA8F2-\\uA8F7\\uA8FB\\uA8FD-\\uA8FE\\uA90A-\\uA925\\uA930-\\uA946\\uA960-\\uA97C\\uA984-\\uA9B2\\uA9CF\\uA9E0-\\uA9E4\\uA9E6-\\uA9EF\\uA9FA-\\uA9FE\\uAA00-\\uAA28\\uAA40-\\uAA42\\uAA44-\\uAA4B\\uAA60-\\uAA76\\uAA7A\\uAA7E-\\uAAAF\\uAAB1\\uAAB5-\\uAAB6\\uAAB9-\\uAABD\\uAAC0\\uAAC2\\uAADB-\\uAADD\\uAAE0-\\uAAEA\\uAAF2-\\uAAF4\\uAB01-\\uAB06\\uAB09-\\uAB0E\\uAB11-\\uAB16\\uAB20-\\uAB26\\uAB28-\\uAB2E\\uAB30-\\uAB5A\\uAB5C-\\uAB69\\uAB70-\\uABE2\\uAC00-\\uD7A3\\uD7B0-\\uD7C6\\uD7CB-\\uD7FB\\uF900-\\uFA6D\\uFA70-\\uFAD9\\uFB00-\\uFB06\\uFB13-\\uFB17\\uFB1D\\uFB1F-\\uFB28\\uFB2A-\\uFB36\\uFB38-\\uFB3C\\uFB3E\\uFB40-\\uFB41\\uFB43-\\uFB44\\uFB46-\\uFBB1\\uFBD3-\\uFD3D\\uFD50-\\uFD8F\\uFD92-\\uFDC7\\uFDF0-\\uFDFB\\uFE70-\\uFE74\\uFE76-\\uFEFC\\uFF21-\\uFF3A\\uFF41-\\uFF5A\\uFF66-\\uFFBE\\uFFC2-\\uFFC7\\uFFCA-\\uFFCF\\uFFD2-\\uFFD7\\uFFDA-\\uFFDC\\u{10000}-\\u{1000B}\\u{1000D}-\\u{10026}\\u{10028}-\\u{1003A}\\u{1003C}-\\u{1003D}\\u{1003F}-\\u{1004D}\\u{10050}-\\u{1005D}\\u{10080}-\\u{100FA}\\u{10280}-\\u{1029C}\\u{102A0}-\\u{102D0}\\u{10300}-\\u{1031F}\\u{1032D}-\\u{10340}\\u{10342}-\\u{10349}\\u{10350}-\\u{10375}\\u{10380}-\\u{1039D}\\u{103A0}-\\u{103C3}\\u{103C8}-\\u{103CF}\\u{10400}-\\u{1049D}\\u{104B0}-\\u{104D3}\\u{104D8}-\\u{104FB}\\u{10500}-\\u{10527}\\u{10530}-\\u{10563}\\u{10570}-\\u{1057A}\\u{1057C}-\\u{1058A}\\u{1058C}-\\u{10592}\\u{10594}-\\u{10595}\\u{10597}-\\u{105A1}\\u{105A3}-\\u{105B1}\\u{105B3}-\\u{105B9}\\u{105BB}-\\u{105BC}\\u{105C0}-\\u{105F3}\\u{10600}-\\u{10736}\\u{10740}-\\u{10755}\\u{10760}-\\u{10767}\\u{10780}-\\u{10785}\\u{10787}-\\u{107B0}\\u{107B2}-\\u{107BA}\\u{10800}-\\u{10805}\\u{10808}\\u{1080A}-\\u{10835}\\u{10837}-\\u{10838}\\u{1083C}\\u{1083F}-\\u{10855}\\u{10860}-\\u{10876}\\u{10880}-\\u{1089E}\\u{108E0}-\\u{108F2}\\u{108F4}-\\u{108F5}\\u{10900}-\\u{10915}\\u{10920}-\\u{10939}\\u{10940}-\\u{10959}\\u{10980}-\\u{109B7}\\u{109BE}-\\u{109BF}\\u{10A00}\\u{10A10}-\\u{10A13}\\u{10A15}-\\u{10A17}\\u{10A19}-\\u{10A35}\\u{10A60}-\\u{10A7C}\\u{10A80}-\\u{10A9C}\\u{10AC0}-\\u{10AC7}\\u{10AC9}-\\u{10AE4}\\u{10B00}-\\u{10B35}\\u{10B40}-\\u{10B55}\\u{10B60}-\\u{10B72}\\u{10B80}-\\u{10B91}\\u{10C00}-\\u{10C48}\\u{10C80}-\\u{10CB2}\\u{10CC0}-\\u{10CF2}\\u{10D00}-\\u{10D23}\\u{10D4A}-\\u{10D65}\\u{10D6F}-\\u{10D85}\\u{10E80}-\\u{10EA9}\\u{10EB0}-\\u{10EB1}\\u{10EC2}-\\u{10EC7}\\u{10F00}-\\u{10F1C}\\u{10F27}\\u{10F30}-\\u{10F45}\\u{10F70}-\\u{10F81}\\u{10FB0}-\\u{10FC4}\\u{10FE0}-\\u{10FF6}\\u{11003}-\\u{11037}\\u{11071}-\\u{11072}\\u{11075}\\u{11083}-\\u{110AF}\\u{110D0}-\\u{110E8}\\u{11103}-\\u{11126}\\u{11144}\\u{11147}\\u{11150}-\\u{11172}\\u{11176}\\u{11183}-\\u{111B2}\\u{111C1}-\\u{111C4}\\u{111DA}\\u{111DC}\\u{11200}-\\u{11211}\\u{11213}-\\u{1122B}\\u{1123F}-\\u{11240}\\u{11280}-\\u{11286}\\u{11288}\\u{1128A}-\\u{1128D}\\u{1128F}-\\u{1129D}\\u{1129F}-\\u{112A8}\\u{112B0}-\\u{112DE}\\u{11305}-\\u{1130C}\\u{1130F}-\\u{11310}\\u{11313}-\\u{11328}\\u{1132A}-\\u{11330}\\u{11332}-\\u{11333}\\u{11335}-\\u{11339}\\u{1133D}\\u{11350}\\u{1135D}-\\u{11361}\\u{11380}-\\u{11389}\\u{1138B}\\u{1138E}\\u{11390}-\\u{113B5}\\u{113B7}\\u{113D1}\\u{113D3}\\u{11400}-\\u{11434}\\u{11447}-\\u{1144A}\\u{1145F}-\\u{11461}\\u{11480}-\\u{114AF}\\u{114C4}-\\u{114C5}\\u{114C7}\\u{11580}-\\u{115AE}\\u{115D8}-\\u{115DB}\\u{11600}-\\u{1162F}\\u{11644}\\u{11680}-\\u{116AA}\\u{116B8}\\u{11700}-\\u{1171A}\\u{11740}-\\u{11746}\\u{11800}-\\u{1182B}\\u{118A0}-\\u{118DF}\\u{118FF}-\\u{11906}\\u{11909}\\u{1190C}-\\u{11913}\\u{11915}-\\u{11916}\\u{11918}-\\u{1192F}\\u{1193F}\\u{11941}\\u{119A0}-\\u{119A7}\\u{119AA}-\\u{119D0}\\u{119E1}\\u{119E3}\\u{11A00}\\u{11A0B}-\\u{11A32}\\u{11A3A}\\u{11A50}\\u{11A5C}-\\u{11A89}\\u{11A9D}\\u{11AB0}-\\u{11AF8}\\u{11BC0}-\\u{11BE0}\\u{11C00}-\\u{11C08}\\u{11C0A}-\\u{11C2E}\\u{11C40}\\u{11C72}-\\u{11C8F}\\u{11D00}-\\u{11D06}\\u{11D08}-\\u{11D09}\\u{11D0B}-\\u{11D30}\\u{11D46}\\u{11D60}-\\u{11D65}\\u{11D67}-\\u{11D68}\\u{11D6A}-\\u{11D89}\\u{11D98}\\u{11DB0}-\\u{11DDB}\\u{11EE0}-\\u{11EF2}\\u{11F02}\\u{11F04}-\\u{11F10}\\u{11F12}-\\u{11F33}\\u{11FB0}\\u{12000}-\\u{12399}\\u{12480}-\\u{12543}\\u{12F90}-\\u{12FF0}\\u{13000}-\\u{1342F}\\u{13441}-\\u{13446}\\u{13460}-\\u{143FA}\\u{14400}-\\u{14646}\\u{16100}-\\u{1611D}\\u{16800}-\\u{16A38}\\u{16A40}-\\u{16A5E}\\u{16A70}-\\u{16ABE}\\u{16AD0}-\\u{16AED}\\u{16B00}-\\u{16B2F}\\u{16B40}-\\u{16B43}\\u{16B63}-\\u{16B77}\\u{16B7D}-\\u{16B8F}\\u{16D40}-\\u{16D6C}\\u{16E40}-\\u{16E7F}\\u{16EA0}-\\u{16EB8}\\u{16EBB}-\\u{16ED3}\\u{16F00}-\\u{16F4A}\\u{16F50}\\u{16F93}-\\u{16F9F}\\u{16FE0}-\\u{16FE1}\\u{16FE3}\\u{16FF2}-\\u{16FF3}\\u{17000}-\\u{18CD5}\\u{18CFF}-\\u{18D1E}\\u{18D80}-\\u{18DF2}\\u{1AFF0}-\\u{1AFF3}\\u{1AFF5}-\\u{1AFFB}\\u{1AFFD}-\\u{1AFFE}\\u{1B000}-\\u{1B122}\\u{1B132}\\u{1B150}-\\u{1B152}\\u{1B155}\\u{1B164}-\\u{1B167}\\u{1B170}-\\u{1B2FB}\\u{1BC00}-\\u{1BC6A}\\u{1BC70}-\\u{1BC7C}\\u{1BC80}-\\u{1BC88}\\u{1BC90}-\\u{1BC99}\\u{1D400}-\\u{1D454}\\u{1D456}-\\u{1D49C}\\u{1D49E}-\\u{1D49F}\\u{1D4A2}\\u{1D4A5}-\\u{1D4A6}\\u{1D4A9}-\\u{1D4AC}\\u{1D4AE}-\\u{1D4B9}\\u{1D4BB}\\u{1D4BD}-\\u{1D4C3}\\u{1D4C5}-\\u{1D505}\\u{1D507}-\\u{1D50A}\\u{1D50D}-\\u{1D514}\\u{1D516}-\\u{1D51C}\\u{1D51E}-\\u{1D539}\\u{1D53B}-\\u{1D53E}\\u{1D540}-\\u{1D544}\\u{1D546}\\u{1D54A}-\\u{1D550}\\u{1D552}-\\u{1D6A5}\\u{1D6A8}-\\u{1D6C0}\\u{1D6C2}-\\u{1D6DA}\\u{1D6DC}-\\u{1D6FA}\\u{1D6FC}-\\u{1D714}\\u{1D716}-\\u{1D734}\\u{1D736}-\\u{1D74E}\\u{1D750}-\\u{1D76E}\\u{1D770}-\\u{1D788}\\u{1D78A}-\\u{1D7A8}\\u{1D7AA}-\\u{1D7C2}\\u{1D7C4}-\\u{1D7CB}\\u{1DF00}-\\u{1DF1E}\\u{1DF25}-\\u{1DF2A}\\u{1E030}-\\u{1E06D}\\u{1E100}-\\u{1E12C}\\u{1E137}-\\u{1E13D}\\u{1E14E}\\u{1E290}-\\u{1E2AD}\\u{1E2C0}-\\u{1E2EB}\\u{1E4D0}-\\u{1E4EB}\\u{1E5D0}-\\u{1E5ED}\\u{1E5F0}\\u{1E6C0}-\\u{1E6DE}\\u{1E6E0}-\\u{1E6E2}\\u{1E6E4}-\\u{1E6E5}\\u{1E6E7}-\\u{1E6ED}\\u{1E6F0}-\\u{1E6F4}\\u{1E6FE}-\\u{1E6FF}\\u{1E7E0}-\\u{1E7E6}\\u{1E7E8}-\\u{1E7EB}\\u{1E7ED}-\\u{1E7EE}\\u{1E7F0}-\\u{1E7FE}\\u{1E800}-\\u{1E8C4}\\u{1E900}-\\u{1E943}\\u{1E94B}\\u{1EE00}-\\u{1EE03}\\u{1EE05}-\\u{1EE1F}\\u{1EE21}-\\u{1EE22}\\u{1EE24}\\u{1EE27}\\u{1EE29}-\\u{1EE32}\\u{1EE34}-\\u{1EE37}\\u{1EE39}\\u{1EE3B}\\u{1EE42}\\u{1EE47}\\u{1EE49}\\u{1EE4B}\\u{1EE4D}-\\u{1EE4F}\\u{1EE51}-\\u{1EE52}\\u{1EE54}\\u{1EE57}\\u{1EE59}\\u{1EE5B}\\u{1EE5D}\\u{1EE5F}\\u{1EE61}-\\u{1EE62}\\u{1EE64}\\u{1EE67}-\\u{1EE6A}\\u{1EE6C}-\\u{1EE72}\\u{1EE74}-\\u{1EE77}\\u{1EE79}-\\u{1EE7C}\\u{1EE7E}\\u{1EE80}-\\u{1EE89}\\u{1EE8B}-\\u{1EE9B}\\u{1EEA1}-\\u{1EEA3}\\u{1EEA5}-\\u{1EEA9}\\u{1EEAB}-\\u{1EEBB}\\u{20000}-\\u{2A6DF}\\u{2A700}-\\u{2B81D}\\u{2B820}-\\u{2CEAD}\\u{2CEB0}-\\u{2EBE0}\\u{2EBF0}-\\u{2EE5D}\\u{2F800}-\\u{2FA1D}\\u{30000}-\\u{3134A}\\u{31350}-\\u{33479}\\u0030-\\u0039\\u00B2-\\u00B3\\u00B9\\u00BC-\\u00BE\\u0660-\\u0669\\u06F0-\\u06F9\\u07C0-\\u07C9\\u0966-\\u096F\\u09E6-\\u09EF\\u09F4-\\u09F9\\u0A66-\\u0A6F\\u0AE6-\\u0AEF\\u0B66-\\u0B6F\\u0B72-\\u0B77\\u0BE6-\\u0BF2\\u0C66-\\u0C6F\\u0C78-\\u0C7E\\u0CE6-\\u0CEF\\u0D58-\\u0D5E\\u0D66-\\u0D78\\u0DE6-\\u0DEF\\u0E50-\\u0E59\\u0ED0-\\u0ED9\\u0F20-\\u0F33\\u1040-\\u1049\\u1090-\\u1099\\u1369-\\u137C\\u16EE-\\u16F0\\u17E0-\\u17E9\\u17F0-\\u17F9\\u1810-\\u1819\\u1946-\\u194F\\u19D0-\\u19DA\\u1A80-\\u1A89\\u1A90-\\u1A99\\u1B50-\\u1B59\\u1BB0-\\u1BB9\\u1C40-\\u1C49\\u1C50-\\u1C59\\u2070\\u2074-\\u2079\\u2080-\\u2089\\u2150-\\u2182\\u2185-\\u2189\\u2460-\\u249B\\u24EA-\\u24FF\\u2776-\\u2793\\u2CFD\\u3007\\u3021-\\u3029\\u3038-\\u303A\\u3192-\\u3195\\u3220-\\u3229\\u3248-\\u324F\\u3251-\\u325F\\u3280-\\u3289\\u32B1-\\u32BF\\uA620-\\uA629\\uA6E6-\\uA6EF\\uA830-\\uA835\\uA8D0-\\uA8D9\\uA900-\\uA909\\uA9D0-\\uA9D9\\uA9F0-\\uA9F9\\uAA50-\\uAA59\\uABF0-\\uABF9\\uFF10-\\uFF19\\u{10107}-\\u{10133}\\u{10140}-\\u{10178}\\u{1018A}-\\u{1018B}\\u{102E1}-\\u{102FB}\\u{10320}-\\u{10323}\\u{10341}\\u{1034A}\\u{103D1}-\\u{103D5}\\u{104A0}-\\u{104A9}\\u{10858}-\\u{1085F}\\u{10879}-\\u{1087F}\\u{108A7}-\\u{108AF}\\u{108FB}-\\u{108FF}\\u{10916}-\\u{1091B}\\u{109BC}-\\u{109BD}\\u{109C0}-\\u{109CF}\\u{109D2}-\\u{109FF}\\u{10A40}-\\u{10A48}\\u{10A7D}-\\u{10A7E}\\u{10A9D}-\\u{10A9F}\\u{10AEB}-\\u{10AEF}\\u{10B58}-\\u{10B5F}\\u{10B78}-\\u{10B7F}\\u{10BA9}-\\u{10BAF}\\u{10CFA}-\\u{10CFF}\\u{10D30}-\\u{10D39}\\u{10D40}-\\u{10D49}\\u{10E60}-\\u{10E7E}\\u{10F1D}-\\u{10F26}\\u{10F51}-\\u{10F54}\\u{10FC5}-\\u{10FCB}\\u{11052}-\\u{1106F}\\u{110F0}-\\u{110F9}\\u{11136}-\\u{1113F}\\u{111D0}-\\u{111D9}\\u{111E1}-\\u{111F4}\\u{112F0}-\\u{112F9}\\u{11450}-\\u{11459}\\u{114D0}-\\u{114D9}\\u{11650}-\\u{11659}\\u{116C0}-\\u{116C9}\\u{116D0}-\\u{116E3}\\u{11730}-\\u{1173B}\\u{118E0}-\\u{118F2}\\u{11950}-\\u{11959}\\u{11BF0}-\\u{11BF9}\\u{11C50}-\\u{11C6C}\\u{11D50}-\\u{11D59}\\u{11DA0}-\\u{11DA9}\\u{11DE0}-\\u{11DE9}\\u{11F50}-\\u{11F59}\\u{11FC0}-\\u{11FD4}\\u{12400}-\\u{1246E}\\u{16130}-\\u{16139}\\u{16A60}-\\u{16A69}\\u{16AC0}-\\u{16AC9}\\u{16B50}-\\u{16B59}\\u{16B5B}-\\u{16B61}\\u{16D70}-\\u{16D79}\\u{16E80}-\\u{16E96}\\u{16FF4}-\\u{16FF6}\\u{1CCF0}-\\u{1CCF9}\\u{1D2C0}-\\u{1D2D3}\\u{1D2E0}-\\u{1D2F3}\\u{1D360}-\\u{1D378}\\u{1D7CE}-\\u{1D7FF}\\u{1E140}-\\u{1E149}\\u{1E2F0}-\\u{1E2F9}\\u{1E4F0}-\\u{1E4F9}\\u{1E5F1}-\\u{1E5FA}\\u{1E8C7}-\\u{1E8CF}\\u{1E950}-\\u{1E959}\\u{1EC71}-\\u{1ECAB}\\u{1ECAD}-\\u{1ECAF}\\u{1ECB1}-\\u{1ECB4}\\u{1ED01}-\\u{1ED2D}\\u{1ED2F}-\\u{1ED3D}\\u{1F100}-\\u{1F10C}\\u{1FBF0}-\\u{1FBF9}]+", "gu"), ' ').trim();
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* The records a text names by their whole name, in the order it names them.
|
|
27
|
+
* A name must stand as its own words ("Rye loaf" is not named by "rye
|
|
28
|
+
* loaves"), a longer name takes the words it shares with a shorter one ("Rye
|
|
29
|
+
* loaf" over "Rye"), and a name shorter than three characters names nothing.
|
|
30
|
+
*/ export function aiRecordsNamedIn(text, records, max) {
|
|
31
|
+
const haystack = ` ${wordsOf(text)} `;
|
|
32
|
+
const hits = [];
|
|
33
|
+
for (const record of records){
|
|
34
|
+
const needle = wordsOf(record.name);
|
|
35
|
+
if (needle.length < 3) continue;
|
|
36
|
+
const at = haystack.indexOf(` ${needle} `);
|
|
37
|
+
if (at !== -1) hits.push({
|
|
38
|
+
record,
|
|
39
|
+
at,
|
|
40
|
+
end: at + needle.length + 1
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
const kept = [];
|
|
44
|
+
for (const hit of [
|
|
45
|
+
...hits
|
|
46
|
+
].sort((a, b)=>b.end - b.at - (a.end - a.at))){
|
|
47
|
+
if (kept.some((other)=>hit.at < other.end && hit.end > other.at)) continue;
|
|
48
|
+
kept.push(hit);
|
|
49
|
+
}
|
|
50
|
+
return kept.sort((a, b)=>a.at - b.at).map((hit)=>hit.record).slice(0, Math.max(0, max));
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* The product ids a member picked for the job, as the create door stores a
|
|
54
|
+
* scalar input: one string of ids separated by commas or spaces.
|
|
55
|
+
*/ export function aiEmailPickedProductIds(inputs) {
|
|
56
|
+
const raw = inputs == null ? void 0 : inputs['productIds'];
|
|
57
|
+
if (typeof raw !== 'string') return [];
|
|
58
|
+
const ids = raw.split(/[\s,]+/).filter((id)=>/^[A-Za-z0-9_-]{1,128}$/.test(id));
|
|
59
|
+
return [
|
|
60
|
+
...new Set(ids)
|
|
61
|
+
].slice(0, AI_EMAIL_MAX_PRODUCTS);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* The products an email binds: the member's picks that still exist, else the
|
|
65
|
+
* ones the brief names. Reads ids and names, and returns only ids.
|
|
66
|
+
*/ export async function resolveAiEmailProducts(firestore, input) {
|
|
67
|
+
const products = firestore.collection('hosts').doc(input.hostId).collection('products');
|
|
68
|
+
const picked = aiEmailPickedProductIds(input.inputs);
|
|
69
|
+
if (picked.length) {
|
|
70
|
+
const snapshots = await Promise.all(picked.map((id)=>products.doc(id).get()));
|
|
71
|
+
return {
|
|
72
|
+
ids: snapshots.filter((snapshot)=>snapshot.exists && snapshot.get('deletedAt') == null).map((snapshot)=>snapshot.id),
|
|
73
|
+
picked: picked.length
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
const snapshot = await products.select('name', 'deletedAt').limit(AI_EMAIL_PRODUCT_SCAN).get();
|
|
77
|
+
const rows = snapshot.docs.filter((doc)=>doc.get('deletedAt') == null).map((doc)=>{
|
|
78
|
+
var _doc_get;
|
|
79
|
+
return {
|
|
80
|
+
id: doc.id,
|
|
81
|
+
name: String((_doc_get = doc.get('name')) != null ? _doc_get : '')
|
|
82
|
+
};
|
|
83
|
+
});
|
|
84
|
+
return {
|
|
85
|
+
ids: aiRecordsNamedIn(input.brief, rows, AI_EMAIL_MAX_PRODUCTS).map((row)=>row.id),
|
|
86
|
+
picked: 0
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* The org list a campaign's brief names, found the way the send path finds an
|
|
91
|
+
* org's lists; `null` when it names none.
|
|
92
|
+
*/ export async function suggestAiCampaignList(input) {
|
|
93
|
+
var _aiRecordsNamedIn_;
|
|
94
|
+
var _contacts_parent;
|
|
95
|
+
const contacts = await orgDataCollectionForHost(input.hostId, 'contacts');
|
|
96
|
+
const lists = (_contacts_parent = contacts.parent) == null ? void 0 : _contacts_parent.collection('lists');
|
|
97
|
+
if (!lists) return null;
|
|
98
|
+
const snapshot = await lists.select('name').limit(AI_CAMPAIGN_LIST_SCAN).get();
|
|
99
|
+
const rows = snapshot.docs.map((doc)=>{
|
|
100
|
+
var _doc_get;
|
|
101
|
+
return {
|
|
102
|
+
id: doc.id,
|
|
103
|
+
name: String((_doc_get = doc.get('name')) != null ? _doc_get : '')
|
|
104
|
+
};
|
|
105
|
+
});
|
|
106
|
+
return (_aiRecordsNamedIn_ = aiRecordsNamedIn(input.brief, rows, 1)[0]) != null ? _aiRecordsNamedIn_ : null;
|
|
107
|
+
}
|
|
108
|
+
function millisOf(value) {
|
|
109
|
+
if (value instanceof Date) return value.getTime();
|
|
110
|
+
if (typeof value === 'number') return value;
|
|
111
|
+
const toMillis = value == null ? void 0 : value.toMillis;
|
|
112
|
+
return typeof toMillis === 'function' ? toMillis.call(value) : 0;
|
|
113
|
+
}
|
|
114
|
+
/** The send time a list's past sends on this site suggest, or `null` with too little history. */ export async function readAiListSendTime(firestore, input) {
|
|
115
|
+
const snapshot = await firestore.collection('hosts').doc(input.hostId).collection('campaigns').where('listId', '==', input.listId).where('status', '==', 'sent').select('sentAt', 'stats.delivered', 'stats.uniqueOpens').limit(AI_CAMPAIGN_SEND_HISTORY_SCAN).get();
|
|
116
|
+
return suggestCampaignSendTime(snapshot.docs.map((doc)=>{
|
|
117
|
+
var _doc_get, _doc_get1;
|
|
118
|
+
return {
|
|
119
|
+
sentAtMs: millisOf(doc.get('sentAt')),
|
|
120
|
+
delivered: Number((_doc_get = doc.get('stats.delivered')) != null ? _doc_get : 0),
|
|
121
|
+
uniqueOpens: Number((_doc_get1 = doc.get('stats.uniqueOpens')) != null ? _doc_get1 : 0)
|
|
122
|
+
};
|
|
123
|
+
}));
|
|
124
|
+
}
|
|
125
|
+
/** What an email's output says about its products; `null` when it binds none and none were picked. */ export function aiEmailProductNote(binding) {
|
|
126
|
+
const bound = binding.ids.length;
|
|
127
|
+
const missing = binding.picked - bound;
|
|
128
|
+
const parts = [];
|
|
129
|
+
if (bound === 1) {
|
|
130
|
+
parts.push('Its product card shows the product’s current name, price and picture when it is sent.');
|
|
131
|
+
} else if (bound > 1) {
|
|
132
|
+
parts.push(`Its ${bound} product cards show each product’s current name, price and picture when it is sent.`);
|
|
133
|
+
}
|
|
134
|
+
if (missing > 0) {
|
|
135
|
+
parts.push(`${missing} of the products picked no longer ${missing === 1 ? 'exists' : 'exist'}, so the email places ${bound || 'none'}.`);
|
|
136
|
+
}
|
|
137
|
+
return parts.length ? parts.join(' ') : null;
|
|
138
|
+
}
|
|
139
|
+
/** What a campaign's output says about who it is for and when to send it. */ export function aiCampaignAudienceNote(list, sendTime) {
|
|
140
|
+
if (!list) {
|
|
141
|
+
return 'The email is aimed at nobody yet: choose who receives it before you schedule it.';
|
|
142
|
+
}
|
|
143
|
+
const when = sendTime ? ` Past campaigns to that list on this site were opened most when sent on ${campaignSendTimeLabel(sendTime)}, across ${sendTime.measured} sends.` : ' That list has too little send history on this site to suggest a send time.';
|
|
144
|
+
return `The brief names the list "${list.name}". The email is aimed at nobody yet: choose "${list.name}" as its audience before you schedule it.${when}`;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
//# sourceMappingURL=ai-email-bindings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/jobs/ai-email-bindings.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n campaignSendTimeLabel,\n suggestCampaignSendTime,\n type CampaignSendTimeSuggestion,\n} from '@aglyn/shared-ui-email-campaigns/model/campaign-send-time'\nimport { orgDataCollectionForHost } from '@aglyn/tenant-data-admin/server/organizations'\n\n/**\n * What an email or campaign job binds and suggests WITHOUT the model\n * (AGL-2912).\n *\n * What AI generation is published to send is the brief, a summary of the\n * site and the content being worked on — not email lists, contacts,\n * recipients, CRM records, product records or engagement statistics. So\n * everything here that touches one of those runs in code, on the server, and\n * hands the model at most a count:\n *\n * - PRODUCTS are bound by id: the ones the member picked for the job, else\n * the ones the brief names by their exact name. The model learns only how\n * many product blocks to place; the ids are set on those blocks after it\n * answers, and the send fills each block's name, price and picture.\n * - THE LIST a campaign is for is suggested when the brief names one of the\n * org's lists by name, and is set on nothing: the drafted email is aimed at\n * nobody until a person chooses.\n * - THE SEND TIME is the shared rule over that list's past sends on this\n * site — when each went out, how many were delivered and how many people\n * opened it — and is said only in the output's note.\n */\n\ntype Firestore = FirebaseFirestore.Firestore\n\n/** The most products one email binds. */\nexport const AI_EMAIL_MAX_PRODUCTS = 6\n\n/** How many of a site's products are read for the names a brief might use. */\nexport const AI_EMAIL_PRODUCT_SCAN = 200\n\n/** How many of an org's lists are read: the composer's list picker window. */\nexport const AI_CAMPAIGN_LIST_SCAN = 50\n\n/** How many of a list's past sends on the site the send time is taken from. */\nexport const AI_CAMPAIGN_SEND_HISTORY_SCAN = 50\n\n/** A record a brief may name, by its id and its name. */\nexport interface AiNamedRecord {\n id: string\n name: string\n}\n\n/** Lowercase words joined by single spaces, for matching a name inside text. */\nfunction wordsOf(value: string): string {\n return value\n .toLowerCase()\n .replace(/[^\\p{L}\\p{N}]+/gu, ' ')\n .trim()\n}\n\n/**\n * The records a text names by their whole name, in the order it names them.\n * A name must stand as its own words (\"Rye loaf\" is not named by \"rye\n * loaves\"), a longer name takes the words it shares with a shorter one (\"Rye\n * loaf\" over \"Rye\"), and a name shorter than three characters names nothing.\n */\nexport function aiRecordsNamedIn(\n text: string,\n records: readonly AiNamedRecord[],\n max: number,\n): AiNamedRecord[] {\n const haystack = ` ${wordsOf(text)} `\n const hits: Array<{ record: AiNamedRecord; at: number; end: number }> = []\n for (const record of records) {\n const needle = wordsOf(record.name)\n if (needle.length < 3) continue\n const at = haystack.indexOf(` ${needle} `)\n if (at !== -1) hits.push({ record, at, end: at + needle.length + 1 })\n }\n const kept: typeof hits = []\n for (const hit of [...hits].sort((a, b) => b.end - b.at - (a.end - a.at))) {\n if (kept.some((other) => hit.at < other.end && hit.end > other.at)) continue\n kept.push(hit)\n }\n return kept\n .sort((a, b) => a.at - b.at)\n .map((hit) => hit.record)\n .slice(0, Math.max(0, max))\n}\n\n/**\n * The product ids a member picked for the job, as the create door stores a\n * scalar input: one string of ids separated by commas or spaces.\n */\nexport function aiEmailPickedProductIds(inputs: Readonly<Record<string, unknown>> | undefined): string[] {\n const raw = inputs?.['productIds']\n if (typeof raw !== 'string') return []\n const ids = raw.split(/[\\s,]+/).filter((id) => /^[A-Za-z0-9_-]{1,128}$/.test(id))\n return [...new Set(ids)].slice(0, AI_EMAIL_MAX_PRODUCTS)\n}\n\nexport interface AiEmailProductBinding {\n /** The product ids bound, in the order the email's product blocks take them. */\n ids: string[]\n /** How many the member picked; 0 when the ids came from the brief. */\n picked: number\n}\n\n/**\n * The products an email binds: the member's picks that still exist, else the\n * ones the brief names. Reads ids and names, and returns only ids.\n */\nexport async function resolveAiEmailProducts(\n firestore: Firestore,\n input: { hostId: string; brief: string; inputs: Readonly<Record<string, unknown>> | undefined },\n): Promise<AiEmailProductBinding> {\n const products = firestore.collection('hosts').doc(input.hostId).collection('products')\n const picked = aiEmailPickedProductIds(input.inputs)\n if (picked.length) {\n const snapshots = await Promise.all(picked.map((id) => products.doc(id).get()))\n return {\n ids: snapshots\n .filter((snapshot) => snapshot.exists && snapshot.get('deletedAt') == null)\n .map((snapshot) => snapshot.id),\n picked: picked.length,\n }\n }\n const snapshot = await products.select('name', 'deletedAt').limit(AI_EMAIL_PRODUCT_SCAN).get()\n const rows = snapshot.docs\n .filter((doc) => doc.get('deletedAt') == null)\n .map((doc) => ({ id: doc.id, name: String(doc.get('name') ?? '') }))\n return {\n ids: aiRecordsNamedIn(input.brief, rows, AI_EMAIL_MAX_PRODUCTS).map((row) => row.id),\n picked: 0,\n }\n}\n\n/**\n * The org list a campaign's brief names, found the way the send path finds an\n * org's lists; `null` when it names none.\n */\nexport async function suggestAiCampaignList(input: {\n hostId: string\n brief: string\n}): Promise<AiNamedRecord | null> {\n const contacts = await orgDataCollectionForHost(input.hostId, 'contacts')\n const lists = contacts.parent?.collection('lists')\n if (!lists) return null\n const snapshot = await lists.select('name').limit(AI_CAMPAIGN_LIST_SCAN).get()\n const rows = snapshot.docs.map((doc) => ({ id: doc.id, name: String(doc.get('name') ?? '') }))\n return aiRecordsNamedIn(input.brief, rows, 1)[0] ?? null\n}\n\nfunction millisOf(value: unknown): number {\n if (value instanceof Date) return value.getTime()\n if (typeof value === 'number') return value\n const toMillis = (value as { toMillis?: () => number } | null)?.toMillis\n return typeof toMillis === 'function' ? toMillis.call(value) : 0\n}\n\n/** The send time a list's past sends on this site suggest, or `null` with too little history. */\nexport async function readAiListSendTime(\n firestore: Firestore,\n input: { hostId: string; listId: string },\n): Promise<CampaignSendTimeSuggestion | null> {\n const snapshot = await firestore\n .collection('hosts')\n .doc(input.hostId)\n .collection('campaigns')\n .where('listId', '==', input.listId)\n .where('status', '==', 'sent')\n .select('sentAt', 'stats.delivered', 'stats.uniqueOpens')\n .limit(AI_CAMPAIGN_SEND_HISTORY_SCAN)\n .get()\n return suggestCampaignSendTime(\n snapshot.docs.map((doc) => ({\n sentAtMs: millisOf(doc.get('sentAt')),\n delivered: Number(doc.get('stats.delivered') ?? 0),\n uniqueOpens: Number(doc.get('stats.uniqueOpens') ?? 0),\n })),\n )\n}\n\n/** What an email's output says about its products; `null` when it binds none and none were picked. */\nexport function aiEmailProductNote(binding: AiEmailProductBinding): string | null {\n const bound = binding.ids.length\n const missing = binding.picked - bound\n const parts: string[] = []\n if (bound === 1) {\n parts.push('Its product card shows the product’s current name, price and picture when it is sent.')\n } else if (bound > 1) {\n parts.push(`Its ${bound} product cards show each product’s current name, price and picture when it is sent.`)\n }\n if (missing > 0) {\n parts.push(\n `${missing} of the products picked no longer ${missing === 1 ? 'exists' : 'exist'}, so the email places ${\n bound || 'none'\n }.`,\n )\n }\n return parts.length ? parts.join(' ') : null\n}\n\n/** What a campaign's output says about who it is for and when to send it. */\nexport function aiCampaignAudienceNote(\n list: AiNamedRecord | null,\n sendTime: CampaignSendTimeSuggestion | null,\n): string {\n if (!list) {\n return 'The email is aimed at nobody yet: choose who receives it before you schedule it.'\n }\n const when = sendTime\n ? ` Past campaigns to that list on this site were opened most when sent on ${campaignSendTimeLabel(\n sendTime,\n )}, across ${sendTime.measured} sends.`\n : ' That list has too little send history on this site to suggest a send time.'\n return `The brief names the list \"${list.name}\". The email is aimed at nobody yet: choose \"${list.name}\" as its audience before you schedule it.${when}`\n}\n"],"names":["campaignSendTimeLabel","suggestCampaignSendTime","orgDataCollectionForHost","AI_EMAIL_MAX_PRODUCTS","AI_EMAIL_PRODUCT_SCAN","AI_CAMPAIGN_LIST_SCAN","AI_CAMPAIGN_SEND_HISTORY_SCAN","wordsOf","value","toLowerCase","replace","trim","aiRecordsNamedIn","text","records","max","haystack","hits","record","needle","name","length","at","indexOf","push","end","kept","hit","sort","a","b","some","other","map","slice","Math","aiEmailPickedProductIds","inputs","raw","ids","split","filter","id","test","Set","resolveAiEmailProducts","firestore","input","products","collection","doc","hostId","picked","snapshots","Promise","all","get","snapshot","exists","select","limit","rows","docs","String","brief","row","suggestAiCampaignList","contacts","lists","parent","millisOf","Date","getTime","toMillis","call","readAiListSendTime","where","listId","sentAtMs","delivered","Number","uniqueOpens","aiEmailProductNote","binding","bound","missing","parts","join","aiCampaignAudienceNote","list","sendTime","when","measured"],"mappings":"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"}
|
|
@@ -0,0 +1,82 @@
|
|
|
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 { AiJobKind, AiJobPlan } from '../model/ai-jobs.types';
|
|
18
|
+
/**
|
|
19
|
+
* What a job kind checks before a job of it runs (AGL-2909).
|
|
20
|
+
*
|
|
21
|
+
* The create door parses the body every kind shares — the org, the site, the
|
|
22
|
+
* brief, scalar inputs — and nothing the machine knows says whether THIS kind
|
|
23
|
+
* can finish: a layout needs a site to write to, a page template names the
|
|
24
|
+
* collection it renders, and both write a document the site's plan counts.
|
|
25
|
+
* A job that cannot finish should never start, because a planned kind spends
|
|
26
|
+
* on its plan before it writes anything. So a kind registers one check, the
|
|
27
|
+
* create door asks it after the gate ladder admitted the request and before
|
|
28
|
+
* the job exists, and the resume door asks it again before a confirmed plan
|
|
29
|
+
* runs, since an allowance free at creation may be used by now. Either way
|
|
30
|
+
* a refusal hands the reservation back and spends nothing.
|
|
31
|
+
*
|
|
32
|
+
* The resume door also hands the check the plan being confirmed (AGL-2907),
|
|
33
|
+
* so a kind that can build only some plans — a page job builds one screen
|
|
34
|
+
* from what the site has — refuses the others when a member confirms them,
|
|
35
|
+
* not a beat later from inside the step.
|
|
36
|
+
*
|
|
37
|
+
* The registry lives apart from the machine so the doors read it without the
|
|
38
|
+
* generators, and a generator registers here beside its runner.
|
|
39
|
+
*/
|
|
40
|
+
export interface AiJobAdmissionContext {
|
|
41
|
+
/** The Admin SDK handle the door runs on. */
|
|
42
|
+
firestore: FirebaseFirestore.Firestore;
|
|
43
|
+
orgId: string;
|
|
44
|
+
hostId: string | null;
|
|
45
|
+
/** The job's kind-specific inputs, as the door parsed or the job stored them. */
|
|
46
|
+
inputs: Readonly<Record<string, unknown>>;
|
|
47
|
+
/** The org document the gate ladder read; a check narrows it to the fields it reads. */
|
|
48
|
+
org: object | null;
|
|
49
|
+
/**
|
|
50
|
+
* The job's plan when the door is resuming a job that has one; absent at
|
|
51
|
+
* creation, when no plan exists yet.
|
|
52
|
+
*/
|
|
53
|
+
plan?: AiJobPlan | null;
|
|
54
|
+
/**
|
|
55
|
+
* The member whose request spends: the creator at the create door, the
|
|
56
|
+
* member confirming at the resume door. A kind whose draft another plugin
|
|
57
|
+
* writes asks that plugin whether this member may create one.
|
|
58
|
+
*/
|
|
59
|
+
uid?: string | null;
|
|
60
|
+
}
|
|
61
|
+
export interface AiJobAdmissionRefusal {
|
|
62
|
+
status: 400 | 403 | 404;
|
|
63
|
+
/** Customer-safe: the door answers with it as it stands. */
|
|
64
|
+
error: string;
|
|
65
|
+
}
|
|
66
|
+
export type AiJobAdmission = (context: AiJobAdmissionContext) => Promise<AiJobAdmissionRefusal | null>;
|
|
67
|
+
/** Idempotent per kind; the last registration wins, and `null` unregisters. */
|
|
68
|
+
export declare function registerAiJobAdmission(kind: AiJobKind, admission: AiJobAdmission | null): void;
|
|
69
|
+
/** The kind's registered admission, or `null` when it has none. */
|
|
70
|
+
export declare function aiJobAdmissionFor(kind: AiJobKind): AiJobAdmission | null;
|
|
71
|
+
/** The kind's refusal, or `null` when it admits the job or has nothing to check. */
|
|
72
|
+
export declare function aiJobAdmissionRefusal(kind: AiJobKind, context: AiJobAdmissionContext): Promise<AiJobAdmissionRefusal | null>;
|
|
73
|
+
/**
|
|
74
|
+
* The refusal for a job on a site that switched AI off (AGL-3028), or `null`.
|
|
75
|
+
*
|
|
76
|
+
* Every kind meets it, and every door asks it BEFORE the kind's own check —
|
|
77
|
+
* the create door, each site of an agency batch, and a resume — so no job
|
|
78
|
+
* comes to exist, or runs another step, for a site that said no, and a
|
|
79
|
+
* switched-off site never pays for a kind's reads. A job with no site is
|
|
80
|
+
* workspace-level and always passes.
|
|
81
|
+
*/
|
|
82
|
+
export declare function aiJobSiteRefusal(context: Pick<AiJobAdmissionContext, 'firestore' | 'org' | 'hostId'>): Promise<AiJobAdmissionRefusal | null>;
|