@aglyn/plugins-ai 1.0.0-beta.219 → 1.0.0-beta.221
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/package.json +18 -18
- package/src/lib/billing/ai-month-meter.d.ts +51 -0
- package/src/lib/billing/ai-month-meter.js +89 -0
- package/src/lib/billing/ai-month-meter.js.map +1 -0
- package/src/lib/billing/ai-overage-close.d.ts +11 -33
- package/src/lib/billing/ai-overage-close.js +4 -3
- package/src/lib/billing/ai-overage-close.js.map +1 -1
- package/src/lib/billing/ai-overage-cutover.d.ts +28 -12
- package/src/lib/billing/ai-overage-cutover.js +1 -28
- package/src/lib/billing/ai-overage-cutover.js.map +1 -1
- package/src/lib/billing/ai-overage-ledger.js +1 -1
- package/src/lib/billing/ai-overage-ledger.js.map +1 -1
- package/src/lib/billing/ai-overage-standing.js +1 -1
- package/src/lib/billing/ai-overage-standing.js.map +1 -1
- package/src/lib/components/ai-allotment-editor.component.js +1 -1
- package/src/lib/components/ai-allotment-editor.component.js.map +1 -1
- package/src/lib/components/ai-assist-provider.component.js +3 -2
- package/src/lib/components/ai-assist-provider.component.js.map +1 -1
- package/src/lib/components/ai-automation-zones.d.ts +63 -0
- package/src/lib/components/ai-automation-zones.js +31 -0
- package/src/lib/components/ai-automation-zones.js.map +1 -0
- package/src/lib/components/ai-describe-automation.component.d.ts +1 -1
- package/src/lib/components/ai-describe-automation.component.js.map +1 -1
- package/src/lib/components/ai-describe-button.component.d.ts +6 -3
- package/src/lib/components/ai-describe-button.component.js +4 -1
- package/src/lib/components/ai-describe-button.component.js.map +1 -1
- package/src/lib/components/ai-explain-automation.component.d.ts +1 -1
- package/src/lib/components/ai-explain-automation.component.js.map +1 -1
- package/src/lib/components/billing-ai-allotments.component.js +1 -1
- package/src/lib/components/billing-ai-allotments.component.js.map +1 -1
- package/src/lib/components/billing-assist-overage-card.component.js +1 -1
- package/src/lib/components/billing-assist-overage-card.component.js.map +1 -1
- package/src/lib/constants.d.ts +5 -0
- package/src/lib/constants.js +4 -0
- package/src/lib/constants.js.map +1 -1
- package/src/lib/declarations.js +2 -0
- package/src/lib/declarations.js.map +1 -1
- package/src/lib/declarations.server.js +24 -10
- package/src/lib/declarations.server.js.map +1 -1
- package/src/lib/insights/ai-dataset-catalog.d.ts +49 -0
- package/src/lib/insights/ai-dataset-catalog.js +57 -0
- package/src/lib/insights/ai-dataset-catalog.js.map +1 -0
- package/src/lib/insights/ai-figure-readers.d.ts +6 -39
- package/src/lib/insights/ai-figure-readers.js +2 -391
- package/src/lib/insights/ai-figure-readers.js.map +1 -1
- package/src/lib/insights/ai-insight-digest.d.ts +10 -1
- package/src/lib/insights/ai-insight-digest.js +16 -4
- package/src/lib/insights/ai-insight-digest.js.map +1 -1
- package/src/lib/insights/ai-insight-readers.d.ts +1 -1
- package/src/lib/insights/ai-insight-readers.js.map +1 -1
- package/src/lib/jobs/ai-job-component-step.d.ts +6 -1
- package/src/lib/jobs/ai-job-component-step.js +23 -6
- package/src/lib/jobs/ai-job-component-step.js.map +1 -1
- package/src/lib/jobs/ai-job-draft-ids.js +11 -0
- package/src/lib/jobs/ai-job-draft-ids.js.map +1 -1
- package/src/lib/jobs/ai-job-email-step.d.ts +5 -1
- package/src/lib/jobs/ai-job-email-step.js +10 -1
- package/src/lib/jobs/ai-job-email-step.js.map +1 -1
- package/src/lib/jobs/ai-job-form-step.d.ts +17 -1
- package/src/lib/jobs/ai-job-form-step.js +60 -8
- package/src/lib/jobs/ai-job-form-step.js.map +1 -1
- package/src/lib/jobs/ai-job-generation.d.ts +21 -0
- package/src/lib/jobs/ai-job-generation.js +53 -1
- package/src/lib/jobs/ai-job-generation.js.map +1 -1
- package/src/lib/jobs/ai-job-insight-step.js +1 -1
- package/src/lib/jobs/ai-job-insight-step.js.map +1 -1
- package/src/lib/jobs/ai-job-layout-step.d.ts +15 -4
- package/src/lib/jobs/ai-job-layout-step.js +45 -12
- package/src/lib/jobs/ai-job-layout-step.js.map +1 -1
- package/src/lib/jobs/ai-job-plan-conformance.d.ts +5 -0
- package/src/lib/jobs/ai-job-plan-conformance.js +7 -1
- package/src/lib/jobs/ai-job-plan-conformance.js.map +1 -1
- package/src/lib/jobs/ai-job-plan-creations.d.ts +80 -0
- package/src/lib/jobs/ai-job-plan-creations.js +199 -0
- package/src/lib/jobs/ai-job-plan-creations.js.map +1 -0
- package/src/lib/jobs/ai-job-plan-step.d.ts +8 -2
- package/src/lib/jobs/ai-job-plan-step.js +20 -6
- package/src/lib/jobs/ai-job-plan-step.js.map +1 -1
- package/src/lib/jobs/ai-job-site-step.d.ts +2 -0
- package/src/lib/jobs/ai-job-site-step.js +6 -6
- package/src/lib/jobs/ai-job-site-step.js.map +1 -1
- package/src/lib/jobs/ai-job-template-step.d.ts +9 -6
- package/src/lib/jobs/ai-job-template-step.js +72 -15
- package/src/lib/jobs/ai-job-template-step.js.map +1 -1
- package/src/lib/jobs/ai-jobs.js +1 -1
- package/src/lib/jobs/ai-jobs.js.map +1 -1
- package/src/lib/jobs/ai-workflow-records.d.ts +5 -4
- package/src/lib/jobs/ai-workflow-records.js +26 -22
- package/src/lib/jobs/ai-workflow-records.js.map +1 -1
- package/src/lib/model/ai-allotments.d.ts +16 -3
- package/src/lib/model/ai-allotments.js +34 -11
- package/src/lib/model/ai-allotments.js.map +1 -1
- package/src/lib/model/ai-job-creations.d.ts +55 -0
- package/src/lib/model/ai-job-creations.js +85 -0
- package/src/lib/model/ai-job-creations.js.map +1 -0
- package/src/lib/model/ai-page-job.d.ts +3 -2
- package/src/lib/model/ai-page-job.js +4 -3
- package/src/lib/model/ai-page-job.js.map +1 -1
- package/src/lib/model/ai-site-job.d.ts +4 -2
- package/src/lib/model/ai-site-job.js +8 -4
- package/src/lib/model/ai-site-job.js.map +1 -1
- package/src/lib/model/ai-template-subjects.d.ts +10 -0
- package/src/lib/model/ai-template-subjects.js +14 -0
- package/src/lib/model/ai-template-subjects.js.map +1 -1
- package/src/lib/model/ai-tokens.js +1 -1
- package/src/lib/model/ai-tokens.js.map +1 -1
- package/src/lib/model/ai-usage-by-user.js +1 -1
- package/src/lib/model/ai-usage-by-user.js.map +1 -1
- package/src/lib/providers/catalog.js +1 -1
- package/src/lib/providers/catalog.js.map +1 -1
- package/src/lib/providers/model-choice.js +1 -1
- package/src/lib/providers/model-choice.js.map +1 -1
- package/src/lib/runtime/ai-device-audit.d.ts +1 -1
- package/src/lib/runtime/ai-device-audit.js +1 -1
- package/src/lib/runtime/ai-device-audit.js.map +1 -1
- package/src/lib/runtime/ai-eval-live.js +1 -1
- package/src/lib/runtime/ai-eval-live.js.map +1 -1
- package/src/lib/runtime/ai-eval.d.ts +1 -1
- package/src/lib/runtime/ai-eval.js.map +1 -1
- package/src/lib/runtime/ai-gate.js +1 -1
- package/src/lib/runtime/ai-gate.js.map +1 -1
- package/src/lib/runtime/ai-palette.d.ts +1 -1
- package/src/lib/runtime/ai-palette.generated.d.ts +1 -1
- package/src/lib/runtime/ai-palette.generated.js +1 -1
- package/src/lib/runtime/ai-palette.generated.js.map +1 -1
- package/src/lib/runtime/ai-palette.js.map +1 -1
- package/src/lib/runtime/site-inventory.js +28 -22
- package/src/lib/runtime/site-inventory.js.map +1 -1
- package/src/lib/server/ai-admin-org.js +1 -1
- package/src/lib/server/ai-admin-org.js.map +1 -1
- package/src/lib/server/ai-admin-orgs-spend.js +1 -1
- package/src/lib/server/ai-admin-orgs-spend.js.map +1 -1
- package/src/lib/server/ai-admin-signals.js +1 -1
- package/src/lib/server/ai-admin-signals.js.map +1 -1
- package/src/lib/server/ai-allotments.js +1 -1
- package/src/lib/server/ai-allotments.js.map +1 -1
- package/src/lib/server/ai-assist.js +2 -2
- package/src/lib/server/ai-assist.js.map +1 -1
- package/src/lib/server/assist-chat.d.ts +1 -1
- package/src/lib/server/assist-chat.js +2 -2
- package/src/lib/server/assist-chat.js.map +1 -1
- package/src/lib/server/billing-credits.d.ts +5 -0
- package/src/lib/server/billing-credits.js +8 -2
- package/src/lib/server/billing-credits.js.map +1 -1
- package/src/lib/server/billing-overage.js +2 -2
- package/src/lib/server/billing-overage.js.map +1 -1
- package/src/lib/testing/stand-in-dataset-index.d.ts +20 -0
- package/src/lib/testing/stand-in-dataset-index.js +80 -0
- package/src/lib/testing/stand-in-dataset-index.js.map +1 -0
- package/src/lib/usage/ai-allotment-alerts.d.ts +10 -7
- package/src/lib/usage/ai-allotment-alerts.js +31 -14
- package/src/lib/usage/ai-allotment-alerts.js.map +1 -1
- package/src/lib/usage/ai-quota-checks.d.ts +37 -0
- package/src/lib/usage/ai-quota-checks.js +69 -0
- package/src/lib/usage/ai-quota-checks.js.map +1 -0
- package/src/lib/usage/ai-usage-alerts.js +22 -10
- package/src/lib/usage/ai-usage-alerts.js.map +1 -1
- package/src/lib/usage/ai-usage-by-user.js +1 -1
- package/src/lib/usage/ai-usage-by-user.js.map +1 -1
- package/src/lib/usage/assist-ceiling.d.ts +2 -2
- package/src/lib/usage/assist-ceiling.js +4 -4
- package/src/lib/usage/assist-ceiling.js.map +1 -1
- package/src/lib/usage/assist-credits.d.ts +494 -0
- package/src/lib/usage/assist-credits.js +524 -0
- package/src/lib/usage/assist-credits.js.map +1 -0
- package/src/lib/usage/assist-free-taste.d.ts +1 -1
- package/src/lib/usage/assist-free-taste.js +1 -1
- package/src/lib/usage/assist-free-taste.js.map +1 -1
- package/src/lib/usage/assist-signal-mining.js +1 -1
- package/src/lib/usage/assist-signal-mining.js.map +1 -1
- package/src/lib/usage/assist-spend-guards.d.ts +153 -0
- package/src/lib/usage/assist-spend-guards.js +182 -0
- package/src/lib/usage/assist-spend-guards.js.map +1 -0
- package/src/lib/usage/assist-usage.d.ts +1 -1
- package/src/lib/usage/assist-usage.js +1 -1
- package/src/lib/usage/assist-usage.js.map +1 -1
- package/src/lib/usage/staff-org-ai.js +1 -1
- package/src/lib/usage/staff-org-ai.js.map +1 -1
- package/src/lib/usage-axes.d.ts +10 -0
- package/src/lib/usage-axes.js +40 -2
- package/src/lib/usage-axes.js.map +1 -1
|
@@ -20,12 +20,11 @@
|
|
|
20
20
|
import { listPluginEventHandlers, registerPluginEventHandler } from "@aglyn/aglyn/plugin-manager/plugin-events";
|
|
21
21
|
import { listPluginUserErasers, registerPluginUserEraser } from "@aglyn/aglyn/plugin-manager/plugin-user-erasure";
|
|
22
22
|
import { listUsageAlertContributors, registerUsageAlertContributor } from "@aglyn/aglyn/plugin-manager/usage-alert-contributors";
|
|
23
|
-
import {
|
|
23
|
+
import { registerPluginUsageMeter } from "@aglyn/aglyn/plugin-manager/plugin-usage-meters";
|
|
24
24
|
import { registerOperatorAlerts } from "@aglyn/aglyn/plugin-manager/operator-alerts";
|
|
25
|
-
import { AI_PLUGIN_ID } from "./constants.js";
|
|
25
|
+
import { AI_PLUGIN_ID, AI_USAGE_METER_ID } from "./constants.js";
|
|
26
26
|
import { AI_PROVIDER_UNAVAILABLE } from "./operator-alerts.js";
|
|
27
27
|
import { registerAiDeclarations } from "./declarations.js";
|
|
28
|
-
import { AI_OVERAGE_METER_LINE_ID, registerAiOverageMeteredLine } from "./billing/ai-overage-cutover.js";
|
|
29
28
|
/** The provider-spend staff alerts' contributor id under the plugin. */ const AI_USAGE_ALERTS_ID = 'provider-spend';
|
|
30
29
|
/**
|
|
31
30
|
* The plugin's SERVER declarations (AGL-2939): what the server must know
|
|
@@ -109,13 +108,24 @@ import { AI_OVERAGE_METER_LINE_ID, registerAiOverageMeteredLine } from "./billin
|
|
|
109
108
|
pluginId: AI_PLUGIN_ID
|
|
110
109
|
});
|
|
111
110
|
}
|
|
112
|
-
// The meter
|
|
113
|
-
//
|
|
114
|
-
//
|
|
115
|
-
//
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
111
|
+
// The plugin's meter in the monthly usage sweep: the month's provider spend
|
|
112
|
+
// onto the rollup, the credits past the band onto the invoice, and — from
|
|
113
|
+
// the cutover month (AGL-3011) — the close-out of what the plugin invoices
|
|
114
|
+
// itself. Registered at boot because the sweep is a core cron, and declared
|
|
115
|
+
// in `usageAxes` so the sweep refuses to bill a month without it. The same
|
|
116
|
+
// registration again replaces itself.
|
|
117
|
+
registerPluginUsageMeter({
|
|
118
|
+
pluginId: AI_PLUGIN_ID,
|
|
119
|
+
id: AI_USAGE_METER_ID,
|
|
120
|
+
measure: async (context)=>{
|
|
121
|
+
const { measureAiMonth } = await import("./billing/ai-month-meter.js");
|
|
122
|
+
return measureAiMonth(context);
|
|
123
|
+
},
|
|
124
|
+
closeMonth: async (context)=>{
|
|
125
|
+
const { closeAiMonth } = await import("./billing/ai-month-meter.js");
|
|
126
|
+
await closeAiMonth(context);
|
|
127
|
+
}
|
|
128
|
+
});
|
|
119
129
|
if (!listPluginUserErasers().includes(AI_PLUGIN_ID)) {
|
|
120
130
|
registerPluginUserEraser(async (request)=>{
|
|
121
131
|
const { eraseAiUsageForUser } = await import("./usage/ai-usage-eraser.js");
|
|
@@ -138,6 +148,10 @@ import { AI_OVERAGE_METER_LINE_ID, registerAiOverageMeteredLine } from "./billin
|
|
|
138
148
|
evaluate: async (context)=>{
|
|
139
149
|
const { evaluateAiUsageAlerts } = await import("./usage/ai-usage-alerts.js");
|
|
140
150
|
await evaluateAiUsageAlerts(context);
|
|
151
|
+
},
|
|
152
|
+
quotaChecks: async (context)=>{
|
|
153
|
+
const { aiQuotaChecks } = await import("./usage/ai-quota-checks.js");
|
|
154
|
+
return aiQuotaChecks(context);
|
|
141
155
|
}
|
|
142
156
|
});
|
|
143
157
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../libs/plugins/ai/src/lib/declarations.server.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// Each registry from its own module, not the `@aglyn/aglyn/server` barrel:\n// boot needs three registries rather than the whole server surface, and a\n// suite that stubs that barrel wholesale still loads these declarations\n// against the real registries.\nimport {\n listPluginEventHandlers,\n registerPluginEventHandler,\n} from '@aglyn/aglyn/plugin-manager/plugin-events'\nimport {\n listPluginUserErasers,\n registerPluginUserEraser,\n} from '@aglyn/aglyn/plugin-manager/plugin-user-erasure'\nimport {\n listUsageAlertContributors,\n registerUsageAlertContributor,\n} from '@aglyn/aglyn/plugin-manager/usage-alert-contributors'\nimport { pluginMeteredLineOwner } from '@aglyn/aglyn/plugin-manager/plugin-metered-lines'\nimport { registerOperatorAlerts } from '@aglyn/aglyn/plugin-manager/operator-alerts'\nimport { AI_PLUGIN_ID } from './constants'\nimport { AI_PROVIDER_UNAVAILABLE } from './operator-alerts'\nimport { registerAiDeclarations } from './declarations'\nimport {\n AI_OVERAGE_METER_LINE_ID,\n registerAiOverageMeteredLine,\n} from './billing/ai-overage-cutover'\n\n/** The provider-spend staff alerts' contributor id under the plugin. */\nconst AI_USAGE_ALERTS_ID = 'provider-spend'\n\n/**\n * The plugin's SERVER declarations (AGL-2939): what the server must know\n * at boot, before any door of the plugin has been called. The two platform\n * events the plugin writes activity for — the AI add-on bought or dropped,\n * an `ai.*` permission moved — are raised by core billing and membership\n * routes that never load the plugin's API surface, so the subscriptions\n * have to be in place from the first request. So does the eraser: an\n * account erasure is a core route too, and a person's AI usage months sit\n * under each org, keyed by the uid, where no core delete reaches them. So\n * does the usage alert contributor (AGL-2984): the usage-alerts sweep is a\n * core cron, and it evaluates the plugin's staff alerts on provider spend for\n * every org it reads.\n *\n * Light at boot by construction: the writers behind the handlers are\n * imported when the first event arrives, and the alert rules when the sweep\n * first evaluates an org, not when the process starts, so the boot cost is\n * the registration and nothing that touches Firestore.\n */\nexport function registerAiServerDeclarations(): void {\n registerAiDeclarations()\n // Idempotent against each REGISTRY rather than a module flag, so a\n // registry reset (a spec) or a second module instance registers again.\n if (!listPluginEventHandlers('org.seatAddons.changed').includes(AI_PLUGIN_ID)) {\n registerPluginEventHandler(\n 'org.seatAddons.changed',\n async ({ orgId, actor, before, after }) => {\n const { logAiAddonChanged } = await import('./activity/ai-activity')\n await logAiAddonChanged(orgId, actor, { before, after })\n },\n { pluginId: AI_PLUGIN_ID },\n )\n registerPluginEventHandler(\n 'org.permissions.changed',\n async ({ orgId, actor, subject, permission, granted }) => {\n if (!permission.startsWith('ai.')) return\n const { logAiPermissionChanged } = await import('./activity/ai-activity')\n await logAiPermissionChanged(orgId, actor, { subject, permission, granted })\n },\n { pluginId: AI_PLUGIN_ID },\n )\n }\n // THE PLATFORM'S BILLING EVENTS (AGL-3011). Subscribed at boot for the\n // same reason as the two above: they are raised by the billing webhook,\n // which never loads an AI door, and a workspace's overage standing moving\n // late is a workspace charged or refused against a fact we already had.\n //\n // The handler modules are imported when the first event arrives, so a\n // process that never receives one pays only for the registration.\n if (!listPluginEventHandlers('billing.invoice.paid').includes(AI_PLUGIN_ID)) {\n registerPluginEventHandler(\n 'billing.invoice.paid',\n async (payload) => {\n const { onAiBillingInvoicePaid } = await import('./billing/ai-overage-events')\n await onAiBillingInvoicePaid(payload)\n },\n { pluginId: AI_PLUGIN_ID },\n )\n registerPluginEventHandler(\n 'billing.invoice.failed',\n async (payload) => {\n const { onAiBillingInvoiceFailed } = await import('./billing/ai-overage-events')\n await onAiBillingInvoiceFailed(payload)\n },\n { pluginId: AI_PLUGIN_ID },\n )\n registerPluginEventHandler(\n 'billing.invoice.closed',\n async (payload) => {\n const { onAiBillingInvoiceClosed } = await import('./billing/ai-overage-events')\n await onAiBillingInvoiceClosed(payload)\n },\n { pluginId: AI_PLUGIN_ID },\n )\n registerPluginEventHandler(\n 'billing.dispute.opened',\n async (payload) => {\n const { onAiBillingDisputeOpened } = await import('./billing/ai-overage-events')\n await onAiBillingDisputeOpened(payload)\n },\n { pluginId: AI_PLUGIN_ID },\n )\n registerPluginEventHandler(\n 'billing.paymentMethod.changed',\n async (payload) => {\n const { onAiBillingPaymentMethodChanged } = await import(\n './billing/ai-overage-events'\n )\n await onAiBillingPaymentMethodChanged(payload)\n },\n { pluginId: AI_PLUGIN_ID },\n )\n }\n // The meter line the plugin bills for itself from the cutover month\n // (AGL-3011). Registered at boot because the monthly usage sweep is a core\n // cron; the claim reads its own cutover month on every call, so it is\n // inert until the month is configured.\n if (pluginMeteredLineOwner(AI_OVERAGE_METER_LINE_ID) !== AI_PLUGIN_ID) {\n registerAiOverageMeteredLine()\n }\n if (!listPluginUserErasers().includes(AI_PLUGIN_ID)) {\n registerPluginUserEraser(\n async (request) => {\n const { eraseAiUsageForUser } = await import('./usage/ai-usage-eraser')\n return eraseAiUsageForUser(request)\n },\n { pluginId: AI_PLUGIN_ID },\n )\n }\n // The platform provider account alert (AGL-3377), listed on Staff →\n // Operator alerts before the first one is ever raised.\n registerOperatorAlerts([AI_PROVIDER_UNAVAILABLE], { pluginId: AI_PLUGIN_ID })\n if (\n !listUsageAlertContributors().some(\n (contributor) =>\n contributor.pluginId === AI_PLUGIN_ID &&\n contributor.id === AI_USAGE_ALERTS_ID,\n )\n ) {\n registerUsageAlertContributor({\n pluginId: AI_PLUGIN_ID,\n id: AI_USAGE_ALERTS_ID,\n evaluate: async (context) => {\n const { evaluateAiUsageAlerts } = await import('./usage/ai-usage-alerts')\n await evaluateAiUsageAlerts(context)\n },\n })\n }\n}\n\nregisterAiServerDeclarations()\n"],"names":["listPluginEventHandlers","registerPluginEventHandler","listPluginUserErasers","registerPluginUserEraser","listUsageAlertContributors","registerUsageAlertContributor","pluginMeteredLineOwner","registerOperatorAlerts","AI_PLUGIN_ID","AI_PROVIDER_UNAVAILABLE","registerAiDeclarations","AI_OVERAGE_METER_LINE_ID","registerAiOverageMeteredLine","AI_USAGE_ALERTS_ID","registerAiServerDeclarations","includes","orgId","actor","before","after","logAiAddonChanged","pluginId","subject","permission","granted","startsWith","logAiPermissionChanged","payload","onAiBillingInvoicePaid","onAiBillingInvoiceFailed","onAiBillingInvoiceClosed","onAiBillingDisputeOpened","onAiBillingPaymentMethodChanged","request","eraseAiUsageForUser","some","contributor","id","evaluate","context","evaluateAiUsageAlerts"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../libs/plugins/ai/src/lib/declarations.server.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// Each registry from its own module, not the `@aglyn/aglyn/server` barrel:\n// boot needs three registries rather than the whole server surface, and a\n// suite that stubs that barrel wholesale still loads these declarations\n// against the real registries.\nimport {\n listPluginEventHandlers,\n registerPluginEventHandler,\n} from '@aglyn/aglyn/plugin-manager/plugin-events'\nimport {\n listPluginUserErasers,\n registerPluginUserEraser,\n} from '@aglyn/aglyn/plugin-manager/plugin-user-erasure'\nimport {\n listUsageAlertContributors,\n registerUsageAlertContributor,\n} from '@aglyn/aglyn/plugin-manager/usage-alert-contributors'\nimport { registerPluginUsageMeter } from '@aglyn/aglyn/plugin-manager/plugin-usage-meters'\nimport { registerOperatorAlerts } from '@aglyn/aglyn/plugin-manager/operator-alerts'\nimport { AI_PLUGIN_ID, AI_USAGE_METER_ID } from './constants'\nimport { AI_PROVIDER_UNAVAILABLE } from './operator-alerts'\nimport { registerAiDeclarations } from './declarations'\n\n/** The provider-spend staff alerts' contributor id under the plugin. */\nconst AI_USAGE_ALERTS_ID = 'provider-spend'\n\n/**\n * The plugin's SERVER declarations (AGL-2939): what the server must know\n * at boot, before any door of the plugin has been called. The two platform\n * events the plugin writes activity for — the AI add-on bought or dropped,\n * an `ai.*` permission moved — are raised by core billing and membership\n * routes that never load the plugin's API surface, so the subscriptions\n * have to be in place from the first request. So does the eraser: an\n * account erasure is a core route too, and a person's AI usage months sit\n * under each org, keyed by the uid, where no core delete reaches them. So\n * does the usage alert contributor (AGL-2984): the usage-alerts sweep is a\n * core cron, and it evaluates the plugin's staff alerts on provider spend for\n * every org it reads.\n *\n * Light at boot by construction: the writers behind the handlers are\n * imported when the first event arrives, and the alert rules when the sweep\n * first evaluates an org, not when the process starts, so the boot cost is\n * the registration and nothing that touches Firestore.\n */\nexport function registerAiServerDeclarations(): void {\n registerAiDeclarations()\n // Idempotent against each REGISTRY rather than a module flag, so a\n // registry reset (a spec) or a second module instance registers again.\n if (!listPluginEventHandlers('org.seatAddons.changed').includes(AI_PLUGIN_ID)) {\n registerPluginEventHandler(\n 'org.seatAddons.changed',\n async ({ orgId, actor, before, after }) => {\n const { logAiAddonChanged } = await import('./activity/ai-activity')\n await logAiAddonChanged(orgId, actor, { before, after })\n },\n { pluginId: AI_PLUGIN_ID },\n )\n registerPluginEventHandler(\n 'org.permissions.changed',\n async ({ orgId, actor, subject, permission, granted }) => {\n if (!permission.startsWith('ai.')) return\n const { logAiPermissionChanged } = await import('./activity/ai-activity')\n await logAiPermissionChanged(orgId, actor, { subject, permission, granted })\n },\n { pluginId: AI_PLUGIN_ID },\n )\n }\n // THE PLATFORM'S BILLING EVENTS (AGL-3011). Subscribed at boot for the\n // same reason as the two above: they are raised by the billing webhook,\n // which never loads an AI door, and a workspace's overage standing moving\n // late is a workspace charged or refused against a fact we already had.\n //\n // The handler modules are imported when the first event arrives, so a\n // process that never receives one pays only for the registration.\n if (!listPluginEventHandlers('billing.invoice.paid').includes(AI_PLUGIN_ID)) {\n registerPluginEventHandler(\n 'billing.invoice.paid',\n async (payload) => {\n const { onAiBillingInvoicePaid } = await import('./billing/ai-overage-events')\n await onAiBillingInvoicePaid(payload)\n },\n { pluginId: AI_PLUGIN_ID },\n )\n registerPluginEventHandler(\n 'billing.invoice.failed',\n async (payload) => {\n const { onAiBillingInvoiceFailed } = await import('./billing/ai-overage-events')\n await onAiBillingInvoiceFailed(payload)\n },\n { pluginId: AI_PLUGIN_ID },\n )\n registerPluginEventHandler(\n 'billing.invoice.closed',\n async (payload) => {\n const { onAiBillingInvoiceClosed } = await import('./billing/ai-overage-events')\n await onAiBillingInvoiceClosed(payload)\n },\n { pluginId: AI_PLUGIN_ID },\n )\n registerPluginEventHandler(\n 'billing.dispute.opened',\n async (payload) => {\n const { onAiBillingDisputeOpened } = await import('./billing/ai-overage-events')\n await onAiBillingDisputeOpened(payload)\n },\n { pluginId: AI_PLUGIN_ID },\n )\n registerPluginEventHandler(\n 'billing.paymentMethod.changed',\n async (payload) => {\n const { onAiBillingPaymentMethodChanged } = await import(\n './billing/ai-overage-events'\n )\n await onAiBillingPaymentMethodChanged(payload)\n },\n { pluginId: AI_PLUGIN_ID },\n )\n }\n // The plugin's meter in the monthly usage sweep: the month's provider spend\n // onto the rollup, the credits past the band onto the invoice, and — from\n // the cutover month (AGL-3011) — the close-out of what the plugin invoices\n // itself. Registered at boot because the sweep is a core cron, and declared\n // in `usageAxes` so the sweep refuses to bill a month without it. The same\n // registration again replaces itself.\n registerPluginUsageMeter({\n pluginId: AI_PLUGIN_ID,\n id: AI_USAGE_METER_ID,\n measure: async (context) => {\n const { measureAiMonth } = await import('./billing/ai-month-meter')\n return measureAiMonth(context)\n },\n closeMonth: async (context) => {\n const { closeAiMonth } = await import('./billing/ai-month-meter')\n await closeAiMonth(context)\n },\n })\n if (!listPluginUserErasers().includes(AI_PLUGIN_ID)) {\n registerPluginUserEraser(\n async (request) => {\n const { eraseAiUsageForUser } = await import('./usage/ai-usage-eraser')\n return eraseAiUsageForUser(request)\n },\n { pluginId: AI_PLUGIN_ID },\n )\n }\n // The platform provider account alert (AGL-3377), listed on Staff →\n // Operator alerts before the first one is ever raised.\n registerOperatorAlerts([AI_PROVIDER_UNAVAILABLE], { pluginId: AI_PLUGIN_ID })\n if (\n !listUsageAlertContributors().some(\n (contributor) =>\n contributor.pluginId === AI_PLUGIN_ID &&\n contributor.id === AI_USAGE_ALERTS_ID,\n )\n ) {\n registerUsageAlertContributor({\n pluginId: AI_PLUGIN_ID,\n id: AI_USAGE_ALERTS_ID,\n evaluate: async (context) => {\n const { evaluateAiUsageAlerts } = await import('./usage/ai-usage-alerts')\n await evaluateAiUsageAlerts(context)\n },\n quotaChecks: async (context) => {\n const { aiQuotaChecks } = await import('./usage/ai-quota-checks')\n return aiQuotaChecks(context)\n },\n })\n }\n}\n\nregisterAiServerDeclarations()\n"],"names":["listPluginEventHandlers","registerPluginEventHandler","listPluginUserErasers","registerPluginUserEraser","listUsageAlertContributors","registerUsageAlertContributor","registerPluginUsageMeter","registerOperatorAlerts","AI_PLUGIN_ID","AI_USAGE_METER_ID","AI_PROVIDER_UNAVAILABLE","registerAiDeclarations","AI_USAGE_ALERTS_ID","registerAiServerDeclarations","includes","orgId","actor","before","after","logAiAddonChanged","pluginId","subject","permission","granted","startsWith","logAiPermissionChanged","payload","onAiBillingInvoicePaid","onAiBillingInvoiceFailed","onAiBillingInvoiceClosed","onAiBillingDisputeOpened","onAiBillingPaymentMethodChanged","id","measure","context","measureAiMonth","closeMonth","closeAiMonth","request","eraseAiUsageForUser","some","contributor","evaluate","evaluateAiUsageAlerts","quotaChecks","aiQuotaChecks"],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* The datasets an insight question may name (AGL-2915), with their fields:
|
|
19
|
+
* what the model picks a dataset breakdown from.
|
|
20
|
+
*
|
|
21
|
+
* The datasets are the data plugin's, so they are listed through the
|
|
22
|
+
* `dataset` index it publishes (AGL-3080), never read from its collection:
|
|
23
|
+
* where no plugin keeps datasets, there are none to name. Narrowed to a site,
|
|
24
|
+
* the index answers only the datasets shared with it. Who may see which is the
|
|
25
|
+
* platform's own rule over the scope tokens each dataset carries
|
|
26
|
+
* (`memberCanSee`), applied for the member who asked — with no member, only
|
|
27
|
+
* datasets shared with every site. The figures themselves are read by the
|
|
28
|
+
* data plugin's own figure readers, under the same rule.
|
|
29
|
+
*/
|
|
30
|
+
type Firestore = FirebaseFirestore.Firestore;
|
|
31
|
+
/** Datasets a catalog lists: the dataset summary's window. */
|
|
32
|
+
export declare const AI_DATASET_CATALOG_LIMIT = 50;
|
|
33
|
+
/** A dataset a question may name, with its fields, as the read prompt lists it. */
|
|
34
|
+
export interface AiDatasetCatalogEntry {
|
|
35
|
+
id: string;
|
|
36
|
+
name: string;
|
|
37
|
+
fields: Array<{
|
|
38
|
+
id: string;
|
|
39
|
+
name: string;
|
|
40
|
+
type: string;
|
|
41
|
+
}>;
|
|
42
|
+
}
|
|
43
|
+
/** The datasets a request may read, with their fields, by name. */
|
|
44
|
+
export declare function aiDatasetCatalog(firestore: Firestore, request: {
|
|
45
|
+
orgId: string;
|
|
46
|
+
hostId: string | null;
|
|
47
|
+
uid: string | null;
|
|
48
|
+
}): Promise<AiDatasetCatalogEntry[]>;
|
|
49
|
+
export {};
|
|
@@ -0,0 +1,57 @@
|
|
|
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 { hostRoleFor, isOrgWideMember, memberCanSee } from "@aglyn/aglyn/app-utils/organizations";
|
|
18
|
+
import { ORG_SCOPE_TOKEN } from "@aglyn/aglyn/app-utils/scope-tokens";
|
|
19
|
+
import { pluginRecordIndex } from "@aglyn/aglyn/plugin-manager/plugin-record-index";
|
|
20
|
+
/** Datasets a catalog lists: the dataset summary's window. */ export const AI_DATASET_CATALOG_LIMIT = 50;
|
|
21
|
+
const text = (value)=>typeof value === 'string' ? value.trim() : '';
|
|
22
|
+
function fieldsOf(value) {
|
|
23
|
+
return (Array.isArray(value) ? value : []).map((field)=>({
|
|
24
|
+
id: text(field == null ? void 0 : field['id']),
|
|
25
|
+
name: text(field == null ? void 0 : field['name']),
|
|
26
|
+
type: text(field == null ? void 0 : field['type']) || 'text'
|
|
27
|
+
})).filter((field)=>field.id).map((field)=>_extends({}, field, {
|
|
28
|
+
name: field.name || field.id
|
|
29
|
+
}));
|
|
30
|
+
}
|
|
31
|
+
/** The datasets a request may read, with their fields, by name. */ export async function aiDatasetCatalog(firestore, request) {
|
|
32
|
+
const datasets = pluginRecordIndex('dataset');
|
|
33
|
+
if (!datasets) return [];
|
|
34
|
+
const [{ records }, memberSnapshot] = await Promise.all([
|
|
35
|
+
datasets.index.list({
|
|
36
|
+
orgId: request.orgId,
|
|
37
|
+
hostId: request.hostId,
|
|
38
|
+
limit: AI_DATASET_CATALOG_LIMIT
|
|
39
|
+
}),
|
|
40
|
+
request.uid ? firestore.collection('orgs').doc(request.orgId).collection('members').doc(request.uid).get() : Promise.resolve(null)
|
|
41
|
+
]);
|
|
42
|
+
const member = (memberSnapshot == null ? void 0 : memberSnapshot.exists) ? memberSnapshot.data() : null;
|
|
43
|
+
if (request.uid && !member) return [];
|
|
44
|
+
if (request.hostId && member && !isOrgWideMember(member) && hostRoleFor(member, request.hostId) === null) {
|
|
45
|
+
return [];
|
|
46
|
+
}
|
|
47
|
+
return records.filter((record)=>{
|
|
48
|
+
const visibleTo = Array.isArray(record.facts['visibleTo']) ? record.facts['visibleTo'] : [];
|
|
49
|
+
return member ? memberCanSee(member, visibleTo) : visibleTo.includes(ORG_SCOPE_TOKEN);
|
|
50
|
+
}).map((record)=>({
|
|
51
|
+
id: record.id,
|
|
52
|
+
name: record.name,
|
|
53
|
+
fields: fieldsOf(record.facts['fields'])
|
|
54
|
+
})).sort((a, b)=>a.name.localeCompare(b.name));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
//# sourceMappingURL=ai-dataset-catalog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/insights/ai-dataset-catalog.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 { hostRoleFor, isOrgWideMember, memberCanSee } from '@aglyn/aglyn/app-utils/organizations'\nimport { ORG_SCOPE_TOKEN } from '@aglyn/aglyn/app-utils/scope-tokens'\nimport type { AglynOrgMember } from '@aglyn/aglyn/foundation/definitions/organization.types'\nimport { pluginRecordIndex } from '@aglyn/aglyn/plugin-manager/plugin-record-index'\n\n/**\n * The datasets an insight question may name (AGL-2915), with their fields:\n * what the model picks a dataset breakdown from.\n *\n * The datasets are the data plugin's, so they are listed through the\n * `dataset` index it publishes (AGL-3080), never read from its collection:\n * where no plugin keeps datasets, there are none to name. Narrowed to a site,\n * the index answers only the datasets shared with it. Who may see which is the\n * platform's own rule over the scope tokens each dataset carries\n * (`memberCanSee`), applied for the member who asked — with no member, only\n * datasets shared with every site. The figures themselves are read by the\n * data plugin's own figure readers, under the same rule.\n */\n\ntype Firestore = FirebaseFirestore.Firestore\n\n/** Datasets a catalog lists: the dataset summary's window. */\nexport const AI_DATASET_CATALOG_LIMIT = 50\n\n/** A dataset a question may name, with its fields, as the read prompt lists it. */\nexport interface AiDatasetCatalogEntry {\n id: string\n name: string\n fields: Array<{ id: string; name: string; type: string }>\n}\n\nconst text = (value: unknown): string => (typeof value === 'string' ? value.trim() : '')\n\nfunction fieldsOf(value: unknown): AiDatasetCatalogEntry['fields'] {\n return (Array.isArray(value) ? (value as Array<Record<string, unknown>>) : [])\n .map((field) => ({ id: text(field?.['id']), name: text(field?.['name']), type: text(field?.['type']) || 'text' }))\n .filter((field) => field.id)\n .map((field) => ({ ...field, name: field.name || field.id }))\n}\n\n/** The datasets a request may read, with their fields, by name. */\nexport async function aiDatasetCatalog(\n firestore: Firestore,\n request: { orgId: string; hostId: string | null; uid: string | null },\n): Promise<AiDatasetCatalogEntry[]> {\n const datasets = pluginRecordIndex('dataset')\n if (!datasets) return []\n const [{ records }, memberSnapshot] = await Promise.all([\n datasets.index.list({ orgId: request.orgId, hostId: request.hostId, limit: AI_DATASET_CATALOG_LIMIT }),\n request.uid\n ? firestore.collection('orgs').doc(request.orgId).collection('members').doc(request.uid).get()\n : Promise.resolve(null),\n ])\n const member = memberSnapshot?.exists ? (memberSnapshot.data() as Partial<AglynOrgMember>) : null\n if (request.uid && !member) return []\n if (request.hostId && member && !isOrgWideMember(member) && hostRoleFor(member, request.hostId) === null) {\n return []\n }\n return records\n .filter((record) => {\n const visibleTo = Array.isArray(record.facts['visibleTo']) ? (record.facts['visibleTo'] as string[]) : []\n return member ? memberCanSee(member, visibleTo) : visibleTo.includes(ORG_SCOPE_TOKEN)\n })\n .map((record) => ({ id: record.id, name: record.name, fields: fieldsOf(record.facts['fields']) }))\n .sort((a, b) => a.name.localeCompare(b.name))\n}\n"],"names":["hostRoleFor","isOrgWideMember","memberCanSee","ORG_SCOPE_TOKEN","pluginRecordIndex","AI_DATASET_CATALOG_LIMIT","text","value","trim","fieldsOf","Array","isArray","map","field","id","name","type","filter","aiDatasetCatalog","firestore","request","datasets","records","memberSnapshot","Promise","all","index","list","orgId","hostId","limit","uid","collection","doc","get","resolve","member","exists","data","record","visibleTo","facts","includes","fields","sort","a","b","localeCompare"],"mappings":";AAAA;;;;;;;;;;;;;;;CAeC,GAED,SAASA,WAAW,EAAEC,eAAe,EAAEC,YAAY,QAAQ,uCAAsC;AACjG,SAASC,eAAe,QAAQ,sCAAqC;AAErE,SAASC,iBAAiB,QAAQ,kDAAiD;AAkBnF,4DAA4D,GAC5D,OAAO,MAAMC,2BAA2B,GAAE;AAS1C,MAAMC,OAAO,CAACC,QAA4B,OAAOA,UAAU,WAAWA,MAAMC,IAAI,KAAK;AAErF,SAASC,SAASF,KAAc;IAC9B,OAAO,AAACG,CAAAA,MAAMC,OAAO,CAACJ,SAAUA,QAA2C,EAAE,AAAD,EACzEK,GAAG,CAAC,CAACC,QAAW,CAAA;YAAEC,IAAIR,KAAKO,yBAAAA,KAAO,CAAC,KAAK;YAAGE,MAAMT,KAAKO,yBAAAA,KAAO,CAAC,OAAO;YAAGG,MAAMV,KAAKO,yBAAAA,KAAO,CAAC,OAAO,KAAK;QAAO,CAAA,GAC9GI,MAAM,CAAC,CAACJ,QAAUA,MAAMC,EAAE,EAC1BF,GAAG,CAAC,CAACC,QAAW,aAAKA;YAAOE,MAAMF,MAAME,IAAI,IAAIF,MAAMC,EAAE;;AAC7D;AAEA,iEAAiE,GACjE,OAAO,eAAeI,iBACpBC,SAAoB,EACpBC,OAAqE;IAErE,MAAMC,WAAWjB,kBAAkB;IACnC,IAAI,CAACiB,UAAU,OAAO,EAAE;IACxB,MAAM,CAAC,EAAEC,OAAO,EAAE,EAAEC,eAAe,GAAG,MAAMC,QAAQC,GAAG,CAAC;QACtDJ,SAASK,KAAK,CAACC,IAAI,CAAC;YAAEC,OAAOR,QAAQQ,KAAK;YAAEC,QAAQT,QAAQS,MAAM;YAAEC,OAAOzB;QAAyB;QACpGe,QAAQW,GAAG,GACPZ,UAAUa,UAAU,CAAC,QAAQC,GAAG,CAACb,QAAQQ,KAAK,EAAEI,UAAU,CAAC,WAAWC,GAAG,CAACb,QAAQW,GAAG,EAAEG,GAAG,KAC1FV,QAAQW,OAAO,CAAC;KACrB;IACD,MAAMC,SAASb,CAAAA,kCAAAA,eAAgBc,MAAM,IAAId,eAAee,IAAI,KAAiC;IAC7F,IAAIlB,QAAQW,GAAG,IAAI,CAACK,QAAQ,OAAO,EAAE;IACrC,IAAIhB,QAAQS,MAAM,IAAIO,UAAU,CAACnC,gBAAgBmC,WAAWpC,YAAYoC,QAAQhB,QAAQS,MAAM,MAAM,MAAM;QACxG,OAAO,EAAE;IACX;IACA,OAAOP,QACJL,MAAM,CAAC,CAACsB;QACP,MAAMC,YAAY9B,MAAMC,OAAO,CAAC4B,OAAOE,KAAK,CAAC,YAAY,IAAKF,OAAOE,KAAK,CAAC,YAAY,GAAgB,EAAE;QACzG,OAAOL,SAASlC,aAAakC,QAAQI,aAAaA,UAAUE,QAAQ,CAACvC;IACvE,GACCS,GAAG,CAAC,CAAC2B,SAAY,CAAA;YAAEzB,IAAIyB,OAAOzB,EAAE;YAAEC,MAAMwB,OAAOxB,IAAI;YAAE4B,QAAQlC,SAAS8B,OAAOE,KAAK,CAAC,SAAS;QAAE,CAAA,GAC9FG,IAAI,CAAC,CAACC,GAAGC,IAAMD,EAAE9B,IAAI,CAACgC,aAAa,CAACD,EAAE/B,IAAI;AAC/C"}
|
|
@@ -14,22 +14,17 @@
|
|
|
14
14
|
* See the License for the specific language governing permissions and
|
|
15
15
|
* limitations under the License.
|
|
16
16
|
*/
|
|
17
|
-
import { type PluginFigureReader
|
|
17
|
+
import { type PluginFigureReader } from '@aglyn/aglyn/plugin-manager/plugin-figures';
|
|
18
18
|
/**
|
|
19
19
|
* The figure readers this plugin registers for records the PLATFORM keeps
|
|
20
|
-
* (AGL-2915): a site's page-view counters
|
|
21
|
-
*
|
|
22
|
-
*
|
|
20
|
+
* (AGL-2915): a site's page-view counters and its forms' counters. Every
|
|
21
|
+
* other reader an insight reads is registered by the plugin that owns its
|
|
22
|
+
* records — commerce, bookings, marketing, the workspace's datasets — on the
|
|
23
23
|
* `plugin-figures` seam, and nothing here reads their documents.
|
|
24
24
|
*
|
|
25
25
|
* Each reader answers with one compact table of aggregates, read-only and
|
|
26
|
-
* about nobody: counts, sums and rates, labeled by a page path, a form's name
|
|
27
|
-
* a referring site
|
|
28
|
-
* a record. A dataset breakdown refuses a field with more than
|
|
29
|
-
* `AI_DATASET_MAX_GROUP_VALUES` different values — on a dataset of any size, a
|
|
30
|
-
* name, an address or an order number — and folds every group of fewer than
|
|
31
|
-
* `AI_DATASET_MIN_GROUP` records into one row, so each label it shows is a
|
|
32
|
-
* value at least that many records share.
|
|
26
|
+
* about nobody: counts, sums and rates, labeled by a page path, a form's name
|
|
27
|
+
* or a referring site — never a visitor or a submission.
|
|
33
28
|
*
|
|
34
29
|
* The readers use the arithmetic their console cards use: the Traffic card's
|
|
35
30
|
* windows and change (`pluginFigureWindows`, `pluginFigureChange`, which are
|
|
@@ -50,36 +45,8 @@ export declare const AI_TRAFFIC_TOP_REFERRERS = 8;
|
|
|
50
45
|
export declare const AI_TRAFFIC_TOP_CAMPAIGNS = 5;
|
|
51
46
|
/** Forms a forms table reads. */
|
|
52
47
|
export declare const AI_FORMS_READ_LIMIT = 100;
|
|
53
|
-
/** Datasets a dataset summary reads. */
|
|
54
|
-
export declare const AI_DATASETS_READ_LIMIT = 50;
|
|
55
|
-
/** Records a dataset breakdown or field summary reads, in document order; the rest are named in a note. */
|
|
56
|
-
export declare const AI_DATASET_RECORDS_READ_LIMIT = 2000;
|
|
57
|
-
/** The fewest records a breakdown shows a group of by its own label. */
|
|
58
|
-
export declare const AI_DATASET_MIN_GROUP = 3;
|
|
59
|
-
/**
|
|
60
|
-
* The most different values a breakdown groups by: every state and territory,
|
|
61
|
-
* a status, a category. A field with more tells records apart rather than
|
|
62
|
-
* sorting them, so it is refused.
|
|
63
|
-
*/
|
|
64
|
-
export declare const AI_DATASET_MAX_GROUP_VALUES = 60;
|
|
65
|
-
/** The aggregates a breakdown computes. */
|
|
66
|
-
export declare const AI_DATASET_OPERATIONS: readonly ["count", "sum", "average", "min", "max"];
|
|
67
|
-
export type AiDatasetOperation = (typeof AI_DATASET_OPERATIONS)[number];
|
|
68
48
|
export declare function trafficFigureReaders(firestore: AiFigureFirestore): PluginFigureReader[];
|
|
69
49
|
export declare function formsFigureReader(firestore: AiFigureFirestore): PluginFigureReader;
|
|
70
|
-
/** A dataset a question may name, with its fields, as the read prompt lists it. */
|
|
71
|
-
export interface AiDatasetCatalogEntry {
|
|
72
|
-
id: string;
|
|
73
|
-
name: string;
|
|
74
|
-
fields: Array<{
|
|
75
|
-
id: string;
|
|
76
|
-
name: string;
|
|
77
|
-
type: string;
|
|
78
|
-
}>;
|
|
79
|
-
}
|
|
80
|
-
/** The datasets a request may read, with their fields: what the model picks a breakdown from. */
|
|
81
|
-
export declare function aiDatasetCatalog(firestore: Firestore, request: Pick<PluginFigureRequest, 'orgId' | 'hostId' | 'uid'>): Promise<AiDatasetCatalogEntry[]>;
|
|
82
|
-
export declare function datasetFigureReaders(firestore: AiFigureFirestore): PluginFigureReader[];
|
|
83
50
|
/** Every reader this plugin registers, for the platform's own records. */
|
|
84
51
|
export declare function aiFigureReaders(firestore: AiFigureFirestore): PluginFigureReader[];
|
|
85
52
|
/**
|