@aglyn/aglyn 1.0.0-beta.217 → 1.0.0-beta.219
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 +14 -14
- package/src/lib/app-utils/actions.d.ts +25 -374
- package/src/lib/app-utils/actions.js +101 -561
- package/src/lib/app-utils/actions.js.map +1 -1
- package/src/lib/app-utils/activity-presenter.d.ts +3 -3
- package/src/lib/app-utils/activity-presenter.js +36 -52
- package/src/lib/app-utils/activity-presenter.js.map +1 -1
- package/src/lib/app-utils/admin-audit-index.js +2 -2
- package/src/lib/app-utils/admin-audit-index.js.map +1 -1
- package/src/lib/app-utils/analytics-events.d.ts +11 -2
- package/src/lib/app-utils/analytics-events.js +11 -2
- package/src/lib/app-utils/analytics-events.js.map +1 -1
- package/src/lib/app-utils/analytics-provider.d.ts +182 -0
- package/src/lib/app-utils/analytics-provider.js +133 -0
- package/src/lib/app-utils/analytics-provider.js.map +1 -0
- package/src/lib/app-utils/api-plugins.d.ts +46 -0
- package/src/lib/app-utils/api-plugins.js +19 -0
- package/src/lib/app-utils/api-plugins.js.map +1 -1
- package/src/lib/app-utils/{marketplace-overrides.d.ts → artifact-overrides.d.ts} +9 -6
- package/src/lib/app-utils/{marketplace-overrides.js → artifact-overrides.js} +10 -7
- package/src/lib/app-utils/artifact-overrides.js.map +1 -0
- package/src/lib/app-utils/{marketplace-provenance.d.ts → artifact-provenance.d.ts} +12 -10
- package/src/lib/app-utils/{marketplace-provenance.js → artifact-provenance.js} +9 -7
- package/src/lib/app-utils/artifact-provenance.js.map +1 -0
- package/src/lib/app-utils/assist-credits.js +2 -1
- package/src/lib/app-utils/assist-credits.js.map +1 -1
- package/src/lib/app-utils/binding-token-catalog.d.ts +5 -13
- package/src/lib/app-utils/binding-token-catalog.js +17 -41
- package/src/lib/app-utils/binding-token-catalog.js.map +1 -1
- package/src/lib/app-utils/binding-tokens.js +1 -1
- package/src/lib/app-utils/binding-tokens.js.map +1 -1
- package/src/lib/app-utils/brand-support-line.d.ts +36 -0
- package/src/lib/app-utils/brand-support-line.js +38 -0
- package/src/lib/app-utils/brand-support-line.js.map +1 -0
- package/src/lib/app-utils/campaign-touch.d.ts +5 -5
- package/src/lib/app-utils/campaign-touch.js +8 -8
- package/src/lib/app-utils/campaign-touch.js.map +1 -1
- package/src/lib/app-utils/collection-entries.d.ts +2 -2
- package/src/lib/app-utils/collection-entries.js.map +1 -1
- package/src/lib/app-utils/consent-group-change.d.ts +4 -0
- package/src/lib/app-utils/consent-group-change.js.map +1 -1
- package/src/lib/app-utils/console-record-links.d.ts +10 -89
- package/src/lib/app-utils/console-record-links.js +3 -107
- package/src/lib/app-utils/console-record-links.js.map +1 -1
- package/src/lib/app-utils/console-routes.d.ts +16 -7
- package/src/lib/app-utils/console-routes.js +9 -3
- package/src/lib/app-utils/console-routes.js.map +1 -1
- package/src/lib/app-utils/contacts.d.ts +23 -1
- package/src/lib/app-utils/contacts.js +21 -5
- package/src/lib/app-utils/contacts.js.map +1 -1
- package/src/lib/app-utils/cross-pool-desync.d.ts +39 -0
- package/src/lib/app-utils/cross-pool-desync.js +47 -0
- package/src/lib/app-utils/cross-pool-desync.js.map +1 -0
- package/src/lib/app-utils/csv-upload.d.ts +29 -0
- package/src/lib/app-utils/csv-upload.js +29 -0
- package/src/lib/app-utils/csv-upload.js.map +1 -0
- package/src/lib/app-utils/dataset-models.d.ts +5 -5
- package/src/lib/app-utils/dataset-models.js +19 -2
- package/src/lib/app-utils/dataset-models.js.map +1 -1
- package/src/lib/app-utils/datasets.d.ts +65 -11
- package/src/lib/app-utils/datasets.js +74 -11
- package/src/lib/app-utils/datasets.js.map +1 -1
- package/src/lib/app-utils/docs-deflection.d.ts +6 -6
- package/src/lib/app-utils/docs-deflection.js.map +1 -1
- package/src/lib/app-utils/docs-help.generated.d.ts +12 -6
- package/src/lib/app-utils/docs-help.generated.js +21 -6
- package/src/lib/app-utils/docs-help.generated.js.map +1 -1
- package/src/lib/app-utils/docs-index.generated.d.ts +2 -2
- package/src/lib/app-utils/docs-index.generated.js +514 -318
- package/src/lib/app-utils/docs-index.generated.js.map +1 -1
- package/src/lib/app-utils/docs-retrieval.d.ts +3 -3
- package/src/lib/app-utils/docs-retrieval.js +14 -10
- package/src/lib/app-utils/docs-retrieval.js.map +1 -1
- package/src/lib/app-utils/duplicate-resource.d.ts +4 -1
- package/src/lib/app-utils/duplicate-resource.js +7 -4
- package/src/lib/app-utils/duplicate-resource.js.map +1 -1
- package/src/lib/app-utils/dynamic-list-rule.d.ts +1 -1
- package/src/lib/app-utils/dynamic-list-rule.js.map +1 -1
- package/src/lib/app-utils/element-ui.d.ts +1 -1
- package/src/lib/app-utils/element-ui.js +1 -1
- package/src/lib/app-utils/element-ui.js.map +1 -1
- package/src/lib/app-utils/email-starter-policy.js +3 -3
- package/src/lib/app-utils/email-starter-policy.js.map +1 -1
- package/src/lib/app-utils/entity-picker-context.d.ts +10 -5
- package/src/lib/app-utils/entity-picker-context.js.map +1 -1
- package/src/lib/app-utils/error-beacon.d.ts +75 -6
- package/src/lib/app-utils/error-beacon.js +160 -21
- package/src/lib/app-utils/error-beacon.js.map +1 -1
- package/src/lib/app-utils/expand-repeatables.d.ts +10 -10
- package/src/lib/app-utils/expand-repeatables.js +10 -10
- package/src/lib/app-utils/expand-repeatables.js.map +1 -1
- package/src/lib/app-utils/host-events.d.ts +82 -0
- package/src/lib/app-utils/host-events.js +62 -0
- package/src/lib/app-utils/host-events.js.map +1 -0
- package/src/lib/app-utils/lockdown.d.ts +33 -1
- package/src/lib/app-utils/lockdown.js +45 -4
- package/src/lib/app-utils/lockdown.js.map +1 -1
- package/src/lib/app-utils/margin-utilization.d.ts +4 -69
- package/src/lib/app-utils/margin-utilization.js +82 -69
- package/src/lib/app-utils/margin-utilization.js.map +1 -1
- package/src/lib/app-utils/node-definition-sanitizer.d.ts +16 -16
- package/src/lib/app-utils/node-definition-sanitizer.js +24 -20
- package/src/lib/app-utils/node-definition-sanitizer.js.map +1 -1
- package/src/lib/app-utils/node-interactions.d.ts +7 -7
- package/src/lib/app-utils/node-interactions.js.map +1 -1
- package/src/lib/app-utils/notifications.d.ts +78 -47
- package/src/lib/app-utils/notifications.js +63 -44
- package/src/lib/app-utils/notifications.js.map +1 -1
- package/src/lib/app-utils/payments-configured.d.ts +8 -21
- package/src/lib/app-utils/payments-configured.js +8 -23
- package/src/lib/app-utils/payments-configured.js.map +1 -1
- package/src/lib/app-utils/plan-entitlements.d.ts +43 -128
- package/src/lib/app-utils/plan-entitlements.js +145 -304
- package/src/lib/app-utils/plan-entitlements.js.map +1 -1
- package/src/lib/app-utils/platform-brand.d.ts +10 -0
- package/src/lib/app-utils/platform-brand.js +14 -3
- package/src/lib/app-utils/platform-brand.js.map +1 -1
- package/src/lib/app-utils/plugin-api-rate-limit.d.ts +7 -1
- package/src/lib/app-utils/plugin-api-rate-limit.js +11 -3
- package/src/lib/app-utils/plugin-api-rate-limit.js.map +1 -1
- package/src/lib/app-utils/plugin-bundle-checks.js +2 -2
- package/src/lib/app-utils/plugin-bundle-checks.js.map +1 -1
- package/src/lib/app-utils/plugin-host-events.generated.d.ts +12 -0
- package/src/lib/app-utils/plugin-host-events.generated.js +169 -0
- package/src/lib/app-utils/plugin-host-events.generated.js.map +1 -0
- package/src/lib/app-utils/plugin-release-flags.generated.d.ts +12 -0
- package/src/lib/app-utils/plugin-release-flags.generated.js +106 -0
- package/src/lib/app-utils/plugin-release-flags.generated.js.map +1 -0
- package/src/lib/app-utils/realm-host-surface.generated.js +2 -0
- package/src/lib/app-utils/realm-host-surface.generated.js.map +1 -1
- package/src/lib/app-utils/release-flags.d.ts +14 -5
- package/src/lib/app-utils/release-flags.js +21 -125
- package/src/lib/app-utils/release-flags.js.map +1 -1
- package/src/lib/app-utils/repeat-sources.d.ts +9 -0
- package/src/lib/app-utils/repeat-sources.js.map +1 -1
- package/src/lib/app-utils/retained-refusals.d.ts +73 -0
- package/src/lib/app-utils/retained-refusals.js +186 -0
- package/src/lib/app-utils/retained-refusals.js.map +1 -0
- package/src/lib/app-utils/scope-tokens.d.ts +27 -0
- package/src/lib/app-utils/scope-tokens.js +61 -0
- package/src/lib/app-utils/scope-tokens.js.map +1 -1
- package/src/lib/app-utils/screen-link-context.js +3 -3
- package/src/lib/app-utils/screen-link-context.js.map +1 -1
- package/src/lib/app-utils/screen-route.d.ts +15 -0
- package/src/lib/app-utils/screen-route.js +21 -1
- package/src/lib/app-utils/screen-route.js.map +1 -1
- package/src/lib/app-utils/seo-audit.d.ts +132 -0
- package/src/lib/app-utils/seo-audit.js +246 -0
- package/src/lib/app-utils/seo-audit.js.map +1 -0
- package/src/lib/app-utils/seo-keywords.d.ts +48 -0
- package/src/lib/app-utils/seo-keywords.js +60 -0
- package/src/lib/app-utils/seo-keywords.js.map +1 -0
- package/src/lib/app-utils/seo-page-facts.d.ts +66 -0
- package/src/lib/app-utils/seo-page-facts.js +155 -0
- package/src/lib/app-utils/seo-page-facts.js.map +1 -0
- package/src/lib/app-utils/seo-site-scan.d.ts +126 -0
- package/src/lib/app-utils/seo-site-scan.js +162 -0
- package/src/lib/app-utils/seo-site-scan.js.map +1 -0
- package/src/lib/app-utils/seo-title-variables.js +1 -1
- package/src/lib/app-utils/seo-title-variables.js.map +1 -1
- package/src/lib/app-utils/server.d.ts +6 -9
- package/src/lib/app-utils/server.js +17 -27
- package/src/lib/app-utils/server.js.map +1 -1
- package/src/lib/app-utils/site-interactions.d.ts +501 -0
- package/src/lib/app-utils/site-interactions.js +554 -0
- package/src/lib/app-utils/site-interactions.js.map +1 -0
- package/src/lib/app-utils/{marketplace-theme.d.ts → site-theme.d.ts} +13 -2
- package/src/lib/app-utils/{marketplace-theme.js → site-theme.js} +5 -2
- package/src/lib/app-utils/site-theme.js.map +1 -0
- package/src/lib/app-utils/sitemap.d.ts +4 -3
- package/src/lib/app-utils/sitemap.js +9 -7
- package/src/lib/app-utils/sitemap.js.map +1 -1
- package/src/lib/app-utils/stale-build-error.d.ts +51 -0
- package/src/lib/app-utils/stale-build-error.js +100 -1
- package/src/lib/app-utils/stale-build-error.js.map +1 -1
- package/src/lib/app-utils/starter-templates.d.ts +20 -0
- package/src/lib/app-utils/starter-templates.js +49 -0
- package/src/lib/app-utils/starter-templates.js.map +1 -1
- package/src/lib/app-utils/tax-jurisdiction-figures.d.ts +118 -0
- package/src/lib/app-utils/tax-jurisdiction-figures.js +123 -0
- package/src/lib/app-utils/tax-jurisdiction-figures.js.map +1 -0
- package/src/lib/app-utils/theme-library.d.ts +10 -3
- package/src/lib/app-utils/theme-library.js +13 -4
- package/src/lib/app-utils/theme-library.js.map +1 -1
- package/src/lib/app-utils/{campaign-attribution.d.ts → utm-attribution.d.ts} +11 -6
- package/src/lib/app-utils/{campaign-attribution.js → utm-attribution.js} +13 -8
- package/src/lib/app-utils/utm-attribution.js.map +1 -0
- package/src/lib/app-utils/{campaign-forwarding.d.ts → utm-forwarding.d.ts} +14 -14
- package/src/lib/app-utils/{campaign-forwarding.js → utm-forwarding.js} +26 -26
- package/src/lib/app-utils/utm-forwarding.js.map +1 -0
- package/src/lib/app-utils/video-object.js +6 -5
- package/src/lib/app-utils/video-object.js.map +1 -1
- package/src/lib/app-utils/visitor-consent.d.ts +41 -164
- package/src/lib/app-utils/visitor-consent.js +66 -277
- package/src/lib/app-utils/visitor-consent.js.map +1 -1
- package/src/lib/app-utils/web-vitals-rum.d.ts +7 -7
- package/src/lib/app-utils/web-vitals-rum.js +31 -63
- package/src/lib/app-utils/web-vitals-rum.js.map +1 -1
- package/src/lib/app-utils/where-used.d.ts +11 -6
- package/src/lib/app-utils/where-used.js +3 -8
- package/src/lib/app-utils/where-used.js.map +1 -1
- package/src/lib/canvas-manager/canvas-manager.js +3 -3
- package/src/lib/canvas-manager/canvas-manager.js.map +1 -1
- package/src/lib/foundation/definitions/components.types.d.ts +1 -1
- package/src/lib/foundation/definitions/components.types.js +1 -1
- package/src/lib/foundation/definitions/components.types.js.map +1 -1
- package/src/lib/foundation/definitions/org-billing.types.d.ts +18 -135
- package/src/lib/foundation/definitions/org-billing.types.js.map +1 -1
- package/src/lib/foundation/definitions/organization.types.d.ts +6 -3
- package/src/lib/foundation/definitions/organization.types.js.map +1 -1
- package/src/lib/foundation/definitions/platform.types.d.ts +27 -5
- package/src/lib/foundation/definitions/platform.types.js.map +1 -1
- package/src/lib/foundation/definitions/write-deny-coverage.util.d.ts +16 -0
- package/src/lib/foundation/definitions/write-deny-coverage.util.js +20 -0
- package/src/lib/foundation/definitions/write-deny-coverage.util.js.map +1 -1
- package/src/lib/foundation/index.d.ts +1 -1
- package/src/lib/foundation/index.js.map +1 -1
- package/src/lib/plugin-manager/besigner-documents.d.ts +96 -0
- package/src/lib/plugin-manager/besigner-documents.js +61 -0
- package/src/lib/plugin-manager/besigner-documents.js.map +1 -0
- package/src/lib/plugin-manager/computed-variables.d.ts +71 -0
- package/src/lib/plugin-manager/computed-variables.js +74 -0
- package/src/lib/plugin-manager/computed-variables.js.map +1 -0
- package/src/lib/plugin-manager/custom-fields.d.ts +29 -2
- package/src/lib/plugin-manager/custom-fields.js +47 -1
- package/src/lib/plugin-manager/custom-fields.js.map +1 -1
- package/src/lib/plugin-manager/feature-plugins.d.ts +292 -20
- package/src/lib/plugin-manager/feature-plugins.js +105 -17
- package/src/lib/plugin-manager/feature-plugins.js.map +1 -1
- package/src/lib/plugin-manager/first-party-plugins.generated.d.ts +123 -0
- package/src/lib/plugin-manager/first-party-plugins.generated.js +785 -14
- package/src/lib/plugin-manager/first-party-plugins.generated.js.map +1 -1
- package/src/lib/plugin-manager/plugin-activity-actions.d.ts +12 -0
- package/src/lib/plugin-manager/plugin-activity-actions.js +25 -0
- package/src/lib/plugin-manager/plugin-activity-actions.js.map +1 -1
- package/src/lib/plugin-manager/plugin-contributions.d.ts +1 -1
- package/src/lib/plugin-manager/plugin-contributions.js.map +1 -1
- package/src/lib/plugin-manager/plugin-declarations-repair.d.ts +36 -0
- package/src/lib/plugin-manager/plugin-declarations-repair.js +64 -0
- package/src/lib/plugin-manager/plugin-declarations-repair.js.map +1 -0
- package/src/lib/plugin-manager/plugin-dependents.d.ts +101 -0
- package/src/lib/plugin-manager/plugin-dependents.js +75 -0
- package/src/lib/plugin-manager/plugin-dependents.js.map +1 -0
- package/src/lib/plugin-manager/plugin-distribution.d.ts +55 -0
- package/src/lib/plugin-manager/plugin-distribution.js +45 -0
- package/src/lib/plugin-manager/plugin-distribution.js.map +1 -0
- package/src/lib/plugin-manager/plugin-host-collections.d.ts +17 -0
- package/src/lib/plugin-manager/plugin-host-collections.js +6 -0
- package/src/lib/plugin-manager/plugin-host-collections.js.map +1 -1
- package/src/lib/plugin-manager/plugin-host-resources.d.ts +133 -0
- package/src/lib/plugin-manager/plugin-host-resources.js +52 -0
- package/src/lib/plugin-manager/plugin-host-resources.js.map +1 -0
- package/src/lib/plugin-manager/plugin-org-erasure.d.ts +28 -2
- package/src/lib/plugin-manager/plugin-org-erasure.js +61 -2
- package/src/lib/plugin-manager/plugin-org-erasure.js.map +1 -1
- package/src/lib/plugin-manager/plugin-plan-entitlements.d.ts +123 -0
- package/src/lib/plugin-manager/plugin-plan-entitlements.js +101 -0
- package/src/lib/plugin-manager/plugin-plan-entitlements.js.map +1 -0
- package/src/lib/plugin-manager/plugin-record-index.d.ts +95 -0
- package/src/lib/plugin-manager/plugin-record-index.js +51 -0
- package/src/lib/plugin-manager/plugin-record-index.js.map +1 -0
- package/src/lib/plugin-manager/plugin-record-written.d.ts +58 -0
- package/src/lib/plugin-manager/plugin-record-written.js +42 -0
- package/src/lib/plugin-manager/plugin-record-written.js.map +1 -0
- package/src/lib/plugin-manager/plugin-revenue-sources.d.ts +213 -0
- package/src/lib/plugin-manager/plugin-revenue-sources.js +194 -0
- package/src/lib/plugin-manager/plugin-revenue-sources.js.map +1 -0
- package/src/lib/plugin-manager/plugin-site-bundle.d.ts +145 -0
- package/src/lib/plugin-manager/plugin-site-bundle.js +78 -0
- package/src/lib/plugin-manager/plugin-site-bundle.js.map +1 -0
- package/src/lib/plugin-manager/plugin-site-cache.d.ts +12 -0
- package/src/lib/plugin-manager/plugin-site-cache.js.map +1 -1
- package/src/lib/plugin-manager/plugin-site-export.d.ts +81 -0
- package/src/lib/plugin-manager/plugin-site-export.js +40 -0
- package/src/lib/plugin-manager/plugin-site-export.js.map +1 -0
- package/src/lib/plugin-manager/plugin-sitemap-sections.d.ts +88 -0
- package/src/lib/plugin-manager/plugin-sitemap-sections.js +29 -0
- package/src/lib/plugin-manager/plugin-sitemap-sections.js.map +1 -0
- package/src/lib/plugin-manager/plugin-tax-profile.d.ts +20 -4
- package/src/lib/plugin-manager/plugin-tax-profile.js.map +1 -1
- package/src/lib/plugin-manager/plugin-tax-return-sources.d.ts +255 -0
- package/src/lib/plugin-manager/plugin-tax-return-sources.js +191 -0
- package/src/lib/plugin-manager/plugin-tax-return-sources.js.map +1 -0
- package/src/lib/plugin-manager/plugin-template-sources.d.ts +75 -0
- package/src/lib/plugin-manager/plugin-template-sources.js +37 -0
- package/src/lib/plugin-manager/plugin-template-sources.js.map +1 -0
- package/src/lib/plugin-manager/plugin-usage-axes.d.ts +107 -0
- package/src/lib/plugin-manager/plugin-usage-axes.js +107 -0
- package/src/lib/plugin-manager/plugin-usage-axes.js.map +1 -0
- package/src/lib/plugin-manager/plugin-zones.d.ts +4 -5
- package/src/lib/plugin-manager/plugin-zones.js.map +1 -1
- package/src/lib/plugin-manager/realm-host-aglyn.generated.js +2 -0
- package/src/lib/plugin-manager/realm-host-aglyn.generated.js.map +1 -1
- package/src/lib/plugin-manager/record-captured-contact.d.ts +1 -14
- package/src/lib/plugin-manager/record-captured-contact.js +10 -32
- package/src/lib/plugin-manager/record-captured-contact.js.map +1 -1
- package/src/lib/plugin-manager/repeat-rows.d.ts +124 -0
- package/src/lib/plugin-manager/repeat-rows.js +108 -0
- package/src/lib/plugin-manager/repeat-rows.js.map +1 -0
- package/src/lib/plugin-manager/submission-record-target.d.ts +144 -0
- package/src/lib/plugin-manager/submission-record-target.js +125 -0
- package/src/lib/plugin-manager/submission-record-target.js.map +1 -0
- package/src/lib/plugin-manager/video-embed-provider.d.ts +108 -0
- package/src/lib/plugin-manager/video-embed-provider.js +165 -0
- package/src/lib/plugin-manager/video-embed-provider.js.map +1 -0
- package/src/lib/types/nodes.d.ts +2 -2
- package/src/lib/types/nodes.js.map +1 -1
- package/src/lib/app-utils/campaign-attribution.js.map +0 -1
- package/src/lib/app-utils/campaign-forwarding.js.map +0 -1
- package/src/lib/app-utils/contact-holder.d.ts +0 -68
- package/src/lib/app-utils/contact-holder.js +0 -129
- package/src/lib/app-utils/contact-holder.js.map +0 -1
- package/src/lib/app-utils/contact-merge.d.ts +0 -136
- package/src/lib/app-utils/contact-merge.js +0 -412
- package/src/lib/app-utils/contact-merge.js.map +0 -1
- package/src/lib/app-utils/crm-csv.d.ts +0 -239
- package/src/lib/app-utils/crm-csv.js +0 -467
- package/src/lib/app-utils/crm-csv.js.map +0 -1
- package/src/lib/app-utils/crm-digest.d.ts +0 -185
- package/src/lib/app-utils/crm-digest.js +0 -272
- package/src/lib/app-utils/crm-digest.js.map +0 -1
- package/src/lib/app-utils/form-dataset-binding.d.ts +0 -50
- package/src/lib/app-utils/form-dataset-binding.js +0 -74
- package/src/lib/app-utils/form-dataset-binding.js.map +0 -1
- package/src/lib/app-utils/list-import.d.ts +0 -158
- package/src/lib/app-utils/list-import.js +0 -332
- package/src/lib/app-utils/list-import.js.map +0 -1
- package/src/lib/app-utils/marketplace-listing-visibility.d.ts +0 -122
- package/src/lib/app-utils/marketplace-listing-visibility.js +0 -147
- package/src/lib/app-utils/marketplace-listing-visibility.js.map +0 -1
- package/src/lib/app-utils/marketplace-overrides.js.map +0 -1
- package/src/lib/app-utils/marketplace-provenance.js.map +0 -1
- package/src/lib/app-utils/marketplace-theme.js.map +0 -1
- package/src/lib/app-utils/marketplace-update-state.d.ts +0 -119
- package/src/lib/app-utils/marketplace-update-state.js +0 -132
- package/src/lib/app-utils/marketplace-update-state.js.map +0 -1
- package/src/lib/app-utils/publisher-agreement.d.ts +0 -289
- package/src/lib/app-utils/publisher-agreement.js +0 -321
- package/src/lib/app-utils/publisher-agreement.js.map +0 -1
- package/src/lib/app-utils/wistia-embed.d.ts +0 -104
- package/src/lib/app-utils/wistia-embed.js +0 -138
- package/src/lib/app-utils/wistia-embed.js.map +0 -1
- package/src/lib/app-utils/workflows.d.ts +0 -136
- package/src/lib/app-utils/workflows.js +0 -346
- package/src/lib/app-utils/workflows.js.map +0 -1
- package/src/lib/plugin-manager/commerce-zone-props.d.ts +0 -172
- package/src/lib/plugin-manager/commerce-zone-props.js +0 -31
- package/src/lib/plugin-manager/commerce-zone-props.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../libs/aglyn/src/lib/app-utils/docs-deflection.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { AssistDocsSection } from './docs-index.generated'\nimport {\n DOCS_SITE_ORIGIN,\n docsDocumentFrequency,\n tokenize,\n type ScoredSection,\n} from './docs-retrieval'\n\n/**\n * Retrieval-first answering for Aglyn Assist (AGL-2486) — the deflection gate.\n *\n * Most assist traffic is \"how do I X\", and the answer to \"how do I X\" is\n * already written down in `apps/docs/docs`. Sending that question to a model\n * so the model can read the docs section back to the user pays provider money\n * to reformat prose we wrote ourselves. This module decides when retrieval is\n * confident enough to hand the docs straight over, and composes the answer\n * when it is. Escalation to the model is what happens the rest of the time —\n * it is the fallback, not the default.\n *\n * ## The one rule: never fabricate\n *\n * A deflected answer contains exactly two kinds of text:\n *\n * 1. Fixed template strings from this file, which say nothing about the\n * product — they name the page and introduce the quote.\n * 2. Section text copied VERBATIM out of the docs index, with the URL of\n * the page it came from.\n *\n * There is no summarisation, no paraphrase and no stitching of adjacent\n * sections into a claim neither one makes. The spec asserts it by\n * RECONSTRUCTION — \"never fabricate — every word is template or verbatim\n * docs\" — stripping the template from a composed answer and requiring what is\n * left to be a prefix of a real section's `text`. That property is the whole\n * safety argument, because a wrong retrieval answer is worse than an\n * escalation — it is confidently wrong prose delivered to a paying customer\n * with a citation under it, which is the shape people trust most.\n *\n * ## What \"confident\" means\n *\n * Seven conditions, ALL of which must hold. Any one failing escalates; there\n * is no partial-credit path where a weak match produces a hedged answer,\n * because a hedged wrong answer is still a wrong answer and it has already\n * cost the user the click.\n *\n * 1. **The question stands on its own.** A follow-up is usually not\n * self-contained: \"does that work on the free plan?\" retrieves the\n * billing pages beautifully and answers a question nobody asked. The\n * conversation is the missing half and only the model has it.\n *\n * The gate is NOT \"no prior turn\" (AGL-2486). Not every follow-up leans\n * on the transcript: the second question in a thread is very often a\n * fresh, complete question that happens to be asked second. Refusing all\n * of them means a thread answers its first question from the docs and\n * then escalates forever — and on a deployment with no AI provider\n * key that reads as \"Aglyn Assist is not configured\",\n * one question in, to a user who just watched it work. A product that\n * answers exactly once per thread is worse than one that never answers,\n * because the second refusal looks like a fault rather than a limit.\n *\n * So the gate now asks whether THIS question stands alone, and holds a\n * raised bar when it does — see {@link questionStandsAlone} and the\n * `FOLLOW_UP_*` constants.\n * 2. **Enough question.** At least {@link MIN_QUESTION_TOKENS} distinct\n * content tokens after stop-word removal. Below that there is not enough\n * of a question to be confident ABOUT.\n * 3. **Not a generative request.** \"write me a hero headline\" is the copy\n * assistant's job, not a docs lookup, and no docs page answers it.\n * 4. **Not a diagnostic.** \"why isn't my domain verifying\" has a\n * troubleshooting page, and dumping that page at someone whose actual\n * problem is one of nine listed causes is exactly the confidently-wrong\n * failure. Diagnostics need the workspace's own state, which is the\n * level-2 context only the model gets.\n * 5. **Absolute score.** The top section scores at least\n * {@link MIN_TOP_SCORE}.\n * 6. **Page dominance.** The winning page beats the best RIVAL page by at\n * least {@link MIN_PAGE_MARGIN}. Measured against the runner-up page\n * rather than as a share of the whole retrieved set, because the set is\n * six sections wide: a page that is unambiguously right still holds a\n * minority of a six-way split the moment three neighbouring pages use the\n * same nouns, and a share test reads that dilution as doubt. And the\n * comparison is page-to-page, not section-to-section — sections of ONE\n * page scoring alike is agreement, which a section margin scores as a tie.\n * 7. **Substance.** The winning section carries at least\n * {@link MIN_SECTION_CHARS} of text. A three-word stub under a heading is\n * a pointer, not an answer.\n *\n * Below the bar the request proceeds exactly as it did before this module\n * existed: the same sections are still retrieved and still ground the model's\n * prompt. Deflection removes model calls; it never removes grounding.\n *\n * ## The thresholds are measured, not guessed\n *\n * `docs-deflection.spec.ts` carries a fixed set of realistic questions —\n * positives written in user vocabulary rather than lifted from docs headings,\n * and negatives that MUST escalate — and asserts a floor on the deflection\n * rate and a ceiling of zero on the negatives. Retuning a constant here\n * without rerunning that spec is how a threshold ends up set by whoever\n * touched it last.\n */\n\n/**\n * Distinct content tokens a question needs before it can be answered.\n *\n * Two, not three, and the difference is most of the corpus: \"how do I install\n * a plugin\", \"what are dataset relations\" and \"how do I cancel my\n * subscription\" all reduce to exactly two content tokens once the stop words\n * go, and every one of them is a plain docs lookup. Three excluded them all.\n *\n * Two is safe here only because the gates below are not a checklist a weak\n * question can pass by being short: a two-token question must have BOTH\n * tokens carried by the winning page (the IDF weighting cannot rescue it —\n * there is nothing generic to discount), and the page must still clear the\n * score floor and out-score its rival. \"is my site down\" has two tokens and\n * fails on dominance, not on length.\n */\nconst MIN_QUESTION_TOKENS = 2\n\n/**\n * Absolute floor on the winning section's retrieval score.\n *\n * The scorer gives 2.5 for a title hit, 2 for a heading hit and up to ~2.2 per\n * body term — about 6.7 for one term landing everywhere at once. 5 is\n * therefore roughly \"two question terms landed and at least one of them hit\n * the page's own statement of topic\". Below that the match is incidental\n * vocabulary rather than a page about the thing.\n *\n * Measured down from 6, which cost five ordinary lookups scoring 4.4–5.9\n * (\"how do I cancel my subscription\", \"how do I set up sso for my team\") and\n * bought nothing: the negative set does not move between the two values,\n * because what actually stops those is coverage and dominance, not the floor.\n */\nconst MIN_TOP_SCORE = 5\n\n/**\n * How far the winning page must out-score the best rival page.\n *\n * 1.3x — the winner needs a visible lead, not a photo finish. Two pages\n * within 30% of each other on the same question means retrieval genuinely\n * does not know which one the user meant, and picking is a coin flip dressed\n * up as an answer.\n *\n * A question that retrieves only ONE page has no rival and passes this gate\n * outright; the score floor and coverage are what bound it there.\n */\nconst MIN_PAGE_MARGIN = 1.3\n\n/**\n * Weighted fraction of the question the winning page must actually contain.\n * Coverage and score answer different questions: score says the page matched\n * strongly, coverage says the page did not IGNORE part of what was asked.\n * \"how do I password protect a screen on the free plan\" scores highly on the\n * site-protection page while silently dropping \"free plan\", and the answer\n * that comes back is then wrong in the one way that matters.\n *\n * ⚠️ WEIGHTED BY IDF, and an unweighted version of this test is why nine\n * perfectly ordinary questions escalated in the first measurement. \"how do I\n * make a reusable component\" covers `reusable` and `component` and misses\n * `make`, because the page says \"create\" — 2/3, under the bar, escalated. The\n * miss carried no information: `make` appears in a third of the corpus, so\n * its absence from one page says nothing, while `reusable` appearing says\n * almost everything. Counting tokens equally lets the most common words in\n * English veto a match on the rarest. Weighting by how rare a term is in THIS\n * corpus makes the test ask what it always meant to ask — did the page cover\n * the DISTINCTIVE part of the question.\n */\nconst MIN_COVERAGE = 0.7\n\n/**\n * The relaxed coverage floor, reachable ONLY by a page that has also won\n * overwhelmingly ({@link STRONG_PAGE_MARGIN}).\n *\n * Coverage and dominance are evidence about the same thing from opposite\n * directions, and holding both as independent hard floors throws away the\n * cases where one is emphatic. \"how do I edit text directly on the canvas\"\n * covers 0.68 — a hair under the bar, and the miss is `directly`, which the\n * text-editing page never says — while winning so completely that every\n * retrieved section belongs to it and there is no rival page to divide by.\n * There is no reading of that evidence in which the text-editing page is the\n * wrong page, and escalating it pays a provider to agree.\n *\n * The floor still binds, and it binds on questions that HAVE cleared\n * {@link STRONG_PAGE_MARGIN}: \"how do I customise the error screens\" wins its\n * page by 4.1x and still escalates at 0.42, because a page that ignores that\n * much of the question is not answering it however clearly it wins. That is\n * the case this pair of numbers is calibrated to keep out.\n *\n * ⚠️ Both figures are measurements over the CURRENT `apps/docs` corpus, and\n * the corpus moves. `docs-deflection.spec.ts` asserts the first one's band\n * rather than only its verdict, so a worked example that drifts out of the\n * band fails there by name instead of going quietly wrong here.\n */\nconst RELAXED_COVERAGE = 0.6\n\n/** The margin that buys {@link RELAXED_COVERAGE}. */\nconst STRONG_PAGE_MARGIN = 3\n\n/**\n * ── The follow-up bar (AGL-2486) ──────────────────────────────────────────\n *\n * A question asked mid-thread is held to a HIGHER standard than the same\n * question asked first, and the asymmetry is the whole idea rather than\n * timidity about a new path.\n *\n * On turn one, a mediocre match costs a mediocre answer to the question that\n * was actually asked, and the closing line invites the user to ask again.\n * Mid-thread, a mediocre match means something else as well: it is EVIDENCE\n * that the words in front of us are not the whole question. A thread is where\n * ellipsis lives, so \"retrieval is unsure\" and \"the missing half is in the\n * transcript\" are the same observation seen twice. Only an emphatic match —\n * one where the page is right whatever came before — may be answered without\n * reading the conversation.\n *\n * The calibration case is the second question, \"how do I add an\n * element to my page\": top score 7.9, and the winning page beats its rival by\n * 1.80 with a coming-soon LAUNCH GUIDE, because that guide happens to say\n * \"add\", \"element\" and \"page\". As a first question that is retrieval doing\n * its honest best. As a follow-up it is a coin flip that also ignores the\n * conversation, and it escalates.\n */\nconst FOLLOW_UP_MIN_TOP_SCORE = 8\n\n/** @see FOLLOW_UP_MIN_TOP_SCORE — 1.3x is a lead; 2x is not arguable. */\nconst FOLLOW_UP_MIN_PAGE_MARGIN = 2\n\n/**\n * A follow-up must ASK something, not merely name a topic.\n *\n * Mid-thread, a bare fragment — \"the free plan?\", \"on mobile\" — is the shape\n * ellipsis takes: the verb it belongs to was in the previous turn, and the\n * fragment is a modifier of a question we cannot see. A first turn cannot be\n * elliptical in that way, which is why this cue is required only when\n * something precedes it.\n *\n * The count of tokens was tried here first and thrown away: it excluded \"how\n * do I install a plugin\" and \"how do I create a site\" — two content tokens\n * each, and both complete questions that a user asks second as readily as\n * first. Length is not what separates a question from a fragment; a verb is.\n */\nconst QUESTION_CUES =\n /\\b(how|what|what'?s|where|when|which|who|whose|whom|can|could|do|does|did|is|are|am|was|were|will|would|should|must|may|explain|show|tell|list|need|want)\\b/i\n\n/**\n * Words and shapes that make a question depend on what came before it.\n *\n * Deliberately BROAD, and the asymmetry of the costs is why: a false positive\n * here escalates a question that could have been answered from the docs — the\n * behaviour that existed for every follow-up until this change, so the worst\n * case is the status quo. A false negative answers a question nobody asked,\n * with a citation under it, in a thread where the user can see we had the\n * context and ignored it. These patterns are only ever consulted for a turn\n * WITH history; a first question may say \"that\" as much as it likes.\n */\nconst CONTEXT_DEPENDENT_PATTERNS: readonly RegExp[] = [\n // Pronouns and demonstratives standing in for a noun in the transcript.\n // \"does IT work on mobile\", \"how do I move THOSE\".\n /\\b(it|its|it'?s|they|them|their|theirs|he|him|his|she|her|hers)\\b/i,\n /\\b(that|this|these|those)\\b/i,\n // Naming an item of the previous answer by its position in it.\n /\\b(the|either|any|another|each)\\s+(other|first|second|third|last|next|same|previous|latter|former)\\b/i,\n /\\b(other|another|either)\\s+one\\b/i,\n // Opening by attaching to the previous turn rather than starting a question.\n /^\\s*(and|but|so|or|then|also|plus|what about|how about|ok(ay)?|yes|no|yeah|nope|thanks?)\\b/i,\n // Elliptical follow-ups that carry the previous turn's verb phrase over.\n /\\b(why not|instead|as well|again|neither|both)\\b/i,\n]\n\n/** Minimum characters of section text before a section counts as an answer. */\nconst MIN_SECTION_CHARS = 200\n\n/** Sections of the winning page quoted verbatim, at most. */\nconst MAX_QUOTED_SECTIONS = 2\n\n/** Total verbatim characters in one deflected answer. */\nconst MAX_ANSWER_CHARS = 2600\n\n/**\n * A request is generative when it asks for something to be WRITTEN, not\n * explained. Anchored to the start of a word and paired with the objects\n * people actually name, because \"how do I create a redirect\" is a docs\n * question and \"create a headline for my hero\" is not.\n */\nconst GENERATIVE_PATTERNS: readonly RegExp[] = [\n /\\b(write|draft|compose|generate|rewrite|reword|rephrase|summari[sz]e|translate|brainstorm|suggest)\\b/i,\n /\\b(make|build|create|give)\\s+(me|us)\\b/i,\n /\\b(come up with|help me write)\\b/i,\n]\n\n/**\n * A request is diagnostic when it describes something not working. These have\n * docs pages and must still escalate: the page lists every cause, and the\n * user has exactly one of them. Only the model, with the level-2 view context,\n * can narrow it — and when it cannot, saying so is better than quoting nine\n * causes at someone.\n */\nconst DIAGNOSTIC_PATTERNS: readonly RegExp[] = [\n /\\bwhy\\s+(is|are|isn'?t|aren'?t|does|doesn'?t|did|didn'?t|won'?t|can'?t|cannot|do)\\b/i,\n /\\b(not working|isn'?t working|doesn'?t work|stopped working|no longer works)\\b/i,\n /\\b(was|were|is|are|never)\\s+not\\s+\\w+ed\\b/i,\n /\\b(broken|failing|failed|stuck|blank|missing|502|404|500)\\b/i,\n /\\b(troubleshoot|debug|diagnose)\\b/i,\n // \"error\" needs a verb of appearance in front of it, within a clause.\n // Bare `\\berrors?\\b` reads \"how do I customise the error screens\" as a\n // support ticket — the docs page for error screens is titled with the word,\n // so the one question the pattern must not catch is the one it caught.\n /\\b(getting|got|see|seeing|shows?|showing|throws?|returns?|says?|hit)\\b[^.?!]{0,40}\\berrors?\\b/i,\n]\n\n/** Why a question was not answered from the docs. `null` reason = answered. */\nexport type DeflectionRefusal =\n | 'follow-up'\n | 'too-short'\n | 'generative'\n | 'diagnostic'\n | 'low-score'\n | 'ambiguous'\n | 'low-coverage'\n | 'thin-section'\n\nexport interface DeflectionVerdict {\n /** True when the docs answer this without a model call. */\n answered: boolean\n /** Set when `answered` is false — which gate refused. */\n refusal: DeflectionRefusal | null\n /** The composed answer; `''` unless `answered`. */\n answer: string\n /** Sections quoted in the answer; `[]` unless `answered`. */\n quoted: readonly AssistDocsSection[]\n /** The winning page's path; `''` when nothing won. */\n page: string\n /** Top section's retrieval score. 0 when nothing was retrieved. */\n topScore: number\n /** Winning page's score over the best rival page's. 0 when unscored. */\n pageMargin: number\n /** IDF-weighted share of the question the winning page carries. */\n coverage: number\n}\n\nfunction refuse(\n refusal: DeflectionRefusal,\n topScore = 0,\n pageMargin = 0,\n coverage = 0,\n): DeflectionVerdict {\n return {\n answered: false,\n refusal,\n answer: '',\n quoted: [],\n page: '',\n topScore,\n pageMargin,\n coverage,\n }\n}\n\n/**\n * Inverse document frequency for one token, over the docs corpus.\n *\n * Smoothed (`+1` inside the log's argument and on the denominator) so a token\n * absent from the index — a product name we have not documented, a typo —\n * gets a large but finite weight rather than a division by zero or an\n * infinity that would swallow every other term in the question.\n */\nfunction tokenWeight(token: string): number {\n const { frequency, sections } = docsDocumentFrequency()\n const seen = frequency.get(token) ?? 0\n return Math.log(1 + sections / (1 + seen))\n}\n\n/** The docs-site URL for one section. */\nexport function sectionUrl(section: AssistDocsSection): string {\n return `${DOCS_SITE_ORIGIN}${section.path}${section.anchor}`\n}\n\n/** `Title — Heading`, or just the title on a page intro. */\nexport function sectionLabel(section: AssistDocsSection): string {\n return section.heading ? `${section.title} — ${section.heading}` : section.title\n}\n\n/**\n * Trim verbatim text to `limit` characters on a sentence boundary, so a quote\n * never ends mid-clause. Returns the text unchanged when it already fits.\n *\n * A truncated quote is still verbatim — it is a PREFIX of the section, which\n * is what the spec's substring check asserts. Cutting on a boundary matters\n * for a different reason: a sentence stopped halfway reads as a broken\n * feature, and the user cannot tell whether the missing half contradicted the\n * visible one.\n */\nexport function trimToSentence(text: string, limit: number): string {\n const trimmed = text.trim()\n if (trimmed.length <= limit) return trimmed\n const window = trimmed.slice(0, limit)\n const lastStop = Math.max(\n window.lastIndexOf('. '),\n window.lastIndexOf('! '),\n window.lastIndexOf('? '),\n )\n // A boundary in the first third would throw most of the quote away; better\n // a hard cut with an ellipsis than an answer reduced to one sentence.\n if (lastStop > limit / 3) return window.slice(0, lastStop + 1)\n return `${window.trimEnd()}…`\n}\n\n/** Question intent, ahead of any retrieval work. */\nexport function questionIsAnswerableFromDocs(question: string): DeflectionRefusal | null {\n const tokens = new Set(tokenize(question))\n if (tokens.size < MIN_QUESTION_TOKENS) return 'too-short'\n for (const pattern of GENERATIVE_PATTERNS) {\n if (pattern.test(question)) return 'generative'\n }\n for (const pattern of DIAGNOSTIC_PATTERNS) {\n if (pattern.test(question)) return 'diagnostic'\n }\n return null\n}\n\n/**\n * Whether a question can be read WITHOUT the conversation it was asked in.\n *\n * Only consulted for a turn that has history — see\n * {@link CONTEXT_DEPENDENT_PATTERNS} for why the test errs towards \"no\", and\n * the class docstring for why the gate is no longer simply \"did anything\n * precede this\".\n *\n * Purely lexical, and that is a real limit worth naming: \"how do I do the\n * same for a blog post\" is caught by `the same`, while \"how do I change the\n * colour\" after a paragraph about buttons is not — nothing in those words\n * says which colour. What saves that case is not this function but the raised\n * evidence bar behind it, which such a question does not clear. The two gates\n * are one argument in two halves: this one reads the question, that one reads\n * the retrieval, and a follow-up must pass both.\n */\nexport function questionStandsAlone(question: string): boolean {\n if (!QUESTION_CUES.test(question)) return false\n for (const pattern of CONTEXT_DEPENDENT_PATTERNS) {\n if (pattern.test(question)) return false\n }\n return true\n}\n\n/**\n * Decide whether the retrieved sections answer the question on their own, and\n * compose the answer when they do.\n *\n * `hasHistory` is passed rather than derived because the caller holds the\n * clamped history and this module must not grow an opinion about how history\n * is budgeted. It is not a hard gate any more (AGL-2486): a turn with history\n * must additionally stand on its own words and clear the raised `FOLLOW_UP_*`\n * bar, and escalates when it does not.\n */\nexport function deflectToDocs(\n question: string,\n scored: readonly ScoredSection[],\n hasHistory: boolean,\n): DeflectionVerdict {\n if (hasHistory && !questionStandsAlone(question)) return refuse('follow-up')\n const intent = questionIsAnswerableFromDocs(question)\n if (intent) return refuse(intent)\n if (!scored.length) return refuse('low-score')\n\n const minTopScore = hasHistory ? FOLLOW_UP_MIN_TOP_SCORE : MIN_TOP_SCORE\n const minPageMargin = hasHistory ? FOLLOW_UP_MIN_PAGE_MARGIN : MIN_PAGE_MARGIN\n\n const top = scored[0]\n const topScore = top.score\n if (!(topScore >= minTopScore)) return refuse('low-score', topScore)\n\n // Score by PAGE. Sections of one page agreeing is the signal; treating them\n // as rivals is how a strong, unambiguous match reads as a tie.\n const perPage = new Map<string, number>()\n for (const entry of scored) {\n perPage.set(entry.section.path, (perPage.get(entry.section.path) ?? 0) + entry.score)\n }\n // The winning page is the highest-scoring PAGE, not the home of the\n // highest-scoring section — three mid-scoring sections of one page can beat\n // one strong section elsewhere, and when they do, that page is the answer.\n let winner = ''\n let winnerScore = 0\n let rivalScore = 0\n for (const [path, score] of perPage) {\n if (score > winnerScore) {\n rivalScore = winnerScore\n winner = path\n winnerScore = score\n } else if (score > rivalScore) {\n rivalScore = score\n }\n }\n // No rival is not a tie — it is the cleanest possible result, one page and\n // nothing else. `Infinity` would be honest but propagates badly through the\n // telemetry, so a lone winner reports its own score as the margin.\n const pageMargin = rivalScore > 0 ? winnerScore / rivalScore : winnerScore\n if (!(pageMargin >= minPageMargin)) return refuse('ambiguous', topScore, pageMargin)\n\n const pageSections = scored.filter((entry) => entry.section.path === winner)\n const pageTokens = new Set<string>()\n for (const entry of pageSections) {\n for (const token of tokenize(entry.section.title)) pageTokens.add(token)\n for (const token of tokenize(entry.section.heading)) pageTokens.add(token)\n for (const token of tokenize(entry.section.text)) pageTokens.add(token)\n }\n const questionTokens = [...new Set(tokenize(question))]\n let wanted = 0\n let covered = 0\n for (const token of questionTokens) {\n const weight = tokenWeight(token)\n wanted += weight\n if (pageTokens.has(token)) covered += weight\n }\n const coverage = wanted > 0 ? covered / wanted : 0\n // The relaxed floor is a FIRST-TURN allowance. It exists because coverage\n // and dominance are evidence about the same thing, so an emphatic winner\n // may carry a coverage miss — but mid-thread a coverage miss has a second\n // reading: the part of the question the page ignored may be the part the\n // conversation supplied. Turn one cannot mean that; a follow-up can, so it\n // pays full coverage.\n const coveredEnough =\n coverage >= MIN_COVERAGE ||\n (!hasHistory && coverage >= RELAXED_COVERAGE && pageMargin >= STRONG_PAGE_MARGIN)\n if (!coveredEnough) {\n return refuse('low-coverage', topScore, pageMargin, coverage)\n }\n\n const usable = pageSections.filter(\n (entry) => entry.section.text.trim().length >= MIN_SECTION_CHARS,\n )\n if (!usable.length) return refuse('thin-section', topScore, pageMargin, coverage)\n\n const quoted = usable.slice(0, MAX_QUOTED_SECTIONS).map((entry) => entry.section)\n return {\n answered: true,\n refusal: null,\n answer: composeDocsAnswer(quoted),\n quoted,\n page: winner,\n topScore,\n pageMargin,\n coverage,\n }\n}\n\n/**\n * The deflected answer: template + verbatim docs + real links, and nothing\n * else. Kept exported so the spec can assert the reconstruction property\n * against it directly rather than through the route.\n *\n * ⚠️ COMPOSED FOR A SURFACE THAT DOES NOT RENDER MARKDOWN. The Assist panel\n * says so in its own docstring — `renderAssistText` turns `[label](url)` and\n * bare URLs into links and renders everything else literally, under\n * `whiteSpace: 'pre-wrap'`. That is a deliberate phase-1 decision, not a gap.\n *\n * This template shipped once with the heading wrapped in `**…**`, and the * besigner drawer duly showed `**Drag-and-drop hierarchy — Moving an element\n * without dragging**`, asterisks and all. The lesson is not \"escape the\n * asterisks\" — it is that the composer has to know what renders it.\n *\n * So the heading is a bare `[label](url)` on its own line — a LINK, which is\n * the one markup the panel speaks, and which is why the title in the * screenshot was correctly clickable even while the asterisks around it were\n * not. Everything else is carried by NEWLINES, which `pre-wrap` renders,\n * rather than by markup, which it does not.\n *\n * The link has to live in the TEXT, and that is still true now that the\n * `docs` array on the `done` event IS rendered (AGL-2486, `AssistSources`).\n * It was tempting to treat that array as the structural home for the citation\n * even when nothing rendered it; it is still the wrong home, for a different\n * reason. `docs` carries every section RETRIEVED, whereas this template\n * quotes only the sections it actually used — so the array is a superset, and\n * a citation moved there would credit pages this answer never drew a word\n * from. `AssistSources` drops any url already linked in the text, which means\n * a deflected answer renders exactly as it does below and gains no duplicate\n * list underneath.\n *\n * Three specs in `docs-deflection.spec.ts` hold the line — no emphasis\n * markers, no heading markers, and a link still present.\n *\n * The closing line is not decoration. A user who reads this and finds it did\n * not answer them needs to know that asking again in different words reaches\n * something else — otherwise the cheap path looks like the assistant simply\n * being worse, and the next thing they do is stop using it.\n */\nexport function composeDocsAnswer(sections: readonly AssistDocsSection[]): string {\n const parts: string[] = []\n let budget = MAX_ANSWER_CHARS\n for (const section of sections) {\n if (budget <= MIN_SECTION_CHARS) break\n const quote = trimToSentence(section.text, budget)\n budget -= quote.length\n parts.push(`[${sectionLabel(section)}](${sectionUrl(section)})\\n${quote}`)\n }\n parts.push(\n 'That is straight from the documentation — the headings above link to the full page. If it did not cover what you meant, ask again with more detail and I will work through it with you.',\n )\n return parts.join('\\n\\n')\n}\n\n/** Closest-pages links offered when nothing could be answered outright. */\nconst MAX_LINKED_SECTIONS = 4\n\n/**\n * The graceful degrade: the closest pages we found, and an honest sentence\n * saying why that is all there is (AGL-2486).\n *\n * ## Why this exists\n *\n * A deployment with no AI provider key — which includes every self-hosted\n * one on the day it comes up, and Aglyn's own production today — can answer\n * only what retrieval is confident about. A bare 501 for everything else\n * reaches the panel as \"Assist is not configured on this deployment\" — and it\n * can arrive on the SECOND question of a thread whose first question was just\n * answered in full. A capability refusal that lands after a working answer\n * reads as a fault, not a limit.\n *\n * The self-host charter says every Aglyn-operated dependency must be\n * configurable AND degrade cleanly. \"Degrades cleanly\" cannot mean \"answers\n * one question per thread and then refuses\" — a keyless deployment still has\n * the entire documentation corpus and a retrieval index over it, so the floor\n * is the best pages we found, not nothing.\n *\n * ## What it may and may not say\n *\n * The no-fabrication rule applies here exactly as it does to a deflected\n * answer, and is tighter in one respect: these pages did NOT clear the\n * confidence bar, so this text must not claim they answer the question. It\n * says they are the closest, which is true by construction — they are the\n * top of the retrieval ranking — and every word around them is a fixed\n * template plus a real section label and URL.\n *\n * It also must not name an env var. A user who wanted to read `501` would\n * have opened the network tab; the operator-facing detail stays in the API\n * error body, where an operator looks. This is the plain-English half.\n */\nexport function composeDocsLinksAnswer(\n sections: readonly AssistDocsSection[],\n): string {\n const links = sections\n .slice(0, MAX_LINKED_SECTIONS)\n .map((section) => `[${sectionLabel(section)}](${sectionUrl(section)})`)\n if (!links.length) return ''\n return [\n 'I could not find one page in the documentation that clearly answers that, and the part of me that talks a question through with you is not switched on for this deployment yet — an administrator has to finish setting it up.',\n 'These are the closest pages I found:',\n links.join('\\n'),\n 'If none of them cover it, asking again in different words often lands somewhere better.',\n ].join('\\n\\n')\n}\n"],"names":["DOCS_SITE_ORIGIN","docsDocumentFrequency","tokenize","MIN_QUESTION_TOKENS","MIN_TOP_SCORE","MIN_PAGE_MARGIN","MIN_COVERAGE","RELAXED_COVERAGE","STRONG_PAGE_MARGIN","FOLLOW_UP_MIN_TOP_SCORE","FOLLOW_UP_MIN_PAGE_MARGIN","QUESTION_CUES","CONTEXT_DEPENDENT_PATTERNS","MIN_SECTION_CHARS","MAX_QUOTED_SECTIONS","MAX_ANSWER_CHARS","GENERATIVE_PATTERNS","DIAGNOSTIC_PATTERNS","refuse","refusal","topScore","pageMargin","coverage","answered","answer","quoted","page","tokenWeight","token","frequency","sections","seen","get","Math","log","sectionUrl","section","path","anchor","sectionLabel","heading","title","trimToSentence","text","limit","trimmed","trim","length","window","slice","lastStop","max","lastIndexOf","trimEnd","questionIsAnswerableFromDocs","question","tokens","Set","size","pattern","test","questionStandsAlone","deflectToDocs","scored","hasHistory","intent","minTopScore","minPageMargin","top","score","perPage","Map","entry","set","winner","winnerScore","rivalScore","pageSections","filter","pageTokens","add","questionTokens","wanted","covered","weight","has","coveredEnough","usable","map","composeDocsAnswer","parts","budget","quote","push","join","MAX_LINKED_SECTIONS","composeDocsLinksAnswer","links"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAGD,SACEA,gBAAgB,EAChBC,qBAAqB,EACrBC,QAAQ,QAEH,sBAAkB;AAEzB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0FC,GAED;;;;;;;;;;;;;;CAcC,GACD,MAAMC,sBAAsB;AAE5B;;;;;;;;;;;;;CAaC,GACD,MAAMC,gBAAgB;AAEtB;;;;;;;;;;CAUC,GACD,MAAMC,kBAAkB;AAExB;;;;;;;;;;;;;;;;;;CAkBC,GACD,MAAMC,eAAe;AAErB;;;;;;;;;;;;;;;;;;;;;;;CAuBC,GACD,MAAMC,mBAAmB;AAEzB,mDAAmD,GACnD,MAAMC,qBAAqB;AAE3B;;;;;;;;;;;;;;;;;;;;;;CAsBC,GACD,MAAMC,0BAA0B;AAEhC,uEAAuE,GACvE,MAAMC,4BAA4B;AAElC;;;;;;;;;;;;;CAaC,GACD,MAAMC,gBACJ;AAEF;;;;;;;;;;CAUC,GACD,MAAMC,6BAAgD;IACpD,wEAAwE;IACxE,mDAAmD;IACnD;IACA;IACA,+DAA+D;IAC/D;IACA;IACA,6EAA6E;IAC7E;IACA,yEAAyE;IACzE;CACD;AAED,6EAA6E,GAC7E,MAAMC,oBAAoB;AAE1B,2DAA2D,GAC3D,MAAMC,sBAAsB;AAE5B,uDAAuD,GACvD,MAAMC,mBAAmB;AAEzB;;;;;CAKC,GACD,MAAMC,sBAAyC;IAC7C;IACA;IACA;CACD;AAED;;;;;;CAMC,GACD,MAAMC,sBAAyC;IAC7C;IACA;IACA;IACA;IACA;IACA,sEAAsE;IACtE,uEAAuE;IACvE,4EAA4E;IAC5E,uEAAuE;IACvE;CACD;AAgCD,SAASC,OACPC,OAA0B,EAC1BC,WAAW,CAAC,EACZC,aAAa,CAAC,EACdC,WAAW,CAAC;IAEZ,OAAO;QACLC,UAAU;QACVJ;QACAK,QAAQ;QACRC,QAAQ,EAAE;QACVC,MAAM;QACNN;QACAC;QACAC;IACF;AACF;AAEA;;;;;;;CAOC,GACD,SAASK,YAAYC,KAAa;QAEnBC;IADb,MAAM,EAAEA,SAAS,EAAEC,QAAQ,EAAE,GAAG7B;IAChC,MAAM8B,QAAOF,iBAAAA,UAAUG,GAAG,CAACJ,kBAAdC,iBAAwB;IACrC,OAAOI,KAAKC,GAAG,CAAC,IAAIJ,WAAY,CAAA,IAAIC,IAAG;AACzC;AAEA,uCAAuC,GACvC,OAAO,SAASI,WAAWC,OAA0B;IACnD,OAAO,GAAGpC,mBAAmBoC,QAAQC,IAAI,GAAGD,QAAQE,MAAM,EAAE;AAC9D;AAEA,0DAA0D,GAC1D,OAAO,SAASC,aAAaH,OAA0B;IACrD,OAAOA,QAAQI,OAAO,GAAG,GAAGJ,QAAQK,KAAK,CAAC,GAAG,EAAEL,QAAQI,OAAO,EAAE,GAAGJ,QAAQK,KAAK;AAClF;AAEA;;;;;;;;;CASC,GACD,OAAO,SAASC,eAAeC,IAAY,EAAEC,KAAa;IACxD,MAAMC,UAAUF,KAAKG,IAAI;IACzB,IAAID,QAAQE,MAAM,IAAIH,OAAO,OAAOC;IACpC,MAAMG,SAASH,QAAQI,KAAK,CAAC,GAAGL;IAChC,MAAMM,WAAWjB,KAAKkB,GAAG,CACvBH,OAAOI,WAAW,CAAC,OACnBJ,OAAOI,WAAW,CAAC,OACnBJ,OAAOI,WAAW,CAAC;IAErB,2EAA2E;IAC3E,sEAAsE;IACtE,IAAIF,WAAWN,QAAQ,GAAG,OAAOI,OAAOC,KAAK,CAAC,GAAGC,WAAW;IAC5D,OAAO,GAAGF,OAAOK,OAAO,GAAG,CAAC,CAAC;AAC/B;AAEA,kDAAkD,GAClD,OAAO,SAASC,6BAA6BC,QAAgB;IAC3D,MAAMC,SAAS,IAAIC,IAAIvD,SAASqD;IAChC,IAAIC,OAAOE,IAAI,GAAGvD,qBAAqB,OAAO;IAC9C,KAAK,MAAMwD,WAAW3C,oBAAqB;QACzC,IAAI2C,QAAQC,IAAI,CAACL,WAAW,OAAO;IACrC;IACA,KAAK,MAAMI,WAAW1C,oBAAqB;QACzC,IAAI0C,QAAQC,IAAI,CAACL,WAAW,OAAO;IACrC;IACA,OAAO;AACT;AAEA;;;;;;;;;;;;;;;CAeC,GACD,OAAO,SAASM,oBAAoBN,QAAgB;IAClD,IAAI,CAAC5C,cAAciD,IAAI,CAACL,WAAW,OAAO;IAC1C,KAAK,MAAMI,WAAW/C,2BAA4B;QAChD,IAAI+C,QAAQC,IAAI,CAACL,WAAW,OAAO;IACrC;IACA,OAAO;AACT;AAEA;;;;;;;;;CASC,GACD,OAAO,SAASO,cACdP,QAAgB,EAChBQ,MAAgC,EAChCC,UAAmB;IAEnB,IAAIA,cAAc,CAACH,oBAAoBN,WAAW,OAAOrC,OAAO;IAChE,MAAM+C,SAASX,6BAA6BC;IAC5C,IAAIU,QAAQ,OAAO/C,OAAO+C;IAC1B,IAAI,CAACF,OAAOhB,MAAM,EAAE,OAAO7B,OAAO;IAElC,MAAMgD,cAAcF,aAAavD,0BAA0BL;IAC3D,MAAM+D,gBAAgBH,aAAatD,4BAA4BL;IAE/D,MAAM+D,MAAML,MAAM,CAAC,EAAE;IACrB,MAAM3C,WAAWgD,IAAIC,KAAK;IAC1B,IAAI,CAAEjD,CAAAA,YAAY8C,WAAU,GAAI,OAAOhD,OAAO,aAAaE;IAE3D,4EAA4E;IAC5E,+DAA+D;IAC/D,MAAMkD,UAAU,IAAIC;IACpB,KAAK,MAAMC,SAAST,OAAQ;YACOO;QAAjCA,QAAQG,GAAG,CAACD,MAAMpC,OAAO,CAACC,IAAI,EAAE,EAACiC,eAAAA,QAAQtC,GAAG,CAACwC,MAAMpC,OAAO,CAACC,IAAI,aAA9BiC,eAAmC,KAAKE,MAAMH,KAAK;IACtF;IACA,oEAAoE;IACpE,4EAA4E;IAC5E,2EAA2E;IAC3E,IAAIK,SAAS;IACb,IAAIC,cAAc;IAClB,IAAIC,aAAa;IACjB,KAAK,MAAM,CAACvC,MAAMgC,MAAM,IAAIC,QAAS;QACnC,IAAID,QAAQM,aAAa;YACvBC,aAAaD;YACbD,SAASrC;YACTsC,cAAcN;QAChB,OAAO,IAAIA,QAAQO,YAAY;YAC7BA,aAAaP;QACf;IACF;IACA,2EAA2E;IAC3E,4EAA4E;IAC5E,mEAAmE;IACnE,MAAMhD,aAAauD,aAAa,IAAID,cAAcC,aAAaD;IAC/D,IAAI,CAAEtD,CAAAA,cAAc8C,aAAY,GAAI,OAAOjD,OAAO,aAAaE,UAAUC;IAEzE,MAAMwD,eAAed,OAAOe,MAAM,CAAC,CAACN,QAAUA,MAAMpC,OAAO,CAACC,IAAI,KAAKqC;IACrE,MAAMK,aAAa,IAAItB;IACvB,KAAK,MAAMe,SAASK,aAAc;QAChC,KAAK,MAAMjD,SAAS1B,SAASsE,MAAMpC,OAAO,CAACK,KAAK,EAAGsC,WAAWC,GAAG,CAACpD;QAClE,KAAK,MAAMA,SAAS1B,SAASsE,MAAMpC,OAAO,CAACI,OAAO,EAAGuC,WAAWC,GAAG,CAACpD;QACpE,KAAK,MAAMA,SAAS1B,SAASsE,MAAMpC,OAAO,CAACO,IAAI,EAAGoC,WAAWC,GAAG,CAACpD;IACnE;IACA,MAAMqD,iBAAiB;WAAI,IAAIxB,IAAIvD,SAASqD;KAAW;IACvD,IAAI2B,SAAS;IACb,IAAIC,UAAU;IACd,KAAK,MAAMvD,SAASqD,eAAgB;QAClC,MAAMG,SAASzD,YAAYC;QAC3BsD,UAAUE;QACV,IAAIL,WAAWM,GAAG,CAACzD,QAAQuD,WAAWC;IACxC;IACA,MAAM9D,WAAW4D,SAAS,IAAIC,UAAUD,SAAS;IACjD,0EAA0E;IAC1E,yEAAyE;IACzE,0EAA0E;IAC1E,yEAAyE;IACzE,2EAA2E;IAC3E,sBAAsB;IACtB,MAAMI,gBACJhE,YAAYhB,gBACX,CAAC0D,cAAc1C,YAAYf,oBAAoBc,cAAcb;IAChE,IAAI,CAAC8E,eAAe;QAClB,OAAOpE,OAAO,gBAAgBE,UAAUC,YAAYC;IACtD;IAEA,MAAMiE,SAASV,aAAaC,MAAM,CAChC,CAACN,QAAUA,MAAMpC,OAAO,CAACO,IAAI,CAACG,IAAI,GAAGC,MAAM,IAAIlC;IAEjD,IAAI,CAAC0E,OAAOxC,MAAM,EAAE,OAAO7B,OAAO,gBAAgBE,UAAUC,YAAYC;IAExE,MAAMG,SAAS8D,OAAOtC,KAAK,CAAC,GAAGnC,qBAAqB0E,GAAG,CAAC,CAAChB,QAAUA,MAAMpC,OAAO;IAChF,OAAO;QACLb,UAAU;QACVJ,SAAS;QACTK,QAAQiE,kBAAkBhE;QAC1BA;QACAC,MAAMgD;QACNtD;QACAC;QACAC;IACF;AACF;AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqCC,GACD,OAAO,SAASmE,kBAAkB3D,QAAsC;IACtE,MAAM4D,QAAkB,EAAE;IAC1B,IAAIC,SAAS5E;IACb,KAAK,MAAMqB,WAAWN,SAAU;QAC9B,IAAI6D,UAAU9E,mBAAmB;QACjC,MAAM+E,QAAQlD,eAAeN,QAAQO,IAAI,EAAEgD;QAC3CA,UAAUC,MAAM7C,MAAM;QACtB2C,MAAMG,IAAI,CAAC,CAAC,CAAC,EAAEtD,aAAaH,SAAS,EAAE,EAAED,WAAWC,SAAS,GAAG,EAAEwD,OAAO;IAC3E;IACAF,MAAMG,IAAI,CACR;IAEF,OAAOH,MAAMI,IAAI,CAAC;AACpB;AAEA,yEAAyE,GACzE,MAAMC,sBAAsB;AAE5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgCC,GACD,OAAO,SAASC,uBACdlE,QAAsC;IAEtC,MAAMmE,QAAQnE,SACXmB,KAAK,CAAC,GAAG8C,qBACTP,GAAG,CAAC,CAACpD,UAAY,CAAC,CAAC,EAAEG,aAAaH,SAAS,EAAE,EAAED,WAAWC,SAAS,CAAC,CAAC;IACxE,IAAI,CAAC6D,MAAMlD,MAAM,EAAE,OAAO;IAC1B,OAAO;QACL;QACA;QACAkD,MAAMH,IAAI,CAAC;QACX;KACD,CAACA,IAAI,CAAC;AACT"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../libs/aglyn/src/lib/app-utils/docs-deflection.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { DocsSection } from './docs-index.generated'\nimport {\n DOCS_SITE_ORIGIN,\n docsDocumentFrequency,\n tokenize,\n type ScoredSection,\n} from './docs-retrieval'\n\n/**\n * Retrieval-first answering for Aglyn Assist (AGL-2486) — the deflection gate.\n *\n * Most assist traffic is \"how do I X\", and the answer to \"how do I X\" is\n * already written down in `apps/docs/docs`. Sending that question to a model\n * so the model can read the docs section back to the user pays provider money\n * to reformat prose we wrote ourselves. This module decides when retrieval is\n * confident enough to hand the docs straight over, and composes the answer\n * when it is. Escalation to the model is what happens the rest of the time —\n * it is the fallback, not the default.\n *\n * ## The one rule: never fabricate\n *\n * A deflected answer contains exactly two kinds of text:\n *\n * 1. Fixed template strings from this file, which say nothing about the\n * product — they name the page and introduce the quote.\n * 2. Section text copied VERBATIM out of the docs index, with the URL of\n * the page it came from.\n *\n * There is no summarisation, no paraphrase and no stitching of adjacent\n * sections into a claim neither one makes. The spec asserts it by\n * RECONSTRUCTION — \"never fabricate — every word is template or verbatim\n * docs\" — stripping the template from a composed answer and requiring what is\n * left to be a prefix of a real section's `text`. That property is the whole\n * safety argument, because a wrong retrieval answer is worse than an\n * escalation — it is confidently wrong prose delivered to a paying customer\n * with a citation under it, which is the shape people trust most.\n *\n * ## What \"confident\" means\n *\n * Seven conditions, ALL of which must hold. Any one failing escalates; there\n * is no partial-credit path where a weak match produces a hedged answer,\n * because a hedged wrong answer is still a wrong answer and it has already\n * cost the user the click.\n *\n * 1. **The question stands on its own.** A follow-up is usually not\n * self-contained: \"does that work on the free plan?\" retrieves the\n * billing pages beautifully and answers a question nobody asked. The\n * conversation is the missing half and only the model has it.\n *\n * The gate is NOT \"no prior turn\" (AGL-2486). Not every follow-up leans\n * on the transcript: the second question in a thread is very often a\n * fresh, complete question that happens to be asked second. Refusing all\n * of them means a thread answers its first question from the docs and\n * then escalates forever — and on a deployment with no AI provider\n * key that reads as \"Aglyn Assist is not configured\",\n * one question in, to a user who just watched it work. A product that\n * answers exactly once per thread is worse than one that never answers,\n * because the second refusal looks like a fault rather than a limit.\n *\n * So the gate now asks whether THIS question stands alone, and holds a\n * raised bar when it does — see {@link questionStandsAlone} and the\n * `FOLLOW_UP_*` constants.\n * 2. **Enough question.** At least {@link MIN_QUESTION_TOKENS} distinct\n * content tokens after stop-word removal. Below that there is not enough\n * of a question to be confident ABOUT.\n * 3. **Not a generative request.** \"write me a hero headline\" is the copy\n * assistant's job, not a docs lookup, and no docs page answers it.\n * 4. **Not a diagnostic.** \"why isn't my domain verifying\" has a\n * troubleshooting page, and dumping that page at someone whose actual\n * problem is one of nine listed causes is exactly the confidently-wrong\n * failure. Diagnostics need the workspace's own state, which is the\n * level-2 context only the model gets.\n * 5. **Absolute score.** The top section scores at least\n * {@link MIN_TOP_SCORE}.\n * 6. **Page dominance.** The winning page beats the best RIVAL page by at\n * least {@link MIN_PAGE_MARGIN}. Measured against the runner-up page\n * rather than as a share of the whole retrieved set, because the set is\n * six sections wide: a page that is unambiguously right still holds a\n * minority of a six-way split the moment three neighbouring pages use the\n * same nouns, and a share test reads that dilution as doubt. And the\n * comparison is page-to-page, not section-to-section — sections of ONE\n * page scoring alike is agreement, which a section margin scores as a tie.\n * 7. **Substance.** The winning section carries at least\n * {@link MIN_SECTION_CHARS} of text. A three-word stub under a heading is\n * a pointer, not an answer.\n *\n * Below the bar the request proceeds exactly as it did before this module\n * existed: the same sections are still retrieved and still ground the model's\n * prompt. Deflection removes model calls; it never removes grounding.\n *\n * ## The thresholds are measured, not guessed\n *\n * `docs-deflection.spec.ts` carries a fixed set of realistic questions —\n * positives written in user vocabulary rather than lifted from docs headings,\n * and negatives that MUST escalate — and asserts a floor on the deflection\n * rate and a ceiling of zero on the negatives. Retuning a constant here\n * without rerunning that spec is how a threshold ends up set by whoever\n * touched it last.\n */\n\n/**\n * Distinct content tokens a question needs before it can be answered.\n *\n * Two, not three, and the difference is most of the corpus: \"how do I install\n * a plugin\", \"what are dataset relations\" and \"how do I cancel my\n * subscription\" all reduce to exactly two content tokens once the stop words\n * go, and every one of them is a plain docs lookup. Three excluded them all.\n *\n * Two is safe here only because the gates below are not a checklist a weak\n * question can pass by being short: a two-token question must have BOTH\n * tokens carried by the winning page (the IDF weighting cannot rescue it —\n * there is nothing generic to discount), and the page must still clear the\n * score floor and out-score its rival. \"is my site down\" has two tokens and\n * fails on dominance, not on length.\n */\nconst MIN_QUESTION_TOKENS = 2\n\n/**\n * Absolute floor on the winning section's retrieval score.\n *\n * The scorer gives 2.5 for a title hit, 2 for a heading hit and up to ~2.2 per\n * body term — about 6.7 for one term landing everywhere at once. 5 is\n * therefore roughly \"two question terms landed and at least one of them hit\n * the page's own statement of topic\". Below that the match is incidental\n * vocabulary rather than a page about the thing.\n *\n * Measured down from 6, which cost five ordinary lookups scoring 4.4–5.9\n * (\"how do I cancel my subscription\", \"how do I set up sso for my team\") and\n * bought nothing: the negative set does not move between the two values,\n * because what actually stops those is coverage and dominance, not the floor.\n */\nconst MIN_TOP_SCORE = 5\n\n/**\n * How far the winning page must out-score the best rival page.\n *\n * 1.3x — the winner needs a visible lead, not a photo finish. Two pages\n * within 30% of each other on the same question means retrieval genuinely\n * does not know which one the user meant, and picking is a coin flip dressed\n * up as an answer.\n *\n * A question that retrieves only ONE page has no rival and passes this gate\n * outright; the score floor and coverage are what bound it there.\n */\nconst MIN_PAGE_MARGIN = 1.3\n\n/**\n * Weighted fraction of the question the winning page must actually contain.\n * Coverage and score answer different questions: score says the page matched\n * strongly, coverage says the page did not IGNORE part of what was asked.\n * \"how do I password protect a screen on the free plan\" scores highly on the\n * site-protection page while silently dropping \"free plan\", and the answer\n * that comes back is then wrong in the one way that matters.\n *\n * ⚠️ WEIGHTED BY IDF, and an unweighted version of this test is why nine\n * perfectly ordinary questions escalated in the first measurement. \"how do I\n * make a reusable component\" covers `reusable` and `component` and misses\n * `make`, because the page says \"create\" — 2/3, under the bar, escalated. The\n * miss carried no information: `make` appears in a third of the corpus, so\n * its absence from one page says nothing, while `reusable` appearing says\n * almost everything. Counting tokens equally lets the most common words in\n * English veto a match on the rarest. Weighting by how rare a term is in THIS\n * corpus makes the test ask what it always meant to ask — did the page cover\n * the DISTINCTIVE part of the question.\n */\nconst MIN_COVERAGE = 0.7\n\n/**\n * The relaxed coverage floor, reachable ONLY by a page that has also won\n * overwhelmingly ({@link STRONG_PAGE_MARGIN}).\n *\n * Coverage and dominance are evidence about the same thing from opposite\n * directions, and holding both as independent hard floors throws away the\n * cases where one is emphatic. \"how do I edit text directly on the canvas\"\n * covers 0.68 — a hair under the bar, and the miss is `directly`, which the\n * text-editing page never says — while winning so completely that every\n * retrieved section belongs to it and there is no rival page to divide by.\n * There is no reading of that evidence in which the text-editing page is the\n * wrong page, and escalating it pays a provider to agree.\n *\n * The floor still binds, and it binds on questions that HAVE cleared\n * {@link STRONG_PAGE_MARGIN}: \"how do I customise the error screens\" wins its\n * page by 4.1x and still escalates at 0.42, because a page that ignores that\n * much of the question is not answering it however clearly it wins. That is\n * the case this pair of numbers is calibrated to keep out.\n *\n * ⚠️ Both figures are measurements over the CURRENT `apps/docs` corpus, and\n * the corpus moves. `docs-deflection.spec.ts` asserts the first one's band\n * rather than only its verdict, so a worked example that drifts out of the\n * band fails there by name instead of going quietly wrong here.\n */\nconst RELAXED_COVERAGE = 0.6\n\n/** The margin that buys {@link RELAXED_COVERAGE}. */\nconst STRONG_PAGE_MARGIN = 3\n\n/**\n * ── The follow-up bar (AGL-2486) ──────────────────────────────────────────\n *\n * A question asked mid-thread is held to a HIGHER standard than the same\n * question asked first, and the asymmetry is the whole idea rather than\n * timidity about a new path.\n *\n * On turn one, a mediocre match costs a mediocre answer to the question that\n * was actually asked, and the closing line invites the user to ask again.\n * Mid-thread, a mediocre match means something else as well: it is EVIDENCE\n * that the words in front of us are not the whole question. A thread is where\n * ellipsis lives, so \"retrieval is unsure\" and \"the missing half is in the\n * transcript\" are the same observation seen twice. Only an emphatic match —\n * one where the page is right whatever came before — may be answered without\n * reading the conversation.\n *\n * The calibration case is the second question, \"how do I add an\n * element to my page\": top score 7.9, and the winning page beats its rival by\n * 1.80 with a coming-soon LAUNCH GUIDE, because that guide happens to say\n * \"add\", \"element\" and \"page\". As a first question that is retrieval doing\n * its honest best. As a follow-up it is a coin flip that also ignores the\n * conversation, and it escalates.\n */\nconst FOLLOW_UP_MIN_TOP_SCORE = 8\n\n/** @see FOLLOW_UP_MIN_TOP_SCORE — 1.3x is a lead; 2x is not arguable. */\nconst FOLLOW_UP_MIN_PAGE_MARGIN = 2\n\n/**\n * A follow-up must ASK something, not merely name a topic.\n *\n * Mid-thread, a bare fragment — \"the free plan?\", \"on mobile\" — is the shape\n * ellipsis takes: the verb it belongs to was in the previous turn, and the\n * fragment is a modifier of a question we cannot see. A first turn cannot be\n * elliptical in that way, which is why this cue is required only when\n * something precedes it.\n *\n * The count of tokens was tried here first and thrown away: it excluded \"how\n * do I install a plugin\" and \"how do I create a site\" — two content tokens\n * each, and both complete questions that a user asks second as readily as\n * first. Length is not what separates a question from a fragment; a verb is.\n */\nconst QUESTION_CUES =\n /\\b(how|what|what'?s|where|when|which|who|whose|whom|can|could|do|does|did|is|are|am|was|were|will|would|should|must|may|explain|show|tell|list|need|want)\\b/i\n\n/**\n * Words and shapes that make a question depend on what came before it.\n *\n * Deliberately BROAD, and the asymmetry of the costs is why: a false positive\n * here escalates a question that could have been answered from the docs — the\n * behaviour that existed for every follow-up until this change, so the worst\n * case is the status quo. A false negative answers a question nobody asked,\n * with a citation under it, in a thread where the user can see we had the\n * context and ignored it. These patterns are only ever consulted for a turn\n * WITH history; a first question may say \"that\" as much as it likes.\n */\nconst CONTEXT_DEPENDENT_PATTERNS: readonly RegExp[] = [\n // Pronouns and demonstratives standing in for a noun in the transcript.\n // \"does IT work on mobile\", \"how do I move THOSE\".\n /\\b(it|its|it'?s|they|them|their|theirs|he|him|his|she|her|hers)\\b/i,\n /\\b(that|this|these|those)\\b/i,\n // Naming an item of the previous answer by its position in it.\n /\\b(the|either|any|another|each)\\s+(other|first|second|third|last|next|same|previous|latter|former)\\b/i,\n /\\b(other|another|either)\\s+one\\b/i,\n // Opening by attaching to the previous turn rather than starting a question.\n /^\\s*(and|but|so|or|then|also|plus|what about|how about|ok(ay)?|yes|no|yeah|nope|thanks?)\\b/i,\n // Elliptical follow-ups that carry the previous turn's verb phrase over.\n /\\b(why not|instead|as well|again|neither|both)\\b/i,\n]\n\n/** Minimum characters of section text before a section counts as an answer. */\nconst MIN_SECTION_CHARS = 200\n\n/** Sections of the winning page quoted verbatim, at most. */\nconst MAX_QUOTED_SECTIONS = 2\n\n/** Total verbatim characters in one deflected answer. */\nconst MAX_ANSWER_CHARS = 2600\n\n/**\n * A request is generative when it asks for something to be WRITTEN, not\n * explained. Anchored to the start of a word and paired with the objects\n * people actually name, because \"how do I create a redirect\" is a docs\n * question and \"create a headline for my hero\" is not.\n */\nconst GENERATIVE_PATTERNS: readonly RegExp[] = [\n /\\b(write|draft|compose|generate|rewrite|reword|rephrase|summari[sz]e|translate|brainstorm|suggest)\\b/i,\n /\\b(make|build|create|give)\\s+(me|us)\\b/i,\n /\\b(come up with|help me write)\\b/i,\n]\n\n/**\n * A request is diagnostic when it describes something not working. These have\n * docs pages and must still escalate: the page lists every cause, and the\n * user has exactly one of them. Only the model, with the level-2 view context,\n * can narrow it — and when it cannot, saying so is better than quoting nine\n * causes at someone.\n */\nconst DIAGNOSTIC_PATTERNS: readonly RegExp[] = [\n /\\bwhy\\s+(is|are|isn'?t|aren'?t|does|doesn'?t|did|didn'?t|won'?t|can'?t|cannot|do)\\b/i,\n /\\b(not working|isn'?t working|doesn'?t work|stopped working|no longer works)\\b/i,\n /\\b(was|were|is|are|never)\\s+not\\s+\\w+ed\\b/i,\n /\\b(broken|failing|failed|stuck|blank|missing|502|404|500)\\b/i,\n /\\b(troubleshoot|debug|diagnose)\\b/i,\n // \"error\" needs a verb of appearance in front of it, within a clause.\n // Bare `\\berrors?\\b` reads \"how do I customise the error screens\" as a\n // support ticket — the docs page for error screens is titled with the word,\n // so the one question the pattern must not catch is the one it caught.\n /\\b(getting|got|see|seeing|shows?|showing|throws?|returns?|says?|hit)\\b[^.?!]{0,40}\\berrors?\\b/i,\n]\n\n/** Why a question was not answered from the docs. `null` reason = answered. */\nexport type DeflectionRefusal =\n | 'follow-up'\n | 'too-short'\n | 'generative'\n | 'diagnostic'\n | 'low-score'\n | 'ambiguous'\n | 'low-coverage'\n | 'thin-section'\n\nexport interface DeflectionVerdict {\n /** True when the docs answer this without a model call. */\n answered: boolean\n /** Set when `answered` is false — which gate refused. */\n refusal: DeflectionRefusal | null\n /** The composed answer; `''` unless `answered`. */\n answer: string\n /** Sections quoted in the answer; `[]` unless `answered`. */\n quoted: readonly DocsSection[]\n /** The winning page's path; `''` when nothing won. */\n page: string\n /** Top section's retrieval score. 0 when nothing was retrieved. */\n topScore: number\n /** Winning page's score over the best rival page's. 0 when unscored. */\n pageMargin: number\n /** IDF-weighted share of the question the winning page carries. */\n coverage: number\n}\n\nfunction refuse(\n refusal: DeflectionRefusal,\n topScore = 0,\n pageMargin = 0,\n coverage = 0,\n): DeflectionVerdict {\n return {\n answered: false,\n refusal,\n answer: '',\n quoted: [],\n page: '',\n topScore,\n pageMargin,\n coverage,\n }\n}\n\n/**\n * Inverse document frequency for one token, over the docs corpus.\n *\n * Smoothed (`+1` inside the log's argument and on the denominator) so a token\n * absent from the index — a product name we have not documented, a typo —\n * gets a large but finite weight rather than a division by zero or an\n * infinity that would swallow every other term in the question.\n */\nfunction tokenWeight(token: string): number {\n const { frequency, sections } = docsDocumentFrequency()\n const seen = frequency.get(token) ?? 0\n return Math.log(1 + sections / (1 + seen))\n}\n\n/** The docs-site URL for one section. */\nexport function sectionUrl(section: DocsSection): string {\n return `${DOCS_SITE_ORIGIN}${section.path}${section.anchor}`\n}\n\n/** `Title — Heading`, or just the title on a page intro. */\nexport function sectionLabel(section: DocsSection): string {\n return section.heading ? `${section.title} — ${section.heading}` : section.title\n}\n\n/**\n * Trim verbatim text to `limit` characters on a sentence boundary, so a quote\n * never ends mid-clause. Returns the text unchanged when it already fits.\n *\n * A truncated quote is still verbatim — it is a PREFIX of the section, which\n * is what the spec's substring check asserts. Cutting on a boundary matters\n * for a different reason: a sentence stopped halfway reads as a broken\n * feature, and the user cannot tell whether the missing half contradicted the\n * visible one.\n */\nexport function trimToSentence(text: string, limit: number): string {\n const trimmed = text.trim()\n if (trimmed.length <= limit) return trimmed\n const window = trimmed.slice(0, limit)\n const lastStop = Math.max(\n window.lastIndexOf('. '),\n window.lastIndexOf('! '),\n window.lastIndexOf('? '),\n )\n // A boundary in the first third would throw most of the quote away; better\n // a hard cut with an ellipsis than an answer reduced to one sentence.\n if (lastStop > limit / 3) return window.slice(0, lastStop + 1)\n return `${window.trimEnd()}…`\n}\n\n/** Question intent, ahead of any retrieval work. */\nexport function questionIsAnswerableFromDocs(question: string): DeflectionRefusal | null {\n const tokens = new Set(tokenize(question))\n if (tokens.size < MIN_QUESTION_TOKENS) return 'too-short'\n for (const pattern of GENERATIVE_PATTERNS) {\n if (pattern.test(question)) return 'generative'\n }\n for (const pattern of DIAGNOSTIC_PATTERNS) {\n if (pattern.test(question)) return 'diagnostic'\n }\n return null\n}\n\n/**\n * Whether a question can be read WITHOUT the conversation it was asked in.\n *\n * Only consulted for a turn that has history — see\n * {@link CONTEXT_DEPENDENT_PATTERNS} for why the test errs towards \"no\", and\n * the class docstring for why the gate is no longer simply \"did anything\n * precede this\".\n *\n * Purely lexical, and that is a real limit worth naming: \"how do I do the\n * same for a blog post\" is caught by `the same`, while \"how do I change the\n * colour\" after a paragraph about buttons is not — nothing in those words\n * says which colour. What saves that case is not this function but the raised\n * evidence bar behind it, which such a question does not clear. The two gates\n * are one argument in two halves: this one reads the question, that one reads\n * the retrieval, and a follow-up must pass both.\n */\nexport function questionStandsAlone(question: string): boolean {\n if (!QUESTION_CUES.test(question)) return false\n for (const pattern of CONTEXT_DEPENDENT_PATTERNS) {\n if (pattern.test(question)) return false\n }\n return true\n}\n\n/**\n * Decide whether the retrieved sections answer the question on their own, and\n * compose the answer when they do.\n *\n * `hasHistory` is passed rather than derived because the caller holds the\n * clamped history and this module must not grow an opinion about how history\n * is budgeted. It is not a hard gate any more (AGL-2486): a turn with history\n * must additionally stand on its own words and clear the raised `FOLLOW_UP_*`\n * bar, and escalates when it does not.\n */\nexport function deflectToDocs(\n question: string,\n scored: readonly ScoredSection[],\n hasHistory: boolean,\n): DeflectionVerdict {\n if (hasHistory && !questionStandsAlone(question)) return refuse('follow-up')\n const intent = questionIsAnswerableFromDocs(question)\n if (intent) return refuse(intent)\n if (!scored.length) return refuse('low-score')\n\n const minTopScore = hasHistory ? FOLLOW_UP_MIN_TOP_SCORE : MIN_TOP_SCORE\n const minPageMargin = hasHistory ? FOLLOW_UP_MIN_PAGE_MARGIN : MIN_PAGE_MARGIN\n\n const top = scored[0]\n const topScore = top.score\n if (!(topScore >= minTopScore)) return refuse('low-score', topScore)\n\n // Score by PAGE. Sections of one page agreeing is the signal; treating them\n // as rivals is how a strong, unambiguous match reads as a tie.\n const perPage = new Map<string, number>()\n for (const entry of scored) {\n perPage.set(entry.section.path, (perPage.get(entry.section.path) ?? 0) + entry.score)\n }\n // The winning page is the highest-scoring PAGE, not the home of the\n // highest-scoring section — three mid-scoring sections of one page can beat\n // one strong section elsewhere, and when they do, that page is the answer.\n let winner = ''\n let winnerScore = 0\n let rivalScore = 0\n for (const [path, score] of perPage) {\n if (score > winnerScore) {\n rivalScore = winnerScore\n winner = path\n winnerScore = score\n } else if (score > rivalScore) {\n rivalScore = score\n }\n }\n // No rival is not a tie — it is the cleanest possible result, one page and\n // nothing else. `Infinity` would be honest but propagates badly through the\n // telemetry, so a lone winner reports its own score as the margin.\n const pageMargin = rivalScore > 0 ? winnerScore / rivalScore : winnerScore\n if (!(pageMargin >= minPageMargin)) return refuse('ambiguous', topScore, pageMargin)\n\n const pageSections = scored.filter((entry) => entry.section.path === winner)\n const pageTokens = new Set<string>()\n for (const entry of pageSections) {\n for (const token of tokenize(entry.section.title)) pageTokens.add(token)\n for (const token of tokenize(entry.section.heading)) pageTokens.add(token)\n for (const token of tokenize(entry.section.text)) pageTokens.add(token)\n }\n const questionTokens = [...new Set(tokenize(question))]\n let wanted = 0\n let covered = 0\n for (const token of questionTokens) {\n const weight = tokenWeight(token)\n wanted += weight\n if (pageTokens.has(token)) covered += weight\n }\n const coverage = wanted > 0 ? covered / wanted : 0\n // The relaxed floor is a FIRST-TURN allowance. It exists because coverage\n // and dominance are evidence about the same thing, so an emphatic winner\n // may carry a coverage miss — but mid-thread a coverage miss has a second\n // reading: the part of the question the page ignored may be the part the\n // conversation supplied. Turn one cannot mean that; a follow-up can, so it\n // pays full coverage.\n const coveredEnough =\n coverage >= MIN_COVERAGE ||\n (!hasHistory && coverage >= RELAXED_COVERAGE && pageMargin >= STRONG_PAGE_MARGIN)\n if (!coveredEnough) {\n return refuse('low-coverage', topScore, pageMargin, coverage)\n }\n\n const usable = pageSections.filter(\n (entry) => entry.section.text.trim().length >= MIN_SECTION_CHARS,\n )\n if (!usable.length) return refuse('thin-section', topScore, pageMargin, coverage)\n\n const quoted = usable.slice(0, MAX_QUOTED_SECTIONS).map((entry) => entry.section)\n return {\n answered: true,\n refusal: null,\n answer: composeDocsAnswer(quoted),\n quoted,\n page: winner,\n topScore,\n pageMargin,\n coverage,\n }\n}\n\n/**\n * The deflected answer: template + verbatim docs + real links, and nothing\n * else. Kept exported so the spec can assert the reconstruction property\n * against it directly rather than through the route.\n *\n * ⚠️ COMPOSED FOR A SURFACE THAT DOES NOT RENDER MARKDOWN. The Assist panel\n * says so in its own docstring — `renderAssistText` turns `[label](url)` and\n * bare URLs into links and renders everything else literally, under\n * `whiteSpace: 'pre-wrap'`. That is a deliberate phase-1 decision, not a gap.\n *\n * This template shipped once with the heading wrapped in `**…**`, and the * besigner drawer duly showed `**Drag-and-drop hierarchy — Moving an element\n * without dragging**`, asterisks and all. The lesson is not \"escape the\n * asterisks\" — it is that the composer has to know what renders it.\n *\n * So the heading is a bare `[label](url)` on its own line — a LINK, which is\n * the one markup the panel speaks, and which is why the title in the * screenshot was correctly clickable even while the asterisks around it were\n * not. Everything else is carried by NEWLINES, which `pre-wrap` renders,\n * rather than by markup, which it does not.\n *\n * The link has to live in the TEXT, and that is still true now that the\n * `docs` array on the `done` event IS rendered (AGL-2486, `AssistSources`).\n * It was tempting to treat that array as the structural home for the citation\n * even when nothing rendered it; it is still the wrong home, for a different\n * reason. `docs` carries every section RETRIEVED, whereas this template\n * quotes only the sections it actually used — so the array is a superset, and\n * a citation moved there would credit pages this answer never drew a word\n * from. `AssistSources` drops any url already linked in the text, which means\n * a deflected answer renders exactly as it does below and gains no duplicate\n * list underneath.\n *\n * Three specs in `docs-deflection.spec.ts` hold the line — no emphasis\n * markers, no heading markers, and a link still present.\n *\n * The closing line is not decoration. A user who reads this and finds it did\n * not answer them needs to know that asking again in different words reaches\n * something else — otherwise the cheap path looks like the assistant simply\n * being worse, and the next thing they do is stop using it.\n */\nexport function composeDocsAnswer(sections: readonly DocsSection[]): string {\n const parts: string[] = []\n let budget = MAX_ANSWER_CHARS\n for (const section of sections) {\n if (budget <= MIN_SECTION_CHARS) break\n const quote = trimToSentence(section.text, budget)\n budget -= quote.length\n parts.push(`[${sectionLabel(section)}](${sectionUrl(section)})\\n${quote}`)\n }\n parts.push(\n 'That is straight from the documentation — the headings above link to the full page. If it did not cover what you meant, ask again with more detail and I will work through it with you.',\n )\n return parts.join('\\n\\n')\n}\n\n/** Closest-pages links offered when nothing could be answered outright. */\nconst MAX_LINKED_SECTIONS = 4\n\n/**\n * The graceful degrade: the closest pages we found, and an honest sentence\n * saying why that is all there is (AGL-2486).\n *\n * ## Why this exists\n *\n * A deployment with no AI provider key — which includes every self-hosted\n * one on the day it comes up, and Aglyn's own production today — can answer\n * only what retrieval is confident about. A bare 501 for everything else\n * reaches the panel as \"Assist is not configured on this deployment\" — and it\n * can arrive on the SECOND question of a thread whose first question was just\n * answered in full. A capability refusal that lands after a working answer\n * reads as a fault, not a limit.\n *\n * The self-host charter says every Aglyn-operated dependency must be\n * configurable AND degrade cleanly. \"Degrades cleanly\" cannot mean \"answers\n * one question per thread and then refuses\" — a keyless deployment still has\n * the entire documentation corpus and a retrieval index over it, so the floor\n * is the best pages we found, not nothing.\n *\n * ## What it may and may not say\n *\n * The no-fabrication rule applies here exactly as it does to a deflected\n * answer, and is tighter in one respect: these pages did NOT clear the\n * confidence bar, so this text must not claim they answer the question. It\n * says they are the closest, which is true by construction — they are the\n * top of the retrieval ranking — and every word around them is a fixed\n * template plus a real section label and URL.\n *\n * It also must not name an env var. A user who wanted to read `501` would\n * have opened the network tab; the operator-facing detail stays in the API\n * error body, where an operator looks. This is the plain-English half.\n */\nexport function composeDocsLinksAnswer(\n sections: readonly DocsSection[],\n): string {\n const links = sections\n .slice(0, MAX_LINKED_SECTIONS)\n .map((section) => `[${sectionLabel(section)}](${sectionUrl(section)})`)\n if (!links.length) return ''\n return [\n 'I could not find one page in the documentation that clearly answers that, and the part of me that talks a question through with you is not switched on for this deployment yet — an administrator has to finish setting it up.',\n 'These are the closest pages I found:',\n links.join('\\n'),\n 'If none of them cover it, asking again in different words often lands somewhere better.',\n ].join('\\n\\n')\n}\n"],"names":["DOCS_SITE_ORIGIN","docsDocumentFrequency","tokenize","MIN_QUESTION_TOKENS","MIN_TOP_SCORE","MIN_PAGE_MARGIN","MIN_COVERAGE","RELAXED_COVERAGE","STRONG_PAGE_MARGIN","FOLLOW_UP_MIN_TOP_SCORE","FOLLOW_UP_MIN_PAGE_MARGIN","QUESTION_CUES","CONTEXT_DEPENDENT_PATTERNS","MIN_SECTION_CHARS","MAX_QUOTED_SECTIONS","MAX_ANSWER_CHARS","GENERATIVE_PATTERNS","DIAGNOSTIC_PATTERNS","refuse","refusal","topScore","pageMargin","coverage","answered","answer","quoted","page","tokenWeight","token","frequency","sections","seen","get","Math","log","sectionUrl","section","path","anchor","sectionLabel","heading","title","trimToSentence","text","limit","trimmed","trim","length","window","slice","lastStop","max","lastIndexOf","trimEnd","questionIsAnswerableFromDocs","question","tokens","Set","size","pattern","test","questionStandsAlone","deflectToDocs","scored","hasHistory","intent","minTopScore","minPageMargin","top","score","perPage","Map","entry","set","winner","winnerScore","rivalScore","pageSections","filter","pageTokens","add","questionTokens","wanted","covered","weight","has","coveredEnough","usable","map","composeDocsAnswer","parts","budget","quote","push","join","MAX_LINKED_SECTIONS","composeDocsLinksAnswer","links"],"mappings":"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"}
|
|
@@ -51,7 +51,7 @@ export declare const PLUGIN_DOCS: {
|
|
|
51
51
|
readonly aiExperiments: {
|
|
52
52
|
readonly path: "/ai/ab-tests-with-ai";
|
|
53
53
|
readonly title: "A/B tests by AI: write variants, read the result";
|
|
54
|
-
readonly excerpt: "Have Aglyn AI write two to four variants for a
|
|
54
|
+
readonly excerpt: "Have Aglyn AI write two to four variants for a page, section or email experiment, and put a finished test into plain language — with the verdict decided from the counts before the model is asked anything.";
|
|
55
55
|
};
|
|
56
56
|
readonly aiMonitoring: {
|
|
57
57
|
readonly path: "/staff-console/ai-monitoring";
|
|
@@ -66,7 +66,7 @@ export declare const PLUGIN_DOCS: {
|
|
|
66
66
|
readonly aiSeo: {
|
|
67
67
|
readonly path: "/building-sites/seo/seo-by-ai";
|
|
68
68
|
readonly title: "AI SEO for your website";
|
|
69
|
-
readonly excerpt: "AI SEO for websites, on the pages you already have: have AI write a page or product's search listing,
|
|
69
|
+
readonly excerpt: "AI SEO for websites, on the pages you already have: have AI write a page or product's search listing, propose a fix for each finding of the SEO check, and draft your structured data and /llms.txt.";
|
|
70
70
|
};
|
|
71
71
|
readonly aiThemes: {
|
|
72
72
|
readonly path: "/ai/theme-assist";
|
|
@@ -163,6 +163,11 @@ export declare const PLUGIN_DOCS: {
|
|
|
163
163
|
readonly title: "CRM settings";
|
|
164
164
|
readonly excerpt: "What the CRM does on its own for every site — whether a company is created from a contact's work email domain, who a new contact is assigned to, the address that files replies on a record, and each site's recipes.";
|
|
165
165
|
};
|
|
166
|
+
readonly crmSharing: {
|
|
167
|
+
readonly path: "/content-and-data/crm/sharing";
|
|
168
|
+
readonly title: "Share records across sites";
|
|
169
|
+
readonly excerpt: "Let another of your sites see a lead, a contact, a company or a deal — one record by hand, a selection from a list, or every record a sharing rule matches, now and later — without sharing the person's consent.";
|
|
170
|
+
};
|
|
166
171
|
readonly crmTasks: {
|
|
167
172
|
readonly path: "/content-and-data/crm/tasks";
|
|
168
173
|
readonly title: "Tasks & follow-ups";
|
|
@@ -196,7 +201,7 @@ export declare const PLUGIN_DOCS: {
|
|
|
196
201
|
readonly events: {
|
|
197
202
|
readonly path: "/content-and-data/events/overview";
|
|
198
203
|
readonly title: "Events Calendar";
|
|
199
|
-
readonly excerpt: "Keep a schedule of events in the console and publish the ones you choose to any
|
|
204
|
+
readonly excerpt: "Keep a schedule of events in the console and publish the ones you choose to any page, with search-engine event markup.";
|
|
200
205
|
};
|
|
201
206
|
readonly forms: {
|
|
202
207
|
readonly path: "/content-and-data/forms/overview";
|
|
@@ -226,7 +231,7 @@ export declare const PLUGIN_DOCS: {
|
|
|
226
231
|
readonly membersOnly: {
|
|
227
232
|
readonly path: "/workspace-and-billing/teams-and-roles/members-only";
|
|
228
233
|
readonly title: "Members-only areas";
|
|
229
|
-
readonly excerpt: "Let visitors sign up as members and gate
|
|
234
|
+
readonly excerpt: "Let visitors sign up as members and gate pages so only members can view them.";
|
|
230
235
|
};
|
|
231
236
|
readonly orgAutomations: {
|
|
232
237
|
readonly path: "/marketing-and-automation/workflows-and-actions/org-automations";
|
|
@@ -289,7 +294,7 @@ export declare const PLUGIN_DOCS_ANCHORS: {
|
|
|
289
294
|
readonly aiExperiments: readonly ["#it-proposes-you-write", "#write-variants", "#putting-them-in", "#what-it-will-not-write", "#read-a-result", "#the-verdict", "#the-words", "#undecided", "#what-is-sent", "#who-can-use-it", "#related"];
|
|
290
295
|
readonly aiMonitoring: readonly ["#the-ai-card", "#where-else", "#one-account", "#the-spend-leaderboard", "#alerts", "#related"];
|
|
291
296
|
readonly aiProducts: readonly ["#write-a-products-copy", "#write-copy-for-many-products", "#when-you-import-products", "#propose-a-first-catalog", "#propose-categories-and-discounts", "#what-the-copy-never-says", "#what-is-sent-to-the-ai-provider", "#who-can-use-it", "#related"];
|
|
292
|
-
readonly aiSeo: readonly ["#write-a-pages-listing", "#write-a-products-listing", "#
|
|
297
|
+
readonly aiSeo: readonly ["#write-a-pages-listing", "#write-a-products-listing", "#fix-what-the-seo-check-finds", "#apply-all-as-drafts", "#structured-data-and-llmstxt", "#related"];
|
|
293
298
|
readonly aiThemes: readonly ["#change-what-you-describe-or-design-a-new-theme", "#match-your-brand", "#review-the-proposal", "#save-it-or-dont", "#who-can-use-it", "#related"];
|
|
294
299
|
readonly assistSignals: readonly ["#the-workflow-this-board-exists-for", "#fleet", "#the-cache-read-rate-and-what-a-bad-number-looks-like", "#where-the-money-goes", "#tokens-by-kind", "#docs-gaps", "#questions-the-docs-could-not-answer", "#what-people-actually-asked", "#what-assist-costs-by-workspace", "#reading-the-sample-honestly", "#related"];
|
|
295
300
|
readonly billing: readonly ["#tiers--entitlements", "#enterprise", "#single-sign-on-and-enforcement", "#usage-meters", "#who-is-generating-what", "#ai-allotments", "#storage-overage", "#if-you-would-rather-uploads-stopped", "#assist-overage", "#stop-ai-assist-at-the-included-band", "#ai-overage-ceiling", "#free-ai-credits", "#ai-credit-alerts", "#usage-budget", "#seats", "#crm-records", "#the-crm-suite", "#one-to-one-email", "#organization-data", "#api-access", "#payments", "#outstanding", "#plan-total", "#billing-email", "#payment-methods", "#billing-address", "#tax-ids", "#sales-tax", "#platform-fees", "#related"];
|
|
@@ -309,6 +314,7 @@ export declare const PLUGIN_DOCS_ANCHORS: {
|
|
|
309
314
|
readonly crmLeads: readonly ["#what-makes-a-lead", "#what-a-lead-holds", "#adding-a-lead-by-hand", "#the-leads-list", "#filter-the-leads", "#working-a-lead-from-the-row", "#several-leads-at-once", "#export-csv", "#import-from-csv", "#who-owns-a-lead", "#a-leads-page", "#email-state", "#converting-a-lead", "#unqualifying-a-lead", "#erasing-the-person", "#who-can-do-this", "#related"];
|
|
310
315
|
readonly crmReports: readonly ["#choosing-a-period", "#contacts", "#sources-and-lifecycle", "#conversion-by-source", "#lead-funnel", "#pipeline", "#forecast-by-close-month", "#won-and-lost", "#won-and-lost-by-owner", "#activity-by-teammate", "#tasks", "#exporting-a-table", "#crm-at-a-glance", "#how-the-numbers-are-counted", "#related"];
|
|
311
316
|
readonly crmSettings: readonly ["#companies", "#create-companies-from-work-email-domains", "#default-owner", "#assignment-rules", "#round-robin", "#email-templates", "#email-capture", "#your-sending-addresses", "#recipes", "#related"];
|
|
317
|
+
readonly crmSharing: readonly ["#what-a-shared-record-looks-like", "#share-a-record-by-hand", "#several-records-at-once", "#sharing-rules", "#access-read-only-or-read-and-edit", "#sharing-is-not-consent", "#who-can-do-this", "#related"];
|
|
312
318
|
readonly crmTasks: readonly ["#the-tasks-page", "#the-calendar-view", "#snoozing-a-task", "#selecting-exporting-and-acting-on-many", "#import-from-csv", "#creating-a-task", "#assigning-a-task-to-someone-else", "#completing-and-reopening", "#organization-tasks", "#tasks-on-a-contact-company-or-deal", "#reminders", "#turning-reminders-off", "#next-activity", "#the-daily-digest", "#turning-it-off", "#the-dashboard-card", "#who-can-do-what", "#related"];
|
|
313
319
|
readonly crmViews: readonly ["#the-views-control", "#a-view-is-a-link", "#filters", "#filters-on-the-contacts-list", "#filters-on-the-other-lists", "#columns-and-sort", "#segments-and-views", "#who-sees-what", "#related"];
|
|
314
320
|
readonly datasets: readonly ["#model-builder", "#typed-documents", "#filter-records", "#relations", "#query-layer", "#repeatable-components", "#who-a-dataset-is-shared-with", "#import--export", "#related"];
|
|
@@ -329,7 +335,7 @@ export declare const PLUGIN_DOCS_ANCHORS: {
|
|
|
329
335
|
readonly publisherHandbook: readonly ["#before-your-first-publish", "#the-publisher-agreement", "#where-to-publish-from", "#what-installing-each-type-does", "#rules-an-email-starter-has-to-meet", "#publishing-a-version", "#before-you-publish", "#review-what-happens-after-you-publish", "#the-two-badges-and-what-each-one-promises", "#asking-to-be-verified", "#testing-a-version-before-it-is-approved", "#watching-your-own-submission", "#disabled-versions", "#private-plugins", "#authoring-your-listing", "#what-your-listing-can-say-about-aglyn", "#versioning--updates", "#shipping-a-new-version", "#how-installs-work-the-buyer-side", "#getting-paid", "#low-prices-and-processing"];
|
|
330
336
|
readonly redirects: readonly ["#manage-redirects", "#sending-visitors-to-another-site", "#metrics", "#match-modes-v2", "#related"];
|
|
331
337
|
readonly sandboxSecurity: readonly ["#a-separate-origin", "#per-manifest-network-policy", "#when-you-cant-declare-the-origin", "#pinned-immutable-artifacts", "#what-this-means-when-you-build", "#related"];
|
|
332
|
-
readonly sequences: readonly ["#what-it-is-for", "#sent-from-your-own-mailbox", "#where-it-lives", "#self-hosted", "#connect-a-mailbox", "#send-as", "#daily-cap", "#mailbox-status", "#auto-pause", "#mailbox-actions", "#link-domains", "#compliance-settings", "#allowed-countries", "#do-not-contact-domains", "#sequences", "#build-a-sequence", "#count-opens", "#send-a-test", "#sequence-status", "#enroll", "#mail-gateways", "#cold-contacts", "#enrollments", "#person-history", "#curate", "#sending", "#what-stops-a-sequence", "#unsubscribe", "#related"];
|
|
338
|
+
readonly sequences: readonly ["#what-it-is-for", "#sent-from-your-own-mailbox", "#where-it-lives", "#self-hosted", "#connect-a-mailbox", "#send-as", "#daily-cap", "#mailbox-status", "#auto-pause", "#mailbox-actions", "#link-domains", "#compliance-settings", "#allowed-countries", "#do-not-contact-domains", "#sequences", "#build-a-sequence", "#count-opens", "#send-a-test", "#sequence-status", "#enroll", "#start-at-step", "#mail-gateways", "#cold-contacts", "#enrollments", "#person-history", "#curate", "#sending", "#what-stops-a-sequence", "#unsubscribe", "#related"];
|
|
333
339
|
readonly staffConsole: readonly ["#runbooks", "#whats-there", "#staff-overview", "#support-queue", "#plugin-reviews", "#organizations-admin", "#filter-the-directory", "#organization-detail", "#staff-org-email", "#free-workspace-limit", "#first-party-hosts", "#entitlement-editor", "#plan-comps", "#sites-admin", "#filter-the-site-list", "#site-detail", "#site-ownership", "#site-transfer", "#site-content", "#staff-automations", "#emails-sent", "#users-admin", "#acquisition", "#password-help", "#sign-one-device-out", "#email-delivery", "#import-delivery-history", "#staff-notes", "#broadcast-announcements", "#billing-insight", "#refunds", "#impersonation", "#system-emails", "#platform-send-rate", "#platform-suppressions", "#feature-flags", "#multi-tenant-architecture", "#audit-archival", "#organization-suspension", "#operator-alerts", "#ai-monitoring", "#sales-tax-return", "#audit-log", "#coupons", "#existing-coupons", "#contact-suppressions", "#access", "#which-identity-holds-staff", "#staff-inside-a-customers-tenant--a-property-worth-knowing", "#offboarding", "#break-glass-access", "#requiring-sso-for-a-company-domain", "#why-am-i-getting-a-404", "#related"];
|
|
334
340
|
readonly webhooks: readonly ["#outbound-webhooks", "#inbound-webhooks", "#tips", "#related"];
|
|
335
341
|
};
|
|
@@ -48,7 +48,7 @@ export const PLUGIN_DOCS = {
|
|
|
48
48
|
aiExperiments: {
|
|
49
49
|
path: '/ai/ab-tests-with-ai',
|
|
50
50
|
title: 'A/B tests by AI: write variants, read the result',
|
|
51
|
-
excerpt: 'Have Aglyn AI write two to four variants for a
|
|
51
|
+
excerpt: 'Have Aglyn AI write two to four variants for a page, section or email experiment, and put a finished test into plain language — with the verdict decided from the counts before the model is asked anything.'
|
|
52
52
|
},
|
|
53
53
|
aiMonitoring: {
|
|
54
54
|
path: '/staff-console/ai-monitoring',
|
|
@@ -63,7 +63,7 @@ export const PLUGIN_DOCS = {
|
|
|
63
63
|
aiSeo: {
|
|
64
64
|
path: '/building-sites/seo/seo-by-ai',
|
|
65
65
|
title: 'AI SEO for your website',
|
|
66
|
-
excerpt: 'AI SEO for websites, on the pages you already have: have AI write a page or product\'s search listing,
|
|
66
|
+
excerpt: 'AI SEO for websites, on the pages you already have: have AI write a page or product\'s search listing, propose a fix for each finding of the SEO check, and draft your structured data and /llms.txt.'
|
|
67
67
|
},
|
|
68
68
|
aiThemes: {
|
|
69
69
|
path: '/ai/theme-assist',
|
|
@@ -160,6 +160,11 @@ export const PLUGIN_DOCS = {
|
|
|
160
160
|
title: 'CRM settings',
|
|
161
161
|
excerpt: 'What the CRM does on its own for every site — whether a company is created from a contact\'s work email domain, who a new contact is assigned to, the address that files replies on a record, and each site\'s recipes.'
|
|
162
162
|
},
|
|
163
|
+
crmSharing: {
|
|
164
|
+
path: '/content-and-data/crm/sharing',
|
|
165
|
+
title: 'Share records across sites',
|
|
166
|
+
excerpt: 'Let another of your sites see a lead, a contact, a company or a deal — one record by hand, a selection from a list, or every record a sharing rule matches, now and later — without sharing the person\'s consent.'
|
|
167
|
+
},
|
|
163
168
|
crmTasks: {
|
|
164
169
|
path: '/content-and-data/crm/tasks',
|
|
165
170
|
title: 'Tasks & follow-ups',
|
|
@@ -193,7 +198,7 @@ export const PLUGIN_DOCS = {
|
|
|
193
198
|
events: {
|
|
194
199
|
path: '/content-and-data/events/overview',
|
|
195
200
|
title: 'Events Calendar',
|
|
196
|
-
excerpt: 'Keep a schedule of events in the console and publish the ones you choose to any
|
|
201
|
+
excerpt: 'Keep a schedule of events in the console and publish the ones you choose to any page, with search-engine event markup.'
|
|
197
202
|
},
|
|
198
203
|
forms: {
|
|
199
204
|
path: '/content-and-data/forms/overview',
|
|
@@ -223,7 +228,7 @@ export const PLUGIN_DOCS = {
|
|
|
223
228
|
membersOnly: {
|
|
224
229
|
path: '/workspace-and-billing/teams-and-roles/members-only',
|
|
225
230
|
title: 'Members-only areas',
|
|
226
|
-
excerpt: 'Let visitors sign up as members and gate
|
|
231
|
+
excerpt: 'Let visitors sign up as members and gate pages so only members can view them.'
|
|
227
232
|
},
|
|
228
233
|
orgAutomations: {
|
|
229
234
|
path: '/marketing-and-automation/workflows-and-actions/org-automations',
|
|
@@ -386,8 +391,7 @@ export const PLUGIN_DOCS_ANCHORS = {
|
|
|
386
391
|
aiSeo: [
|
|
387
392
|
'#write-a-pages-listing',
|
|
388
393
|
'#write-a-products-listing',
|
|
389
|
-
'#
|
|
390
|
-
'#target-keywords',
|
|
394
|
+
'#fix-what-the-seo-check-finds',
|
|
391
395
|
'#apply-all-as-drafts',
|
|
392
396
|
'#structured-data-and-llmstxt',
|
|
393
397
|
'#related'
|
|
@@ -669,6 +673,16 @@ export const PLUGIN_DOCS_ANCHORS = {
|
|
|
669
673
|
'#recipes',
|
|
670
674
|
'#related'
|
|
671
675
|
],
|
|
676
|
+
crmSharing: [
|
|
677
|
+
'#what-a-shared-record-looks-like',
|
|
678
|
+
'#share-a-record-by-hand',
|
|
679
|
+
'#several-records-at-once',
|
|
680
|
+
'#sharing-rules',
|
|
681
|
+
'#access-read-only-or-read-and-edit',
|
|
682
|
+
'#sharing-is-not-consent',
|
|
683
|
+
'#who-can-do-this',
|
|
684
|
+
'#related'
|
|
685
|
+
],
|
|
672
686
|
crmTasks: [
|
|
673
687
|
'#the-tasks-page',
|
|
674
688
|
'#the-calendar-view',
|
|
@@ -983,6 +997,7 @@ export const PLUGIN_DOCS_ANCHORS = {
|
|
|
983
997
|
'#send-a-test',
|
|
984
998
|
'#sequence-status',
|
|
985
999
|
'#enroll',
|
|
1000
|
+
'#start-at-step',
|
|
986
1001
|
'#mail-gateways',
|
|
987
1002
|
'#cold-contacts',
|
|
988
1003
|
'#enrollments',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../libs/aglyn/src/lib/app-utils/docs-help.generated.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// GENERATED FILE — do not edit. Regenerate with:\n// node tools/scripts/generate-docs-help.mjs\n// Source of truth: apps/docs/docs frontmatter + headings (AGL-602).\n\n// The first-party plugin consoles live in `libs/plugins/*` and cannot import\n// the console's constants, so they carry their own generated subset of the\n// docs help registry — the topics their cards actually link to, and no others.\n\nexport interface PluginDocsTopic {\n /** Docs-site path, e.g. `/commerce-and-bookings/commerce/overview`. */\n path: string\n /** Docs page title. */\n title: string\n /** Verbatim docs frontmatter description — the tooltip excerpt. */\n excerpt: string\n}\n\nexport const PLUGIN_DOCS = {\n abuseReports: {\n path: '/staff-console/abuse-reports',\n title: 'Abuse reports',\n excerpt: 'The public abuse-report queue — where outside reports land, how to triage by severity, which lever answers which report, and the CSAM and DMCA paths that are not takedown buttons.',\n },\n actionsBuilder: {\n path: '/marketing-and-automation/workflows-and-actions/actions-builder',\n title: 'Actions builder',\n excerpt: 'Map a single event to a single action without building a full workflow.',\n },\n aglynAssist: {\n path: '/getting-started/aglyn-assist',\n title: 'Aglyn Assist',\n excerpt: 'Ask the built-in AI helper how to do anything in Aglyn — it answers from these docs and links you straight to the right page.',\n },\n aiAutomations: {\n path: '/ai/automations-with-ai',\n title: 'Explain automations with AI',\n excerpt: 'Aglyn AI can explain an automation you already have and tell you why one of its runs failed. Drafting an automation from a description is not available yet.',\n },\n aiCrm: {\n path: '/ai/crm-by-ai',\n title: 'The AI CRM built into Aglyn',\n excerpt: 'An AI CRM for small business: a short summary and a suggested next step on a contact, company, deal or lead, a one-to-one email drafted into the composer, and an import\\'s columns matched to fields.',\n },\n aiExperiments: {\n path: '/ai/ab-tests-with-ai',\n title: 'A/B tests by AI: write variants, read the result',\n excerpt: 'Have Aglyn AI write two to four variants for a screen, section or email experiment, and put a finished test into plain language — with the verdict decided from the counts before the model is asked anything.',\n },\n aiMonitoring: {\n path: '/staff-console/ai-monitoring',\n title: 'AI monitoring',\n excerpt: 'How staff watch one organization\\'s AI usage — the add-on, credit pool, overage, refusals, jobs, tokens and cache hit rate, top spenders and margin — and where those figures appear across the staff console.',\n },\n aiProducts: {\n path: '/ai/products-with-ai',\n title: 'Product copy and catalogs with AI',\n excerpt: 'An AI product description generator for your catalog: write copy for one product or a whole import, propose a first catalog, and propose categories and discounts — all as proposals you review.',\n },\n aiSeo: {\n path: '/building-sites/seo/seo-by-ai',\n title: 'AI SEO for your website',\n excerpt: 'AI SEO for websites, on the pages you already have: have AI write a page or product\\'s search listing, audit every published page with a proposed fix for each finding, and draft your structured data and /llms.txt.',\n },\n aiThemes: {\n path: '/ai/theme-assist',\n title: 'Change your site\\'s theme with AI',\n excerpt: 'Describe a change to your site\\'s theme and get a proposal for the theme editor\\'s own controls, previewed before and after, that you save in the editor.',\n },\n assistSignals: {\n path: '/staff-console/assist-signals',\n title: 'Assist Signal',\n excerpt: 'The docs-gap and cost board behind Assist — how the ranking is ordered, why ungrounded questions are counted separately, and what the cache-read rate says about margin.',\n },\n billing: {\n path: '/workspace-and-billing/billing-and-plans/overview',\n title: 'Billing & Plans',\n excerpt: 'How Aglyn\\'s tiers, entitlements, quotas, usage meters, and seat add-ons work.',\n },\n bindings: {\n path: '/building-sites/bindings/overview',\n title: 'Bindings, Variables & Functions',\n excerpt: 'Live values in your content — typed variables, no-code functions, and rename-safe id tokens.',\n },\n bookings: {\n path: '/commerce-and-bookings/bookings/overview',\n title: 'Bookings & Scheduling',\n excerpt: 'Offer services with availability, let visitors book, take payment, and send reminders.',\n },\n buildAWorkflow: {\n path: '/marketing-and-automation/workflows-and-actions/build-a-workflow',\n title: 'Build a workflow',\n excerpt: 'Create a multi-step workflow that runs when a site event fires.',\n },\n catalog: {\n path: '/commerce-and-bookings/commerce/catalog',\n title: 'Product catalog',\n excerpt: 'Products with options and variants, categories, tags, and manual or smart collections.',\n },\n commerce: {\n path: '/commerce-and-bookings/commerce/overview',\n title: 'Commerce',\n excerpt: 'Sell physical, digital, and service products with a full catalog, orders pipeline, shipping, taxes, and your own Stripe account.',\n },\n commerceEndToEnd: {\n path: '/guides/commerce-end-to-end',\n title: 'Commerce end to end',\n excerpt: 'Create products with billing modes, design the storefront with Commerce blocks, take Stripe checkout for one-time and subscription sales, and run orders from the console.',\n },\n companies: {\n path: '/content-and-data/crm/companies',\n title: 'Companies',\n excerpt: 'Group your contacts under the businesses they belong to — one record per company, with its domain, owner, address and the people who work there.',\n },\n consoleTour: {\n path: '/getting-started/console-tour',\n title: 'The console tour',\n excerpt: 'Where things live in the Aglyn console app bar and navigation.',\n },\n contactActivities: {\n path: '/content-and-data/crm/activities',\n title: 'Activities & the timeline',\n excerpt: 'Log calls, emails, meetings and notes against a contact, a company, a deal or a lead, email one person from their record, and read it all in one timeline beside everything captured and every campaign sent.',\n },\n contactFields: {\n path: '/content-and-data/crm/custom-fields',\n title: 'Custom fields',\n excerpt: 'Define your own properties on contacts, companies, deals and leads — text, number, date, choice, checkbox or link — show them on every record and its list, and save form answers straight into a contact\\'s.',\n },\n contactRecord: {\n path: '/content-and-data/crm/contact-record',\n title: 'The contact record',\n excerpt: 'Add a contact by hand, keep a profile on them — phone, company, title, address, owner and lifecycle stage — open their own page in the CRM, and merge two records that turn out to be one person.',\n },\n contacts: {\n path: '/content-and-data/crm/overview',\n title: 'CRM',\n excerpt: 'One place for the people who interact with your sites — contacts captured from forms, members, orders and bookings, with leads, companies, a deals pipeline, tasks, a timeline, reports and custom fields.',\n },\n crmEmailTemplates: {\n path: '/content-and-data/crm/email-templates',\n title: 'Email templates',\n excerpt: 'Keep the letters your team sends from a record — templates that fill in the subject and the message, snippets that drop in a paragraph, and merge fields that fill in the person\\'s name, their company, the deal and you.',\n },\n crmLeads: {\n path: '/content-and-data/crm/leads',\n title: 'Leads',\n excerpt: 'Work the people your site has captured — a status, an owner and notes on every lead — and convert one into a contact, a company and a deal.',\n },\n crmReports: {\n path: '/content-and-data/crm/reports',\n title: 'Reports',\n excerpt: 'New contacts, where they came from and which sources convert, the lead funnel, the open pipeline and its forecast, won and lost, who logged what, and the task load — counted on the server, every table exportable as CSV.',\n },\n crmSettings: {\n path: '/content-and-data/crm/settings',\n title: 'CRM settings',\n excerpt: 'What the CRM does on its own for every site — whether a company is created from a contact\\'s work email domain, who a new contact is assigned to, the address that files replies on a record, and each site\\'s recipes.',\n },\n crmTasks: {\n path: '/content-and-data/crm/tasks',\n title: 'Tasks & follow-ups',\n excerpt: 'Calls, emails, meetings and to-dos with a due date, an assignee and a link to the record they are for — overdue and today read off the clock, a snooze, a reminder at its own time, and a morning digest.',\n },\n crmViews: {\n path: '/content-and-data/crm/views',\n title: 'Saved views',\n excerpt: 'Keep a CRM list\\'s filters, columns and sort under a name, open it from the views menu or a link, share it with the team, and use a contacts view as an email audience.',\n },\n datasets: {\n path: '/content-and-data/datasets/overview',\n title: 'Datasets & Dynamic Content',\n excerpt: 'Model structured content with typed fields and relations, then bind it into repeatable components.',\n },\n deals: {\n path: '/content-and-data/crm/deals',\n title: 'Deals pipeline',\n excerpt: 'Every open deal by stage — with an amount, an owner and an expected close — as a board you drag across or a table you page through, and the won and lost history behind it.',\n },\n designedEmails: {\n path: '/marketing-and-automation/email-campaigns/designed-emails',\n title: 'Designed emails',\n excerpt: 'Build campaign emails in the besigner with email-safe blocks and merge tokens — no separate editor.',\n },\n emailCampaigns: {\n path: '/marketing-and-automation/email-campaigns/overview',\n title: 'Email Campaigns',\n excerpt: 'Campaigns to audiences built from your contacts. Campaign email starts at Pro and needs a sending domain of the site\\'s own; receipts and account email send on every plan.',\n },\n events: {\n path: '/content-and-data/events/overview',\n title: 'Events Calendar',\n excerpt: 'Keep a schedule of events in the console and publish the ones you choose to any screen, with search-engine event markup.',\n },\n forms: {\n path: '/content-and-data/forms/overview',\n title: 'Forms & Lead Capture',\n excerpt: 'Add forms to your site, collect submissions in an inbox, and write them into datasets.',\n },\n installYourFirstPlugin: {\n path: '/guides/install-your-first-plugin',\n title: 'Install your first marketplace item',\n excerpt: 'A click-by-click walkthrough of the Marketplace — find something, choose which sites get it, install it, and turn it off again.',\n },\n inviteTeammates: {\n path: '/workspace-and-billing/teams-and-roles/invite-teammates',\n title: 'Invite teammates',\n excerpt: 'Add people to your site and understand how team members act within your organization.',\n },\n manifestAndEnvs: {\n path: '/developers/plugins/reference/manifest-and-envs',\n title: 'Manifests, trust lifecycle & environment',\n excerpt: 'The plugin manifest schema, the marketplace listing/version documents, the trust state machine, and every PLUGIN_* environment variable.',\n },\n marketingOverlays: {\n path: '/marketing-and-automation/marketing-overlays/overview',\n title: 'Marketing Overlays',\n excerpt: 'Site-wide announcement bars and promotional popups with triggers, scheduling, and email capture.',\n },\n membersOnly: {\n path: '/workspace-and-billing/teams-and-roles/members-only',\n title: 'Members-only areas',\n excerpt: 'Let visitors sign up as members and gate screens so only members can view them.',\n },\n orgAutomations: {\n path: '/marketing-and-automation/workflows-and-actions/org-automations',\n title: 'Org automations',\n excerpt: 'Write an automation once for the whole organization and run it on the sites you choose, with a pause on each site.',\n },\n plugins: {\n path: '/developers/plugins/overview',\n title: 'Plugins & Marketplace',\n excerpt: 'Extend Aglyn with sandboxed plugins — install from the marketplace, configure them, and publish your own.',\n },\n pos: {\n path: '/commerce-and-bookings/commerce/pos-and-reservations',\n title: 'POS & reservations',\n excerpt: 'Sell in person from the console register and take date-range reservations with deposits.',\n },\n publishAPlugin: {\n path: '/developers/plugins/publish-a-plugin',\n title: 'Publish a plugin',\n excerpt: 'Ship your own plugin to the marketplace with version pinning.',\n },\n publisherHandbook: {\n path: '/developers/plugins/publishing/publisher-handbook',\n title: 'Publisher handbook',\n excerpt: 'Publishing to the Aglyn marketplace — from profile setup through listing authoring, review, updates, and getting paid.',\n },\n redirects: {\n path: '/building-sites/redirects/overview',\n title: 'Redirects',\n excerpt: 'Manage URL redirects with validation, loop detection, and hit metrics.',\n },\n sandboxSecurity: {\n path: '/developers/plugins/reference/sandbox-security',\n title: 'Sandbox security model',\n excerpt: 'How sandboxed marketplace plugins are isolated — separate origin, per-manifest CSP, pinned artifacts — and what that means when you write one.',\n },\n sequences: {\n path: '/content-and-data/crm/sequences',\n title: 'Sequences',\n excerpt: 'One-to-one email sequences a rep sends to a person from their own connected mailbox, kept with the CRM. Rolling out.',\n },\n staffConsole: {\n path: '/staff-console/overview',\n title: 'Staff Console (internal)',\n excerpt: 'Aglyn-staff tools for managing organizations, entitlements, users, and audits.',\n },\n webhooks: {\n path: '/marketing-and-automation/workflows-and-actions/webhooks',\n title: 'Webhooks',\n excerpt: 'Connect Aglyn to other systems with outbound and inbound webhooks.',\n },\n} as const satisfies Record<string, PluginDocsTopic>\n\nexport type PluginDocsKey = keyof typeof PLUGIN_DOCS\n\nexport const PLUGIN_DOCS_ANCHORS = {\n abuseReports: ['#fraud-and-risk-alerts-by-email', '#where-reports-come-from', '#held-outbound-email', '#what-is-screened', '#tiers', '#deciding-a-held-row', '#names-and-domains', '#stripe-fraud-signals', '#seller-fraud-pattern', '#card-testing-velocity', '#marketplace', '#risk-notices', '#triage-by-severity', '#csam', '#which-lever', '#statuses', '#disclosure', '#dmca', '#counter-notices', '#counter-notice-clock', '#counter-notice-steps', '#repeat-infringers', '#repeat-infringer-threshold', '#known-gaps', '#related'],\n actionsBuilder: ['#create-an-action', '#recipes', '#describe-it', '#triggers', '#crm-events', '#only-run-when-a-field-matches', '#chain-multiple-conditions-andor', '#steps', '#crm-steps', '#step-conditions', '#sequences', '#run-history', '#what-is-and-isnt-recorded', '#interactions-from-the-besigner', '#when-to-use-which', '#related'],\n aglynAssist: ['#what-it-can-do', '#aglyn-ai', '#answers-for-beginners-and-developers', '#offers-to-open-a-page', '#edits-in-the-besigner', '#where-an-answer-came-from', '#answers-straight-from-the-documentation', '#message-limits', '#feedback', '#privacy'],\n aiAutomations: ['#draft', '#explain', '#why-a-run-failed', '#what-is-sent', '#who-can-use-it', '#related'],\n aiCrm: ['#summarize-a-record', '#summaries-are-reused-until-the-record-changes', '#draft-an-email', '#match-columns', '#what-is-sent', '#who-can-use-it', '#related'],\n aiExperiments: ['#it-proposes-you-write', '#write-variants', '#putting-them-in', '#what-it-will-not-write', '#read-a-result', '#the-verdict', '#the-words', '#undecided', '#what-is-sent', '#who-can-use-it', '#related'],\n aiMonitoring: ['#the-ai-card', '#where-else', '#one-account', '#the-spend-leaderboard', '#alerts', '#related'],\n aiProducts: ['#write-a-products-copy', '#write-copy-for-many-products', '#when-you-import-products', '#propose-a-first-catalog', '#propose-categories-and-discounts', '#what-the-copy-never-says', '#what-is-sent-to-the-ai-provider', '#who-can-use-it', '#related'],\n aiSeo: ['#write-a-pages-listing', '#write-a-products-listing', '#audit-the-whole-site', '#target-keywords', '#apply-all-as-drafts', '#structured-data-and-llmstxt', '#related'],\n aiThemes: ['#change-what-you-describe-or-design-a-new-theme', '#match-your-brand', '#review-the-proposal', '#save-it-or-dont', '#who-can-use-it', '#related'],\n assistSignals: ['#the-workflow-this-board-exists-for', '#fleet', '#the-cache-read-rate-and-what-a-bad-number-looks-like', '#where-the-money-goes', '#tokens-by-kind', '#docs-gaps', '#questions-the-docs-could-not-answer', '#what-people-actually-asked', '#what-assist-costs-by-workspace', '#reading-the-sample-honestly', '#related'],\n billing: ['#tiers--entitlements', '#enterprise', '#single-sign-on-and-enforcement', '#usage-meters', '#who-is-generating-what', '#ai-allotments', '#storage-overage', '#if-you-would-rather-uploads-stopped', '#assist-overage', '#stop-ai-assist-at-the-included-band', '#ai-overage-ceiling', '#free-ai-credits', '#ai-credit-alerts', '#usage-budget', '#seats', '#crm-records', '#the-crm-suite', '#one-to-one-email', '#organization-data', '#api-access', '#payments', '#outstanding', '#plan-total', '#billing-email', '#payment-methods', '#billing-address', '#tax-ids', '#sales-tax', '#platform-fees', '#related'],\n bindings: ['#binding-tokens', '#rename-safe-id-tokens', '#insert-a-variable', '#token-pills', '#in-the-canvas-text-editor', '#site-details', '#typed-variables', '#no-code-functions', '#parameters-a-visitor-can-answer', '#a-calculator-you-lay-out', '#where-used--safety', '#workflows', '#related'],\n bookings: ['#set-up-bookings', '#taking-bookings', '#reminders', '#payments-and-fees', '#service-tax', '#manage', '#booking-from-the-crm', '#canceling-and-refunding', '#related'],\n buildAWorkflow: ['#1-open-the-workflows-page', '#2-choose-a-trigger', '#3-add-steps', '#waiting', '#4-save-and-test', '#duplicate-a-workflow', '#tips', '#related'],\n catalog: ['#products-options-and-variants', '#billing-modes-and-subscriptions', '#ai', '#categories-and-tags', '#collections', '#slugs', '#merchant-center-feed', '#related'],\n commerce: ['#products-hub', '#inventory', '#reserved-stock', '#stock-movements', '#gift-cards', '#recovery-and-alerts', '#orders', '#orders-screen', '#order-statuses', '#order-money-tiles', '#a-lost-dispute', '#shipping--taxes', '#lodging-tax-on-reservations', '#storefront-sales-tax', '#destination-coverage', '#dropshipping', '#related'],\n commerceEndToEnd: ['#1-connect-payments', '#2-create-products', '#3-design-the-storefront', '#catalog-search-filters-and-sort', '#category-pages', '#the-product-page-template', '#4-what-checkout-does', '#paying-without-leaving-your-site', '#5-run-orders-from-the-console', '#6-subscriptions--the-stripe-portal', '#related'],\n companies: ['#the-companies-list', '#create-a-company', '#a-companys-page', '#contacts-at-a-company', '#linked-on-capture', '#import-from-csv', '#export-csv', '#deleting-a-company', '#who-can-see-a-company', '#files', '#related'],\n consoleTour: ['#the-app-bar', '#in-context-help', '#filter-and-search', '#primary-navigation', '#editing-vs-managing', '#the-sites-list', '#the-status-pill', '#how-the-pill-is-decided', '#your-site-allowance', '#a-sites-dashboard', '#next', '#workspace-settings--notifications', '#the-notifications-feed', '#notification-settings', '#one-kind-at-a-time', '#workspace-and-site-overrides', '#daily-digests', '#alerts-on-this-device'],\n contactActivities: ['#four-kinds-of-history', '#reading-the-timeline', '#campaign-email', '#logging-an-activity', '#meeting-from-a-booking', '#click-to-call', '#sending-an-email', '#delivery-states', '#captured-email', '#where-an-activity-is-visible', '#the-recent-activity-feed', '#related'],\n contactFields: ['#define-a-field', '#fields-per-record', '#where-values-show', '#save-a-form-field', '#lead-source-values', '#over-the-api', '#retire-restore-delete', '#recompute-next-activity', '#related'],\n contactRecord: ['#adding-a-contact-by-hand', '#the-record-page', '#deleting-and-erasing', '#what-each-site-keeps-to-itself', '#when-sites-join-or-leave-a-group', '#merging-two-records', '#likely-duplicates', '#owner', '#last-engaged', '#lifecycle-stages', '#where-the-persons-lead-is', '#finding-a-contact', '#files', '#related'],\n contacts: ['#whats-in-the-crm-area', '#unified-ingestion', '#what-each-plan-includes', '#the-contacts-page', '#import-from-csv', '#segments', '#everywhere-the-crm-shows-up', '#capture-replies', '#at-the-organization-level', '#who-can-open-the-crm', '#one-sender-one-crm', '#related'],\n crmEmailTemplates: ['#templates-and-snippets', '#merge-fields', '#saving', '#managing-templates', '#duplicate-a-template', '#shared-or-personal', '#over-the-rest-api', '#related'],\n crmLeads: ['#what-makes-a-lead', '#what-a-lead-holds', '#adding-a-lead-by-hand', '#the-leads-list', '#filter-the-leads', '#working-a-lead-from-the-row', '#several-leads-at-once', '#export-csv', '#import-from-csv', '#who-owns-a-lead', '#a-leads-page', '#email-state', '#converting-a-lead', '#unqualifying-a-lead', '#erasing-the-person', '#who-can-do-this', '#related'],\n crmReports: ['#choosing-a-period', '#contacts', '#sources-and-lifecycle', '#conversion-by-source', '#lead-funnel', '#pipeline', '#forecast-by-close-month', '#won-and-lost', '#won-and-lost-by-owner', '#activity-by-teammate', '#tasks', '#exporting-a-table', '#crm-at-a-glance', '#how-the-numbers-are-counted', '#related'],\n crmSettings: ['#companies', '#create-companies-from-work-email-domains', '#default-owner', '#assignment-rules', '#round-robin', '#email-templates', '#email-capture', '#your-sending-addresses', '#recipes', '#related'],\n crmTasks: ['#the-tasks-page', '#the-calendar-view', '#snoozing-a-task', '#selecting-exporting-and-acting-on-many', '#import-from-csv', '#creating-a-task', '#assigning-a-task-to-someone-else', '#completing-and-reopening', '#organization-tasks', '#tasks-on-a-contact-company-or-deal', '#reminders', '#turning-reminders-off', '#next-activity', '#the-daily-digest', '#turning-it-off', '#the-dashboard-card', '#who-can-do-what', '#related'],\n crmViews: ['#the-views-control', '#a-view-is-a-link', '#filters', '#filters-on-the-contacts-list', '#filters-on-the-other-lists', '#columns-and-sort', '#segments-and-views', '#who-sees-what', '#related'],\n datasets: ['#model-builder', '#typed-documents', '#filter-records', '#relations', '#query-layer', '#repeatable-components', '#who-a-dataset-is-shared-with', '#import--export', '#related'],\n deals: ['#pipelines', '#stages', '#the-board-and-the-table', '#import-from-csv', '#creating-a-deal', '#line-items', '#moving-winning-and-losing', '#a-won-deal-makes-its-contact-a-customer', '#a-deals-page', '#files', '#related'],\n designedEmails: ['#create-a-template', '#find-a-template', '#duplicate-a-template', '#styling-email-blocks', '#merge-tokens', '#send-it', '#the-plain-text-version', '#start-from-a-brief-instead'],\n emailCampaigns: ['#send-a-campaign', '#campaigns-belong-to-the-organization', '#organization-emails-page', '#campaigns-group-emails', '#filter-the-lists', '#what-belongs-to-a-campaign', '#who-the-email-comes-from', '#sending-domains', '#account-email-always-sends', '#marketing-needs-a-domain', '#two-ways-to-get-a-domain', '#a-domain-we-set-up-is-a-request', '#domain-states', '#senders', '#send-a-test', '#preview-the-email', '#monthly-send-cap', '#personalize-with-merge-tags', '#recipient-count', '#who-a-campaign-is-allowed-to-reach', '#schedule-a-send', '#held-for-review', '#duplicate-an-email', '#email-lists', '#manual-lists', '#list-members', '#add-to-a-list', '#import-a-list', '#remove-from-a-list', '#lists-built-from-a-rule', '#experiments', '#experiments-across-sites', '#opens--clicks', '#the-campaign-report', '#per-contact-engagement', '#which-links-were-clicked', '#revenue-from-a-campaign', '#conversions', '#compliance', '#list-unsubscribe', '#topics', '#preference-page', '#consent-groups', '#consent-group-create', '#consent-group-join', '#consent-group-leave', '#consent-group-rename', '#consent-group-progress', '#frequency-opt-down', '#double-opt-in', '#consent-group-confirmation', '#marketing-mail', '#frequency-cap', '#suppressions', '#add-a-suppression', '#platform-suppressions', '#related'],\n events: ['#manage-events', '#show-events-on-a-screen', '#search-engines', '#related'],\n forms: ['#reading-submissions-from-code', '#build-a-form', '#monthly-allowance-per-plan', '#spam-and-abuse-protection', '#the-per-site-monthly-ceiling', '#field-types', '#labels-and-placeholders', '#example-a-quick-survey', '#after-submit', '#example-grow-an-email-list-from-a-signup-form', '#consent-group-disclosure', '#where-submissions-go', '#the-inbox', '#filter-the-inbox', '#who-a-submission-is-from', '#where-this-one-went', '#replying-to-a-submission', '#every-sites-inbox-at-once', '#one-forms-own-page', '#find-a-form', '#duplicate-a-form', '#switch-forms-off-for-one-site', '#related'],\n installYourFirstPlugin: ['#before-you-start', '#step-1-open', '#step-2-browse', '#step-3-reviews', '#step-4-targeting', '#step-5-install', '#step-6-use', '#step-7-off', '#what-to-do-next', '#related'],\n inviteTeammates: ['#invite-someone', '#pending-invites', '#who-gets-told', '#accepting-an-invite', '#declining-an-invite', '#an-invitation-never-changes-who-owns-the-workspace', '#how-team-members-act', '#you-are-a-site-collaborators-support-channel', '#help-a-teammate-who-is-locked-out', '#why-you-cant-always-set-a-password', '#activity-log', '#ai-actions', '#ai-usage', '#ai-allotment', '#tips', '#related'],\n manifestAndEnvs: ['#plugin-manifest-published-with-every-version', '#contributes--where-the-plugin-loads', '#config--settings-without-writing-a-settings-screen', '#listing--version-documents', '#review--trust-lifecycle', '#environment-variables', '#pluginsconfigjson-first-party-contributors'],\n marketingOverlays: ['#announcement-bar', '#promotional-popups', '#frequency', '#popup-v2', '#multiple-overlays-scheduling--page-targeting', '#variables-in-copy', '#engagement-stats', '#across-your-sites', '#related'],\n membersOnly: ['#let-visitors-sign-up', '#sign-in-sign-up-and-recovery-pages', '#forgotten-passwords', '#gate-a-screen', '#manage-your-members', '#suspend-or-reactivate-a-member', '#tips', '#related'],\n orgAutomations: ['#what-an-org-automation-is', '#create-one', '#triggers', '#steps', '#pause-it-on-one-site', '#waiting-switching-off-and-deleting', '#every-sites-own-automations', '#related'],\n plugins: ['#install--upgrade', '#browse-card', '#whats-included', '#what-the-badges-on-a-listing-mean', '#how-plugins-run', '#when-one-plugin-depends-on-another', '#a-dependency-that-is-off-for-one-site', '#configure', '#configure-site', '#publish-your-own', '#related'],\n pos: ['#registers', '#the-register', '#platform-fees-at-the-register', '#selling-past-the-count', '#when-something-disconnects', '#reservations', '#related'],\n publishAPlugin: ['#the-publish-pipeline', '#private-plugins', '#paid-listings', '#your-publisher-profile', '#tips', '#related'],\n publisherHandbook: ['#before-your-first-publish', '#the-publisher-agreement', '#where-to-publish-from', '#what-installing-each-type-does', '#rules-an-email-starter-has-to-meet', '#publishing-a-version', '#before-you-publish', '#review-what-happens-after-you-publish', '#the-two-badges-and-what-each-one-promises', '#asking-to-be-verified', '#testing-a-version-before-it-is-approved', '#watching-your-own-submission', '#disabled-versions', '#private-plugins', '#authoring-your-listing', '#what-your-listing-can-say-about-aglyn', '#versioning--updates', '#shipping-a-new-version', '#how-installs-work-the-buyer-side', '#getting-paid', '#low-prices-and-processing'],\n redirects: ['#manage-redirects', '#sending-visitors-to-another-site', '#metrics', '#match-modes-v2', '#related'],\n sandboxSecurity: ['#a-separate-origin', '#per-manifest-network-policy', '#when-you-cant-declare-the-origin', '#pinned-immutable-artifacts', '#what-this-means-when-you-build', '#related'],\n sequences: ['#what-it-is-for', '#sent-from-your-own-mailbox', '#where-it-lives', '#self-hosted', '#connect-a-mailbox', '#send-as', '#daily-cap', '#mailbox-status', '#auto-pause', '#mailbox-actions', '#link-domains', '#compliance-settings', '#allowed-countries', '#do-not-contact-domains', '#sequences', '#build-a-sequence', '#count-opens', '#send-a-test', '#sequence-status', '#enroll', '#mail-gateways', '#cold-contacts', '#enrollments', '#person-history', '#curate', '#sending', '#what-stops-a-sequence', '#unsubscribe', '#related'],\n staffConsole: ['#runbooks', '#whats-there', '#staff-overview', '#support-queue', '#plugin-reviews', '#organizations-admin', '#filter-the-directory', '#organization-detail', '#staff-org-email', '#free-workspace-limit', '#first-party-hosts', '#entitlement-editor', '#plan-comps', '#sites-admin', '#filter-the-site-list', '#site-detail', '#site-ownership', '#site-transfer', '#site-content', '#staff-automations', '#emails-sent', '#users-admin', '#acquisition', '#password-help', '#sign-one-device-out', '#email-delivery', '#import-delivery-history', '#staff-notes', '#broadcast-announcements', '#billing-insight', '#refunds', '#impersonation', '#system-emails', '#platform-send-rate', '#platform-suppressions', '#feature-flags', '#multi-tenant-architecture', '#audit-archival', '#organization-suspension', '#operator-alerts', '#ai-monitoring', '#sales-tax-return', '#audit-log', '#coupons', '#existing-coupons', '#contact-suppressions', '#access', '#which-identity-holds-staff', '#staff-inside-a-customers-tenant--a-property-worth-knowing', '#offboarding', '#break-glass-access', '#requiring-sso-for-a-company-domain', '#why-am-i-getting-a-404', '#related'],\n webhooks: ['#outbound-webhooks', '#inbound-webhooks', '#tips', '#related'],\n} as const satisfies Partial<Record<PluginDocsKey, readonly `#${string}`[]>>\n\ntype PluginAnchorMap = typeof PLUGIN_DOCS_ANCHORS\n\n/** Valid heading anchors for a plugin docs page (`never` when none). */\nexport type PluginDocsAnchor<K extends PluginDocsKey> =\n K extends keyof PluginAnchorMap ? PluginAnchorMap[K][number] : never\n"],"names":["PLUGIN_DOCS","abuseReports","path","title","excerpt","actionsBuilder","aglynAssist","aiAutomations","aiCrm","aiExperiments","aiMonitoring","aiProducts","aiSeo","aiThemes","assistSignals","billing","bindings","bookings","buildAWorkflow","catalog","commerce","commerceEndToEnd","companies","consoleTour","contactActivities","contactFields","contactRecord","contacts","crmEmailTemplates","crmLeads","crmReports","crmSettings","crmTasks","crmViews","datasets","deals","designedEmails","emailCampaigns","events","forms","installYourFirstPlugin","inviteTeammates","manifestAndEnvs","marketingOverlays","membersOnly","orgAutomations","plugins","pos","publishAPlugin","publisherHandbook","redirects","sandboxSecurity","sequences","staffConsole","webhooks","PLUGIN_DOCS_ANCHORS"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GACD,iDAAiD;AACjD,8CAA8C;AAC9C,oEAAoE;AAEpE,6EAA6E;AAC7E,2EAA2E;AAC3E,+EAA+E;AAW/E,OAAO,MAAMA,cAAc;IACzBC,cAAc;QACZC,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAC,gBAAgB;QACdH,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAE,aAAa;QACXJ,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAG,eAAe;QACbL,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAI,OAAO;QACLN,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAK,eAAe;QACbP,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAM,cAAc;QACZR,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAO,YAAY;QACVT,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAQ,OAAO;QACLV,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAS,UAAU;QACRX,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAU,eAAe;QACbZ,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAW,SAAS;QACPb,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAY,UAAU;QACRd,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAa,UAAU;QACRf,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAc,gBAAgB;QACdhB,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAe,SAAS;QACPjB,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAgB,UAAU;QACRlB,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAiB,kBAAkB;QAChBnB,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAkB,WAAW;QACTpB,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAmB,aAAa;QACXrB,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAoB,mBAAmB;QACjBtB,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAqB,eAAe;QACbvB,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAsB,eAAe;QACbxB,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAuB,UAAU;QACRzB,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAwB,mBAAmB;QACjB1B,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAyB,UAAU;QACR3B,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACA0B,YAAY;QACV5B,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACA2B,aAAa;QACX7B,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACA4B,UAAU;QACR9B,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACA6B,UAAU;QACR/B,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACA8B,UAAU;QACRhC,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACA+B,OAAO;QACLjC,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAgC,gBAAgB;QACdlC,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAiC,gBAAgB;QACdnC,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAkC,QAAQ;QACNpC,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAmC,OAAO;QACLrC,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAoC,wBAAwB;QACtBtC,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAqC,iBAAiB;QACfvC,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAsC,iBAAiB;QACfxC,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAuC,mBAAmB;QACjBzC,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAwC,aAAa;QACX1C,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAyC,gBAAgB;QACd3C,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACA0C,SAAS;QACP5C,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACA2C,KAAK;QACH7C,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACA4C,gBAAgB;QACd9C,MAAM;QACNC,O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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../libs/aglyn/src/lib/app-utils/docs-help.generated.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// GENERATED FILE — do not edit. Regenerate with:\n// node tools/scripts/generate-docs-help.mjs\n// Source of truth: apps/docs/docs frontmatter + headings (AGL-602).\n\n// The first-party plugin consoles live in `libs/plugins/*` and cannot import\n// the console's constants, so they carry their own generated subset of the\n// docs help registry — the topics their cards actually link to, and no others.\n\nexport interface PluginDocsTopic {\n /** Docs-site path, e.g. `/commerce-and-bookings/commerce/overview`. */\n path: string\n /** Docs page title. */\n title: string\n /** Verbatim docs frontmatter description — the tooltip excerpt. */\n excerpt: string\n}\n\nexport const PLUGIN_DOCS = {\n abuseReports: {\n path: '/staff-console/abuse-reports',\n title: 'Abuse reports',\n excerpt: 'The public abuse-report queue — where outside reports land, how to triage by severity, which lever answers which report, and the CSAM and DMCA paths that are not takedown buttons.',\n },\n actionsBuilder: {\n path: '/marketing-and-automation/workflows-and-actions/actions-builder',\n title: 'Actions builder',\n excerpt: 'Map a single event to a single action without building a full workflow.',\n },\n aglynAssist: {\n path: '/getting-started/aglyn-assist',\n title: 'Aglyn Assist',\n excerpt: 'Ask the built-in AI helper how to do anything in Aglyn — it answers from these docs and links you straight to the right page.',\n },\n aiAutomations: {\n path: '/ai/automations-with-ai',\n title: 'Explain automations with AI',\n excerpt: 'Aglyn AI can explain an automation you already have and tell you why one of its runs failed. Drafting an automation from a description is not available yet.',\n },\n aiCrm: {\n path: '/ai/crm-by-ai',\n title: 'The AI CRM built into Aglyn',\n excerpt: 'An AI CRM for small business: a short summary and a suggested next step on a contact, company, deal or lead, a one-to-one email drafted into the composer, and an import\\'s columns matched to fields.',\n },\n aiExperiments: {\n path: '/ai/ab-tests-with-ai',\n title: 'A/B tests by AI: write variants, read the result',\n excerpt: 'Have Aglyn AI write two to four variants for a page, section or email experiment, and put a finished test into plain language — with the verdict decided from the counts before the model is asked anything.',\n },\n aiMonitoring: {\n path: '/staff-console/ai-monitoring',\n title: 'AI monitoring',\n excerpt: 'How staff watch one organization\\'s AI usage — the add-on, credit pool, overage, refusals, jobs, tokens and cache hit rate, top spenders and margin — and where those figures appear across the staff console.',\n },\n aiProducts: {\n path: '/ai/products-with-ai',\n title: 'Product copy and catalogs with AI',\n excerpt: 'An AI product description generator for your catalog: write copy for one product or a whole import, propose a first catalog, and propose categories and discounts — all as proposals you review.',\n },\n aiSeo: {\n path: '/building-sites/seo/seo-by-ai',\n title: 'AI SEO for your website',\n excerpt: 'AI SEO for websites, on the pages you already have: have AI write a page or product\\'s search listing, propose a fix for each finding of the SEO check, and draft your structured data and /llms.txt.',\n },\n aiThemes: {\n path: '/ai/theme-assist',\n title: 'Change your site\\'s theme with AI',\n excerpt: 'Describe a change to your site\\'s theme and get a proposal for the theme editor\\'s own controls, previewed before and after, that you save in the editor.',\n },\n assistSignals: {\n path: '/staff-console/assist-signals',\n title: 'Assist Signal',\n excerpt: 'The docs-gap and cost board behind Assist — how the ranking is ordered, why ungrounded questions are counted separately, and what the cache-read rate says about margin.',\n },\n billing: {\n path: '/workspace-and-billing/billing-and-plans/overview',\n title: 'Billing & Plans',\n excerpt: 'How Aglyn\\'s tiers, entitlements, quotas, usage meters, and seat add-ons work.',\n },\n bindings: {\n path: '/building-sites/bindings/overview',\n title: 'Bindings, Variables & Functions',\n excerpt: 'Live values in your content — typed variables, no-code functions, and rename-safe id tokens.',\n },\n bookings: {\n path: '/commerce-and-bookings/bookings/overview',\n title: 'Bookings & Scheduling',\n excerpt: 'Offer services with availability, let visitors book, take payment, and send reminders.',\n },\n buildAWorkflow: {\n path: '/marketing-and-automation/workflows-and-actions/build-a-workflow',\n title: 'Build a workflow',\n excerpt: 'Create a multi-step workflow that runs when a site event fires.',\n },\n catalog: {\n path: '/commerce-and-bookings/commerce/catalog',\n title: 'Product catalog',\n excerpt: 'Products with options and variants, categories, tags, and manual or smart collections.',\n },\n commerce: {\n path: '/commerce-and-bookings/commerce/overview',\n title: 'Commerce',\n excerpt: 'Sell physical, digital, and service products with a full catalog, orders pipeline, shipping, taxes, and your own Stripe account.',\n },\n commerceEndToEnd: {\n path: '/guides/commerce-end-to-end',\n title: 'Commerce end to end',\n excerpt: 'Create products with billing modes, design the storefront with Commerce blocks, take Stripe checkout for one-time and subscription sales, and run orders from the console.',\n },\n companies: {\n path: '/content-and-data/crm/companies',\n title: 'Companies',\n excerpt: 'Group your contacts under the businesses they belong to — one record per company, with its domain, owner, address and the people who work there.',\n },\n consoleTour: {\n path: '/getting-started/console-tour',\n title: 'The console tour',\n excerpt: 'Where things live in the Aglyn console app bar and navigation.',\n },\n contactActivities: {\n path: '/content-and-data/crm/activities',\n title: 'Activities & the timeline',\n excerpt: 'Log calls, emails, meetings and notes against a contact, a company, a deal or a lead, email one person from their record, and read it all in one timeline beside everything captured and every campaign sent.',\n },\n contactFields: {\n path: '/content-and-data/crm/custom-fields',\n title: 'Custom fields',\n excerpt: 'Define your own properties on contacts, companies, deals and leads — text, number, date, choice, checkbox or link — show them on every record and its list, and save form answers straight into a contact\\'s.',\n },\n contactRecord: {\n path: '/content-and-data/crm/contact-record',\n title: 'The contact record',\n excerpt: 'Add a contact by hand, keep a profile on them — phone, company, title, address, owner and lifecycle stage — open their own page in the CRM, and merge two records that turn out to be one person.',\n },\n contacts: {\n path: '/content-and-data/crm/overview',\n title: 'CRM',\n excerpt: 'One place for the people who interact with your sites — contacts captured from forms, members, orders and bookings, with leads, companies, a deals pipeline, tasks, a timeline, reports and custom fields.',\n },\n crmEmailTemplates: {\n path: '/content-and-data/crm/email-templates',\n title: 'Email templates',\n excerpt: 'Keep the letters your team sends from a record — templates that fill in the subject and the message, snippets that drop in a paragraph, and merge fields that fill in the person\\'s name, their company, the deal and you.',\n },\n crmLeads: {\n path: '/content-and-data/crm/leads',\n title: 'Leads',\n excerpt: 'Work the people your site has captured — a status, an owner and notes on every lead — and convert one into a contact, a company and a deal.',\n },\n crmReports: {\n path: '/content-and-data/crm/reports',\n title: 'Reports',\n excerpt: 'New contacts, where they came from and which sources convert, the lead funnel, the open pipeline and its forecast, won and lost, who logged what, and the task load — counted on the server, every table exportable as CSV.',\n },\n crmSettings: {\n path: '/content-and-data/crm/settings',\n title: 'CRM settings',\n excerpt: 'What the CRM does on its own for every site — whether a company is created from a contact\\'s work email domain, who a new contact is assigned to, the address that files replies on a record, and each site\\'s recipes.',\n },\n crmSharing: {\n path: '/content-and-data/crm/sharing',\n title: 'Share records across sites',\n excerpt: 'Let another of your sites see a lead, a contact, a company or a deal — one record by hand, a selection from a list, or every record a sharing rule matches, now and later — without sharing the person\\'s consent.',\n },\n crmTasks: {\n path: '/content-and-data/crm/tasks',\n title: 'Tasks & follow-ups',\n excerpt: 'Calls, emails, meetings and to-dos with a due date, an assignee and a link to the record they are for — overdue and today read off the clock, a snooze, a reminder at its own time, and a morning digest.',\n },\n crmViews: {\n path: '/content-and-data/crm/views',\n title: 'Saved views',\n excerpt: 'Keep a CRM list\\'s filters, columns and sort under a name, open it from the views menu or a link, share it with the team, and use a contacts view as an email audience.',\n },\n datasets: {\n path: '/content-and-data/datasets/overview',\n title: 'Datasets & Dynamic Content',\n excerpt: 'Model structured content with typed fields and relations, then bind it into repeatable components.',\n },\n deals: {\n path: '/content-and-data/crm/deals',\n title: 'Deals pipeline',\n excerpt: 'Every open deal by stage — with an amount, an owner and an expected close — as a board you drag across or a table you page through, and the won and lost history behind it.',\n },\n designedEmails: {\n path: '/marketing-and-automation/email-campaigns/designed-emails',\n title: 'Designed emails',\n excerpt: 'Build campaign emails in the besigner with email-safe blocks and merge tokens — no separate editor.',\n },\n emailCampaigns: {\n path: '/marketing-and-automation/email-campaigns/overview',\n title: 'Email Campaigns',\n excerpt: 'Campaigns to audiences built from your contacts. Campaign email starts at Pro and needs a sending domain of the site\\'s own; receipts and account email send on every plan.',\n },\n events: {\n path: '/content-and-data/events/overview',\n title: 'Events Calendar',\n excerpt: 'Keep a schedule of events in the console and publish the ones you choose to any page, with search-engine event markup.',\n },\n forms: {\n path: '/content-and-data/forms/overview',\n title: 'Forms & Lead Capture',\n excerpt: 'Add forms to your site, collect submissions in an inbox, and write them into datasets.',\n },\n installYourFirstPlugin: {\n path: '/guides/install-your-first-plugin',\n title: 'Install your first marketplace item',\n excerpt: 'A click-by-click walkthrough of the Marketplace — find something, choose which sites get it, install it, and turn it off again.',\n },\n inviteTeammates: {\n path: '/workspace-and-billing/teams-and-roles/invite-teammates',\n title: 'Invite teammates',\n excerpt: 'Add people to your site and understand how team members act within your organization.',\n },\n manifestAndEnvs: {\n path: '/developers/plugins/reference/manifest-and-envs',\n title: 'Manifests, trust lifecycle & environment',\n excerpt: 'The plugin manifest schema, the marketplace listing/version documents, the trust state machine, and every PLUGIN_* environment variable.',\n },\n marketingOverlays: {\n path: '/marketing-and-automation/marketing-overlays/overview',\n title: 'Marketing Overlays',\n excerpt: 'Site-wide announcement bars and promotional popups with triggers, scheduling, and email capture.',\n },\n membersOnly: {\n path: '/workspace-and-billing/teams-and-roles/members-only',\n title: 'Members-only areas',\n excerpt: 'Let visitors sign up as members and gate pages so only members can view them.',\n },\n orgAutomations: {\n path: '/marketing-and-automation/workflows-and-actions/org-automations',\n title: 'Org automations',\n excerpt: 'Write an automation once for the whole organization and run it on the sites you choose, with a pause on each site.',\n },\n plugins: {\n path: '/developers/plugins/overview',\n title: 'Plugins & Marketplace',\n excerpt: 'Extend Aglyn with sandboxed plugins — install from the marketplace, configure them, and publish your own.',\n },\n pos: {\n path: '/commerce-and-bookings/commerce/pos-and-reservations',\n title: 'POS & reservations',\n excerpt: 'Sell in person from the console register and take date-range reservations with deposits.',\n },\n publishAPlugin: {\n path: '/developers/plugins/publish-a-plugin',\n title: 'Publish a plugin',\n excerpt: 'Ship your own plugin to the marketplace with version pinning.',\n },\n publisherHandbook: {\n path: '/developers/plugins/publishing/publisher-handbook',\n title: 'Publisher handbook',\n excerpt: 'Publishing to the Aglyn marketplace — from profile setup through listing authoring, review, updates, and getting paid.',\n },\n redirects: {\n path: '/building-sites/redirects/overview',\n title: 'Redirects',\n excerpt: 'Manage URL redirects with validation, loop detection, and hit metrics.',\n },\n sandboxSecurity: {\n path: '/developers/plugins/reference/sandbox-security',\n title: 'Sandbox security model',\n excerpt: 'How sandboxed marketplace plugins are isolated — separate origin, per-manifest CSP, pinned artifacts — and what that means when you write one.',\n },\n sequences: {\n path: '/content-and-data/crm/sequences',\n title: 'Sequences',\n excerpt: 'One-to-one email sequences a rep sends to a person from their own connected mailbox, kept with the CRM. Rolling out.',\n },\n staffConsole: {\n path: '/staff-console/overview',\n title: 'Staff Console (internal)',\n excerpt: 'Aglyn-staff tools for managing organizations, entitlements, users, and audits.',\n },\n webhooks: {\n path: '/marketing-and-automation/workflows-and-actions/webhooks',\n title: 'Webhooks',\n excerpt: 'Connect Aglyn to other systems with outbound and inbound webhooks.',\n },\n} as const satisfies Record<string, PluginDocsTopic>\n\nexport type PluginDocsKey = keyof typeof PLUGIN_DOCS\n\nexport const PLUGIN_DOCS_ANCHORS = {\n abuseReports: ['#fraud-and-risk-alerts-by-email', '#where-reports-come-from', '#held-outbound-email', '#what-is-screened', '#tiers', '#deciding-a-held-row', '#names-and-domains', '#stripe-fraud-signals', '#seller-fraud-pattern', '#card-testing-velocity', '#marketplace', '#risk-notices', '#triage-by-severity', '#csam', '#which-lever', '#statuses', '#disclosure', '#dmca', '#counter-notices', '#counter-notice-clock', '#counter-notice-steps', '#repeat-infringers', '#repeat-infringer-threshold', '#known-gaps', '#related'],\n actionsBuilder: ['#create-an-action', '#recipes', '#describe-it', '#triggers', '#crm-events', '#only-run-when-a-field-matches', '#chain-multiple-conditions-andor', '#steps', '#crm-steps', '#step-conditions', '#sequences', '#run-history', '#what-is-and-isnt-recorded', '#interactions-from-the-besigner', '#when-to-use-which', '#related'],\n aglynAssist: ['#what-it-can-do', '#aglyn-ai', '#answers-for-beginners-and-developers', '#offers-to-open-a-page', '#edits-in-the-besigner', '#where-an-answer-came-from', '#answers-straight-from-the-documentation', '#message-limits', '#feedback', '#privacy'],\n aiAutomations: ['#draft', '#explain', '#why-a-run-failed', '#what-is-sent', '#who-can-use-it', '#related'],\n aiCrm: ['#summarize-a-record', '#summaries-are-reused-until-the-record-changes', '#draft-an-email', '#match-columns', '#what-is-sent', '#who-can-use-it', '#related'],\n aiExperiments: ['#it-proposes-you-write', '#write-variants', '#putting-them-in', '#what-it-will-not-write', '#read-a-result', '#the-verdict', '#the-words', '#undecided', '#what-is-sent', '#who-can-use-it', '#related'],\n aiMonitoring: ['#the-ai-card', '#where-else', '#one-account', '#the-spend-leaderboard', '#alerts', '#related'],\n aiProducts: ['#write-a-products-copy', '#write-copy-for-many-products', '#when-you-import-products', '#propose-a-first-catalog', '#propose-categories-and-discounts', '#what-the-copy-never-says', '#what-is-sent-to-the-ai-provider', '#who-can-use-it', '#related'],\n aiSeo: ['#write-a-pages-listing', '#write-a-products-listing', '#fix-what-the-seo-check-finds', '#apply-all-as-drafts', '#structured-data-and-llmstxt', '#related'],\n aiThemes: ['#change-what-you-describe-or-design-a-new-theme', '#match-your-brand', '#review-the-proposal', '#save-it-or-dont', '#who-can-use-it', '#related'],\n assistSignals: ['#the-workflow-this-board-exists-for', '#fleet', '#the-cache-read-rate-and-what-a-bad-number-looks-like', '#where-the-money-goes', '#tokens-by-kind', '#docs-gaps', '#questions-the-docs-could-not-answer', '#what-people-actually-asked', '#what-assist-costs-by-workspace', '#reading-the-sample-honestly', '#related'],\n billing: ['#tiers--entitlements', '#enterprise', '#single-sign-on-and-enforcement', '#usage-meters', '#who-is-generating-what', '#ai-allotments', '#storage-overage', '#if-you-would-rather-uploads-stopped', '#assist-overage', '#stop-ai-assist-at-the-included-band', '#ai-overage-ceiling', '#free-ai-credits', '#ai-credit-alerts', '#usage-budget', '#seats', '#crm-records', '#the-crm-suite', '#one-to-one-email', '#organization-data', '#api-access', '#payments', '#outstanding', '#plan-total', '#billing-email', '#payment-methods', '#billing-address', '#tax-ids', '#sales-tax', '#platform-fees', '#related'],\n bindings: ['#binding-tokens', '#rename-safe-id-tokens', '#insert-a-variable', '#token-pills', '#in-the-canvas-text-editor', '#site-details', '#typed-variables', '#no-code-functions', '#parameters-a-visitor-can-answer', '#a-calculator-you-lay-out', '#where-used--safety', '#workflows', '#related'],\n bookings: ['#set-up-bookings', '#taking-bookings', '#reminders', '#payments-and-fees', '#service-tax', '#manage', '#booking-from-the-crm', '#canceling-and-refunding', '#related'],\n buildAWorkflow: ['#1-open-the-workflows-page', '#2-choose-a-trigger', '#3-add-steps', '#waiting', '#4-save-and-test', '#duplicate-a-workflow', '#tips', '#related'],\n catalog: ['#products-options-and-variants', '#billing-modes-and-subscriptions', '#ai', '#categories-and-tags', '#collections', '#slugs', '#merchant-center-feed', '#related'],\n commerce: ['#products-hub', '#inventory', '#reserved-stock', '#stock-movements', '#gift-cards', '#recovery-and-alerts', '#orders', '#orders-screen', '#order-statuses', '#order-money-tiles', '#a-lost-dispute', '#shipping--taxes', '#lodging-tax-on-reservations', '#storefront-sales-tax', '#destination-coverage', '#dropshipping', '#related'],\n commerceEndToEnd: ['#1-connect-payments', '#2-create-products', '#3-design-the-storefront', '#catalog-search-filters-and-sort', '#category-pages', '#the-product-page-template', '#4-what-checkout-does', '#paying-without-leaving-your-site', '#5-run-orders-from-the-console', '#6-subscriptions--the-stripe-portal', '#related'],\n companies: ['#the-companies-list', '#create-a-company', '#a-companys-page', '#contacts-at-a-company', '#linked-on-capture', '#import-from-csv', '#export-csv', '#deleting-a-company', '#who-can-see-a-company', '#files', '#related'],\n consoleTour: ['#the-app-bar', '#in-context-help', '#filter-and-search', '#primary-navigation', '#editing-vs-managing', '#the-sites-list', '#the-status-pill', '#how-the-pill-is-decided', '#your-site-allowance', '#a-sites-dashboard', '#next', '#workspace-settings--notifications', '#the-notifications-feed', '#notification-settings', '#one-kind-at-a-time', '#workspace-and-site-overrides', '#daily-digests', '#alerts-on-this-device'],\n contactActivities: ['#four-kinds-of-history', '#reading-the-timeline', '#campaign-email', '#logging-an-activity', '#meeting-from-a-booking', '#click-to-call', '#sending-an-email', '#delivery-states', '#captured-email', '#where-an-activity-is-visible', '#the-recent-activity-feed', '#related'],\n contactFields: ['#define-a-field', '#fields-per-record', '#where-values-show', '#save-a-form-field', '#lead-source-values', '#over-the-api', '#retire-restore-delete', '#recompute-next-activity', '#related'],\n contactRecord: ['#adding-a-contact-by-hand', '#the-record-page', '#deleting-and-erasing', '#what-each-site-keeps-to-itself', '#when-sites-join-or-leave-a-group', '#merging-two-records', '#likely-duplicates', '#owner', '#last-engaged', '#lifecycle-stages', '#where-the-persons-lead-is', '#finding-a-contact', '#files', '#related'],\n contacts: ['#whats-in-the-crm-area', '#unified-ingestion', '#what-each-plan-includes', '#the-contacts-page', '#import-from-csv', '#segments', '#everywhere-the-crm-shows-up', '#capture-replies', '#at-the-organization-level', '#who-can-open-the-crm', '#one-sender-one-crm', '#related'],\n crmEmailTemplates: ['#templates-and-snippets', '#merge-fields', '#saving', '#managing-templates', '#duplicate-a-template', '#shared-or-personal', '#over-the-rest-api', '#related'],\n crmLeads: ['#what-makes-a-lead', '#what-a-lead-holds', '#adding-a-lead-by-hand', '#the-leads-list', '#filter-the-leads', '#working-a-lead-from-the-row', '#several-leads-at-once', '#export-csv', '#import-from-csv', '#who-owns-a-lead', '#a-leads-page', '#email-state', '#converting-a-lead', '#unqualifying-a-lead', '#erasing-the-person', '#who-can-do-this', '#related'],\n crmReports: ['#choosing-a-period', '#contacts', '#sources-and-lifecycle', '#conversion-by-source', '#lead-funnel', '#pipeline', '#forecast-by-close-month', '#won-and-lost', '#won-and-lost-by-owner', '#activity-by-teammate', '#tasks', '#exporting-a-table', '#crm-at-a-glance', '#how-the-numbers-are-counted', '#related'],\n crmSettings: ['#companies', '#create-companies-from-work-email-domains', '#default-owner', '#assignment-rules', '#round-robin', '#email-templates', '#email-capture', '#your-sending-addresses', '#recipes', '#related'],\n crmSharing: ['#what-a-shared-record-looks-like', '#share-a-record-by-hand', '#several-records-at-once', '#sharing-rules', '#access-read-only-or-read-and-edit', '#sharing-is-not-consent', '#who-can-do-this', '#related'],\n crmTasks: ['#the-tasks-page', '#the-calendar-view', '#snoozing-a-task', '#selecting-exporting-and-acting-on-many', '#import-from-csv', '#creating-a-task', '#assigning-a-task-to-someone-else', '#completing-and-reopening', '#organization-tasks', '#tasks-on-a-contact-company-or-deal', '#reminders', '#turning-reminders-off', '#next-activity', '#the-daily-digest', '#turning-it-off', '#the-dashboard-card', '#who-can-do-what', '#related'],\n crmViews: ['#the-views-control', '#a-view-is-a-link', '#filters', '#filters-on-the-contacts-list', '#filters-on-the-other-lists', '#columns-and-sort', '#segments-and-views', '#who-sees-what', '#related'],\n datasets: ['#model-builder', '#typed-documents', '#filter-records', '#relations', '#query-layer', '#repeatable-components', '#who-a-dataset-is-shared-with', '#import--export', '#related'],\n deals: ['#pipelines', '#stages', '#the-board-and-the-table', '#import-from-csv', '#creating-a-deal', '#line-items', '#moving-winning-and-losing', '#a-won-deal-makes-its-contact-a-customer', '#a-deals-page', '#files', '#related'],\n designedEmails: ['#create-a-template', '#find-a-template', '#duplicate-a-template', '#styling-email-blocks', '#merge-tokens', '#send-it', '#the-plain-text-version', '#start-from-a-brief-instead'],\n emailCampaigns: ['#send-a-campaign', '#campaigns-belong-to-the-organization', '#organization-emails-page', '#campaigns-group-emails', '#filter-the-lists', '#what-belongs-to-a-campaign', '#who-the-email-comes-from', '#sending-domains', '#account-email-always-sends', '#marketing-needs-a-domain', '#two-ways-to-get-a-domain', '#a-domain-we-set-up-is-a-request', '#domain-states', '#senders', '#send-a-test', '#preview-the-email', '#monthly-send-cap', '#personalize-with-merge-tags', '#recipient-count', '#who-a-campaign-is-allowed-to-reach', '#schedule-a-send', '#held-for-review', '#duplicate-an-email', '#email-lists', '#manual-lists', '#list-members', '#add-to-a-list', '#import-a-list', '#remove-from-a-list', '#lists-built-from-a-rule', '#experiments', '#experiments-across-sites', '#opens--clicks', '#the-campaign-report', '#per-contact-engagement', '#which-links-were-clicked', '#revenue-from-a-campaign', '#conversions', '#compliance', '#list-unsubscribe', '#topics', '#preference-page', '#consent-groups', '#consent-group-create', '#consent-group-join', '#consent-group-leave', '#consent-group-rename', '#consent-group-progress', '#frequency-opt-down', '#double-opt-in', '#consent-group-confirmation', '#marketing-mail', '#frequency-cap', '#suppressions', '#add-a-suppression', '#platform-suppressions', '#related'],\n events: ['#manage-events', '#show-events-on-a-screen', '#search-engines', '#related'],\n forms: ['#reading-submissions-from-code', '#build-a-form', '#monthly-allowance-per-plan', '#spam-and-abuse-protection', '#the-per-site-monthly-ceiling', '#field-types', '#labels-and-placeholders', '#example-a-quick-survey', '#after-submit', '#example-grow-an-email-list-from-a-signup-form', '#consent-group-disclosure', '#where-submissions-go', '#the-inbox', '#filter-the-inbox', '#who-a-submission-is-from', '#where-this-one-went', '#replying-to-a-submission', '#every-sites-inbox-at-once', '#one-forms-own-page', '#find-a-form', '#duplicate-a-form', '#switch-forms-off-for-one-site', '#related'],\n installYourFirstPlugin: ['#before-you-start', '#step-1-open', '#step-2-browse', '#step-3-reviews', '#step-4-targeting', '#step-5-install', '#step-6-use', '#step-7-off', '#what-to-do-next', '#related'],\n inviteTeammates: ['#invite-someone', '#pending-invites', '#who-gets-told', '#accepting-an-invite', '#declining-an-invite', '#an-invitation-never-changes-who-owns-the-workspace', '#how-team-members-act', '#you-are-a-site-collaborators-support-channel', '#help-a-teammate-who-is-locked-out', '#why-you-cant-always-set-a-password', '#activity-log', '#ai-actions', '#ai-usage', '#ai-allotment', '#tips', '#related'],\n manifestAndEnvs: ['#plugin-manifest-published-with-every-version', '#contributes--where-the-plugin-loads', '#config--settings-without-writing-a-settings-screen', '#listing--version-documents', '#review--trust-lifecycle', '#environment-variables', '#pluginsconfigjson-first-party-contributors'],\n marketingOverlays: ['#announcement-bar', '#promotional-popups', '#frequency', '#popup-v2', '#multiple-overlays-scheduling--page-targeting', '#variables-in-copy', '#engagement-stats', '#across-your-sites', '#related'],\n membersOnly: ['#let-visitors-sign-up', '#sign-in-sign-up-and-recovery-pages', '#forgotten-passwords', '#gate-a-screen', '#manage-your-members', '#suspend-or-reactivate-a-member', '#tips', '#related'],\n orgAutomations: ['#what-an-org-automation-is', '#create-one', '#triggers', '#steps', '#pause-it-on-one-site', '#waiting-switching-off-and-deleting', '#every-sites-own-automations', '#related'],\n plugins: ['#install--upgrade', '#browse-card', '#whats-included', '#what-the-badges-on-a-listing-mean', '#how-plugins-run', '#when-one-plugin-depends-on-another', '#a-dependency-that-is-off-for-one-site', '#configure', '#configure-site', '#publish-your-own', '#related'],\n pos: ['#registers', '#the-register', '#platform-fees-at-the-register', '#selling-past-the-count', '#when-something-disconnects', '#reservations', '#related'],\n publishAPlugin: ['#the-publish-pipeline', '#private-plugins', '#paid-listings', '#your-publisher-profile', '#tips', '#related'],\n publisherHandbook: ['#before-your-first-publish', '#the-publisher-agreement', '#where-to-publish-from', '#what-installing-each-type-does', '#rules-an-email-starter-has-to-meet', '#publishing-a-version', '#before-you-publish', '#review-what-happens-after-you-publish', '#the-two-badges-and-what-each-one-promises', '#asking-to-be-verified', '#testing-a-version-before-it-is-approved', '#watching-your-own-submission', '#disabled-versions', '#private-plugins', '#authoring-your-listing', '#what-your-listing-can-say-about-aglyn', '#versioning--updates', '#shipping-a-new-version', '#how-installs-work-the-buyer-side', '#getting-paid', '#low-prices-and-processing'],\n redirects: ['#manage-redirects', '#sending-visitors-to-another-site', '#metrics', '#match-modes-v2', '#related'],\n sandboxSecurity: ['#a-separate-origin', '#per-manifest-network-policy', '#when-you-cant-declare-the-origin', '#pinned-immutable-artifacts', '#what-this-means-when-you-build', '#related'],\n sequences: ['#what-it-is-for', '#sent-from-your-own-mailbox', '#where-it-lives', '#self-hosted', '#connect-a-mailbox', '#send-as', '#daily-cap', '#mailbox-status', '#auto-pause', '#mailbox-actions', '#link-domains', '#compliance-settings', '#allowed-countries', '#do-not-contact-domains', '#sequences', '#build-a-sequence', '#count-opens', '#send-a-test', '#sequence-status', '#enroll', '#start-at-step', '#mail-gateways', '#cold-contacts', '#enrollments', '#person-history', '#curate', '#sending', '#what-stops-a-sequence', '#unsubscribe', '#related'],\n staffConsole: ['#runbooks', '#whats-there', '#staff-overview', '#support-queue', '#plugin-reviews', '#organizations-admin', '#filter-the-directory', '#organization-detail', '#staff-org-email', '#free-workspace-limit', '#first-party-hosts', '#entitlement-editor', '#plan-comps', '#sites-admin', '#filter-the-site-list', '#site-detail', '#site-ownership', '#site-transfer', '#site-content', '#staff-automations', '#emails-sent', '#users-admin', '#acquisition', '#password-help', '#sign-one-device-out', '#email-delivery', '#import-delivery-history', '#staff-notes', '#broadcast-announcements', '#billing-insight', '#refunds', '#impersonation', '#system-emails', '#platform-send-rate', '#platform-suppressions', '#feature-flags', '#multi-tenant-architecture', '#audit-archival', '#organization-suspension', '#operator-alerts', '#ai-monitoring', '#sales-tax-return', '#audit-log', '#coupons', '#existing-coupons', '#contact-suppressions', '#access', '#which-identity-holds-staff', '#staff-inside-a-customers-tenant--a-property-worth-knowing', '#offboarding', '#break-glass-access', '#requiring-sso-for-a-company-domain', '#why-am-i-getting-a-404', '#related'],\n webhooks: ['#outbound-webhooks', '#inbound-webhooks', '#tips', '#related'],\n} as const satisfies Partial<Record<PluginDocsKey, readonly `#${string}`[]>>\n\ntype PluginAnchorMap = typeof PLUGIN_DOCS_ANCHORS\n\n/** Valid heading anchors for a plugin docs page (`never` when none). */\nexport type PluginDocsAnchor<K extends PluginDocsKey> =\n K extends keyof PluginAnchorMap ? PluginAnchorMap[K][number] : never\n"],"names":["PLUGIN_DOCS","abuseReports","path","title","excerpt","actionsBuilder","aglynAssist","aiAutomations","aiCrm","aiExperiments","aiMonitoring","aiProducts","aiSeo","aiThemes","assistSignals","billing","bindings","bookings","buildAWorkflow","catalog","commerce","commerceEndToEnd","companies","consoleTour","contactActivities","contactFields","contactRecord","contacts","crmEmailTemplates","crmLeads","crmReports","crmSettings","crmSharing","crmTasks","crmViews","datasets","deals","designedEmails","emailCampaigns","events","forms","installYourFirstPlugin","inviteTeammates","manifestAndEnvs","marketingOverlays","membersOnly","orgAutomations","plugins","pos","publishAPlugin","publisherHandbook","redirects","sandboxSecurity","sequences","staffConsole","webhooks","PLUGIN_DOCS_ANCHORS"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GACD,iDAAiD;AACjD,8CAA8C;AAC9C,oEAAoE;AAEpE,6EAA6E;AAC7E,2EAA2E;AAC3E,+EAA+E;AAW/E,OAAO,MAAMA,cAAc;IACzBC,cAAc;QACZC,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAC,gBAAgB;QACdH,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAE,aAAa;QACXJ,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAG,eAAe;QACbL,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAI,OAAO;QACLN,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAK,eAAe;QACbP,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAM,cAAc;QACZR,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAO,YAAY;QACVT,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAQ,OAAO;QACLV,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAS,UAAU;QACRX,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAU,eAAe;QACbZ,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAW,SAAS;QACPb,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAY,UAAU;QACRd,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAa,UAAU;QACRf,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAc,gBAAgB;QACdhB,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAe,SAAS;QACPjB,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAgB,UAAU;QACRlB,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAiB,kBAAkB;QAChBnB,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAkB,WAAW;QACTpB,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAmB,aAAa;QACXrB,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAoB,mBAAmB;QACjBtB,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAqB,eAAe;QACbvB,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAsB,eAAe;QACbxB,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAuB,UAAU;QACRzB,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAwB,mBAAmB;QACjB1B,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAyB,UAAU;QACR3B,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACA0B,YAAY;QACV5B,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACA2B,aAAa;QACX7B,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACA4B,YAAY;QACV9B,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACA6B,UAAU;QACR/B,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACA8B,UAAU;QACRhC,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACA+B,UAAU;QACRjC,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAgC,OAAO;QACLlC,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAiC,gBAAgB;QACdnC,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAkC,gBAAgB;QACdpC,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAmC,QAAQ;QACNrC,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAoC,OAAO;QACLtC,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAqC,wBAAwB;QACtBvC,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAsC,iBAAiB;QACfxC,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAuC,iBAAiB;QACfzC,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAwC,mBAAmB;QACjB1C,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACAyC,aAAa;QACX3C,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACA0C,gBAAgB;QACd5C,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACA2C,SAAS;QACP7C,MAAM;QACNC,OAAO;QACPC,SAAS;IACX;IACA4C,KAAK;QACH9C,MAAM;QACNC,OAA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"}
|