@aglyn/aglyn 1.0.0-beta.143
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +11 -0
- package/package.json +66 -0
- package/src/index.d.ts +25 -0
- package/src/index.js +26 -0
- package/src/index.js.map +1 -0
- package/src/lib/aglyn.d.ts +31 -0
- package/src/lib/aglyn.js +114 -0
- package/src/lib/aglyn.js.map +1 -0
- package/src/lib/app-utils/abuse-report.d.ts +193 -0
- package/src/lib/app-utils/abuse-report.js +321 -0
- package/src/lib/app-utils/abuse-report.js.map +1 -0
- package/src/lib/app-utils/accept-negotiation.d.ts +129 -0
- package/src/lib/app-utils/accept-negotiation.js +266 -0
- package/src/lib/app-utils/accept-negotiation.js.map +1 -0
- package/src/lib/app-utils/account-emails.d.ts +263 -0
- package/src/lib/app-utils/account-emails.js +264 -0
- package/src/lib/app-utils/account-emails.js.map +1 -0
- package/src/lib/app-utils/actions.d.ts +717 -0
- package/src/lib/app-utils/actions.js +1031 -0
- package/src/lib/app-utils/actions.js.map +1 -0
- package/src/lib/app-utils/activity-presenter.d.ts +152 -0
- package/src/lib/app-utils/activity-presenter.js +326 -0
- package/src/lib/app-utils/activity-presenter.js.map +1 -0
- package/src/lib/app-utils/advertising-tag-mounts.d.ts +133 -0
- package/src/lib/app-utils/advertising-tag-mounts.js +118 -0
- package/src/lib/app-utils/advertising-tag-mounts.js.map +1 -0
- package/src/lib/app-utils/advertising-tags.d.ts +307 -0
- package/src/lib/app-utils/advertising-tags.js +525 -0
- package/src/lib/app-utils/advertising-tags.js.map +1 -0
- package/src/lib/app-utils/agent-api-catalog.d.ts +94 -0
- package/src/lib/app-utils/agent-api-catalog.js +106 -0
- package/src/lib/app-utils/agent-api-catalog.js.map +1 -0
- package/src/lib/app-utils/agent-openapi.d.ts +103 -0
- package/src/lib/app-utils/agent-openapi.js +1128 -0
- package/src/lib/app-utils/agent-openapi.js.map +1 -0
- package/src/lib/app-utils/analytics-beacon.d.ts +154 -0
- package/src/lib/app-utils/analytics-beacon.js +152 -0
- package/src/lib/app-utils/analytics-beacon.js.map +1 -0
- package/src/lib/app-utils/analytics-environment.d.ts +133 -0
- package/src/lib/app-utils/analytics-environment.js +152 -0
- package/src/lib/app-utils/analytics-environment.js.map +1 -0
- package/src/lib/app-utils/analytics-events.d.ts +744 -0
- package/src/lib/app-utils/analytics-events.js +650 -0
- package/src/lib/app-utils/analytics-events.js.map +1 -0
- package/src/lib/app-utils/analytics-link-clicks.d.ts +102 -0
- package/src/lib/app-utils/analytics-link-clicks.js +267 -0
- package/src/lib/app-utils/analytics-link-clicks.js.map +1 -0
- package/src/lib/app-utils/analytics-path-key.d.ts +46 -0
- package/src/lib/app-utils/analytics-path-key.js +46 -0
- package/src/lib/app-utils/analytics-path-key.js.map +1 -0
- package/src/lib/app-utils/api-adapter.d.ts +47 -0
- package/src/lib/app-utils/api-adapter.js +367 -0
- package/src/lib/app-utils/api-adapter.js.map +1 -0
- package/src/lib/app-utils/api-idempotency.d.ts +169 -0
- package/src/lib/app-utils/api-idempotency.js +213 -0
- package/src/lib/app-utils/api-idempotency.js.map +1 -0
- package/src/lib/app-utils/api-plugins.d.ts +210 -0
- package/src/lib/app-utils/api-plugins.js +221 -0
- package/src/lib/app-utils/api-plugins.js.map +1 -0
- package/src/lib/app-utils/assist-credits.d.ts +482 -0
- package/src/lib/app-utils/assist-credits.js +509 -0
- package/src/lib/app-utils/assist-credits.js.map +1 -0
- package/src/lib/app-utils/attribution-attribute.d.ts +34 -0
- package/src/lib/app-utils/attribution-attribute.js +34 -0
- package/src/lib/app-utils/attribution-attribute.js.map +1 -0
- package/src/lib/app-utils/attribution-guard.d.ts +130 -0
- package/src/lib/app-utils/attribution-guard.js +410 -0
- package/src/lib/app-utils/attribution-guard.js.map +1 -0
- package/src/lib/app-utils/author-css.d.ts +123 -0
- package/src/lib/app-utils/author-css.js +275 -0
- package/src/lib/app-utils/author-css.js.map +1 -0
- package/src/lib/app-utils/author-html-markdown.d.ts +31 -0
- package/src/lib/app-utils/author-html-markdown.js +497 -0
- package/src/lib/app-utils/author-html-markdown.js.map +1 -0
- package/src/lib/app-utils/author-html.d.ts +135 -0
- package/src/lib/app-utils/author-html.js +1037 -0
- package/src/lib/app-utils/author-html.js.map +1 -0
- package/src/lib/app-utils/automation-placeholders.d.ts +72 -0
- package/src/lib/app-utils/automation-placeholders.js +207 -0
- package/src/lib/app-utils/automation-placeholders.js.map +1 -0
- package/src/lib/app-utils/bandwidth-cap.d.ts +183 -0
- package/src/lib/app-utils/bandwidth-cap.js +193 -0
- package/src/lib/app-utils/bandwidth-cap.js.map +1 -0
- package/src/lib/app-utils/binding-token-catalog.d.ts +82 -0
- package/src/lib/app-utils/binding-token-catalog.js +293 -0
- package/src/lib/app-utils/binding-token-catalog.js.map +1 -0
- package/src/lib/app-utils/binding-tokens.d.ts +157 -0
- package/src/lib/app-utils/binding-tokens.js +251 -0
- package/src/lib/app-utils/binding-tokens.js.map +1 -0
- package/src/lib/app-utils/breadcrumb-json-ld.d.ts +57 -0
- package/src/lib/app-utils/breadcrumb-json-ld.js +67 -0
- package/src/lib/app-utils/breadcrumb-json-ld.js.map +1 -0
- package/src/lib/app-utils/campaign-attribution.d.ts +117 -0
- package/src/lib/app-utils/campaign-attribution.js +162 -0
- package/src/lib/app-utils/campaign-attribution.js.map +1 -0
- package/src/lib/app-utils/campaign-forwarding.d.ts +220 -0
- package/src/lib/app-utils/campaign-forwarding.js +332 -0
- package/src/lib/app-utils/campaign-forwarding.js.map +1 -0
- package/src/lib/app-utils/campaign-membership.d.ts +109 -0
- package/src/lib/app-utils/campaign-membership.js +176 -0
- package/src/lib/app-utils/campaign-membership.js.map +1 -0
- package/src/lib/app-utils/campaign-touch.d.ts +206 -0
- package/src/lib/app-utils/campaign-touch.js +326 -0
- package/src/lib/app-utils/campaign-touch.js.map +1 -0
- package/src/lib/app-utils/child-contract-compose.d.ts +28 -0
- package/src/lib/app-utils/child-contract-compose.js +140 -0
- package/src/lib/app-utils/child-contract-compose.js.map +1 -0
- package/src/lib/app-utils/child-contract.d.ts +129 -0
- package/src/lib/app-utils/child-contract.js +153 -0
- package/src/lib/app-utils/child-contract.js.map +1 -0
- package/src/lib/app-utils/collection-delete.d.ts +113 -0
- package/src/lib/app-utils/collection-delete.js +120 -0
- package/src/lib/app-utils/collection-delete.js.map +1 -0
- package/src/lib/app-utils/collection-entries.d.ts +833 -0
- package/src/lib/app-utils/collection-entries.js +1285 -0
- package/src/lib/app-utils/collection-entries.js.map +1 -0
- package/src/lib/app-utils/collection-entry-date.d.ts +129 -0
- package/src/lib/app-utils/collection-entry-date.js +183 -0
- package/src/lib/app-utils/collection-entry-date.js.map +1 -0
- package/src/lib/app-utils/collection-kind.d.ts +55 -0
- package/src/lib/app-utils/collection-kind.js +69 -0
- package/src/lib/app-utils/collection-kind.js.map +1 -0
- package/src/lib/app-utils/collection-slug.d.ts +79 -0
- package/src/lib/app-utils/collection-slug.js +70 -0
- package/src/lib/app-utils/collection-slug.js.map +1 -0
- package/src/lib/app-utils/compose-layout-nodes.d.ts +147 -0
- package/src/lib/app-utils/compose-layout-nodes.js +261 -0
- package/src/lib/app-utils/compose-layout-nodes.js.map +1 -0
- package/src/lib/app-utils/compose-layout-props.d.ts +71 -0
- package/src/lib/app-utils/compose-layout-props.js +61 -0
- package/src/lib/app-utils/compose-layout-props.js.map +1 -0
- package/src/lib/app-utils/compose-reusable-components.d.ts +504 -0
- package/src/lib/app-utils/compose-reusable-components.js +1366 -0
- package/src/lib/app-utils/compose-reusable-components.js.map +1 -0
- package/src/lib/app-utils/compress.d.ts +35 -0
- package/src/lib/app-utils/compress.js +38 -0
- package/src/lib/app-utils/compress.js.map +1 -0
- package/src/lib/app-utils/consent-banner-ui.d.ts +226 -0
- package/src/lib/app-utils/consent-banner-ui.js +583 -0
- package/src/lib/app-utils/consent-banner-ui.js.map +1 -0
- package/src/lib/app-utils/consent-groups.d.ts +189 -0
- package/src/lib/app-utils/consent-groups.js +219 -0
- package/src/lib/app-utils/consent-groups.js.map +1 -0
- package/src/lib/app-utils/consent-preferences-dialog.d.ts +58 -0
- package/src/lib/app-utils/consent-preferences-dialog.js +106 -0
- package/src/lib/app-utils/consent-preferences-dialog.js.map +1 -0
- package/src/lib/app-utils/console-record-links.d.ts +163 -0
- package/src/lib/app-utils/console-record-links.js +178 -0
- package/src/lib/app-utils/console-record-links.js.map +1 -0
- package/src/lib/app-utils/console-routes.d.ts +658 -0
- package/src/lib/app-utils/console-routes.js +489 -0
- package/src/lib/app-utils/console-routes.js.map +1 -0
- package/src/lib/app-utils/console-widget-slot-context.d.ts +46 -0
- package/src/lib/app-utils/console-widget-slot-context.js +23 -0
- package/src/lib/app-utils/console-widget-slot-context.js.map +1 -0
- package/src/lib/app-utils/contact-custom-fields.d.ts +191 -0
- package/src/lib/app-utils/contact-custom-fields.js +349 -0
- package/src/lib/app-utils/contact-custom-fields.js.map +1 -0
- package/src/lib/app-utils/contact-holder.d.ts +52 -0
- package/src/lib/app-utils/contact-holder.js +98 -0
- package/src/lib/app-utils/contact-holder.js.map +1 -0
- package/src/lib/app-utils/contact-merge.d.ts +136 -0
- package/src/lib/app-utils/contact-merge.js +379 -0
- package/src/lib/app-utils/contact-merge.js.map +1 -0
- package/src/lib/app-utils/contacts.d.ts +554 -0
- package/src/lib/app-utils/contacts.js +401 -0
- package/src/lib/app-utils/contacts.js.map +1 -0
- package/src/lib/app-utils/content-author-profile.d.ts +68 -0
- package/src/lib/app-utils/content-author-profile.js +118 -0
- package/src/lib/app-utils/content-author-profile.js.map +1 -0
- package/src/lib/app-utils/content-authors.d.ts +662 -0
- package/src/lib/app-utils/content-authors.js +771 -0
- package/src/lib/app-utils/content-authors.js.map +1 -0
- package/src/lib/app-utils/content-schema-type.d.ts +81 -0
- package/src/lib/app-utils/content-schema-type.js +87 -0
- package/src/lib/app-utils/content-schema-type.js.map +1 -0
- package/src/lib/app-utils/contexts.d.ts +35 -0
- package/src/lib/app-utils/contexts.js +35 -0
- package/src/lib/app-utils/contexts.js.map +1 -0
- package/src/lib/app-utils/create-resource-uid.d.ts +18 -0
- package/src/lib/app-utils/create-resource-uid.js +23 -0
- package/src/lib/app-utils/create-resource-uid.js.map +1 -0
- package/src/lib/app-utils/crm-booking.d.ts +75 -0
- package/src/lib/app-utils/crm-booking.js +133 -0
- package/src/lib/app-utils/crm-booking.js.map +1 -0
- package/src/lib/app-utils/crm-csv.d.ts +232 -0
- package/src/lib/app-utils/crm-csv.js +432 -0
- package/src/lib/app-utils/crm-csv.js.map +1 -0
- package/src/lib/app-utils/crm-digest.d.ts +179 -0
- package/src/lib/app-utils/crm-digest.js +271 -0
- package/src/lib/app-utils/crm-digest.js.map +1 -0
- package/src/lib/app-utils/crm-email-templates.d.ts +172 -0
- package/src/lib/app-utils/crm-email-templates.js +382 -0
- package/src/lib/app-utils/crm-email-templates.js.map +1 -0
- package/src/lib/app-utils/crm-inbound.d.ts +245 -0
- package/src/lib/app-utils/crm-inbound.js +407 -0
- package/src/lib/app-utils/crm-inbound.js.map +1 -0
- package/src/lib/app-utils/crm-kinds.d.ts +73 -0
- package/src/lib/app-utils/crm-kinds.js +92 -0
- package/src/lib/app-utils/crm-kinds.js.map +1 -0
- package/src/lib/app-utils/crm-next-activity.d.ts +107 -0
- package/src/lib/app-utils/crm-next-activity.js +140 -0
- package/src/lib/app-utils/crm-next-activity.js.map +1 -0
- package/src/lib/app-utils/crm-reports.d.ts +479 -0
- package/src/lib/app-utils/crm-reports.js +680 -0
- package/src/lib/app-utils/crm-reports.js.map +1 -0
- package/src/lib/app-utils/crm-task-reminders.d.ts +129 -0
- package/src/lib/app-utils/crm-task-reminders.js +139 -0
- package/src/lib/app-utils/crm-task-reminders.js.map +1 -0
- package/src/lib/app-utils/crm.d.ts +1546 -0
- package/src/lib/app-utils/crm.js +1814 -0
- package/src/lib/app-utils/crm.js.map +1 -0
- package/src/lib/app-utils/csp-report.d.ts +84 -0
- package/src/lib/app-utils/csp-report.js +177 -0
- package/src/lib/app-utils/csp-report.js.map +1 -0
- package/src/lib/app-utils/csv-import.d.ts +192 -0
- package/src/lib/app-utils/csv-import.js +279 -0
- package/src/lib/app-utils/csv-import.js.map +1 -0
- package/src/lib/app-utils/dataset-csv.d.ts +109 -0
- package/src/lib/app-utils/dataset-csv.js +235 -0
- package/src/lib/app-utils/dataset-csv.js.map +1 -0
- package/src/lib/app-utils/dataset-models.d.ts +194 -0
- package/src/lib/app-utils/dataset-models.js +409 -0
- package/src/lib/app-utils/dataset-models.js.map +1 -0
- package/src/lib/app-utils/dataset-query.d.ts +57 -0
- package/src/lib/app-utils/dataset-query.js +126 -0
- package/src/lib/app-utils/dataset-query.js.map +1 -0
- package/src/lib/app-utils/datasets.d.ts +136 -0
- package/src/lib/app-utils/datasets.js +177 -0
- package/src/lib/app-utils/datasets.js.map +1 -0
- package/src/lib/app-utils/decompress.d.ts +36 -0
- package/src/lib/app-utils/decompress.js +32 -0
- package/src/lib/app-utils/decompress.js.map +1 -0
- package/src/lib/app-utils/dedicated-sending-domain.d.ts +47 -0
- package/src/lib/app-utils/dedicated-sending-domain.js +114 -0
- package/src/lib/app-utils/dedicated-sending-domain.js.map +1 -0
- package/src/lib/app-utils/deferred-image.d.ts +86 -0
- package/src/lib/app-utils/deferred-image.js +83 -0
- package/src/lib/app-utils/deferred-image.js.map +1 -0
- package/src/lib/app-utils/definition-canvas-tree.d.ts +61 -0
- package/src/lib/app-utils/definition-canvas-tree.js +126 -0
- package/src/lib/app-utils/definition-canvas-tree.js.map +1 -0
- package/src/lib/app-utils/deployment-shape.d.ts +167 -0
- package/src/lib/app-utils/deployment-shape.js +238 -0
- package/src/lib/app-utils/deployment-shape.js.map +1 -0
- package/src/lib/app-utils/detect-template-placeholders.d.ts +30 -0
- package/src/lib/app-utils/detect-template-placeholders.js +53 -0
- package/src/lib/app-utils/detect-template-placeholders.js.map +1 -0
- package/src/lib/app-utils/dmca-counter-notice.d.ts +185 -0
- package/src/lib/app-utils/dmca-counter-notice.js +277 -0
- package/src/lib/app-utils/dmca-counter-notice.js.map +1 -0
- package/src/lib/app-utils/docs-deflection.d.ts +156 -0
- package/src/lib/app-utils/docs-deflection.js +547 -0
- package/src/lib/app-utils/docs-deflection.js.map +1 -0
- package/src/lib/app-utils/docs-help.d.ts +57 -0
- package/src/lib/app-utils/docs-help.generated.d.ts +303 -0
- package/src/lib/app-utils/docs-help.generated.js +867 -0
- package/src/lib/app-utils/docs-help.generated.js.map +1 -0
- package/src/lib/app-utils/docs-help.js +46 -0
- package/src/lib/app-utils/docs-help.js.map +1 -0
- package/src/lib/app-utils/docs-index.generated.d.ts +29 -0
- package/src/lib/app-utils/docs-index.generated.js +8388 -0
- package/src/lib/app-utils/docs-index.generated.js.map +1 -0
- package/src/lib/app-utils/docs-retrieval.d.ts +67 -0
- package/src/lib/app-utils/docs-retrieval.js +188 -0
- package/src/lib/app-utils/docs-retrieval.js.map +1 -0
- package/src/lib/app-utils/document-landmark.d.ts +50 -0
- package/src/lib/app-utils/document-landmark.js +100 -0
- package/src/lib/app-utils/document-landmark.js.map +1 -0
- package/src/lib/app-utils/duplicate-resource.d.ts +101 -0
- package/src/lib/app-utils/duplicate-resource.js +206 -0
- package/src/lib/app-utils/duplicate-resource.js.map +1 -0
- package/src/lib/app-utils/dynamic-list-rule.d.ts +471 -0
- package/src/lib/app-utils/dynamic-list-rule.js +914 -0
- package/src/lib/app-utils/dynamic-list-rule.js.map +1 -0
- package/src/lib/app-utils/element-animation.d.ts +200 -0
- package/src/lib/app-utils/element-animation.js +233 -0
- package/src/lib/app-utils/element-animation.js.map +1 -0
- package/src/lib/app-utils/element-hidden-style.d.ts +46 -0
- package/src/lib/app-utils/element-hidden-style.js +48 -0
- package/src/lib/app-utils/element-hidden-style.js.map +1 -0
- package/src/lib/app-utils/element-ui.d.ts +243 -0
- package/src/lib/app-utils/element-ui.js +459 -0
- package/src/lib/app-utils/element-ui.js.map +1 -0
- package/src/lib/app-utils/email-starter-policy.d.ts +160 -0
- package/src/lib/app-utils/email-starter-policy.js +327 -0
- package/src/lib/app-utils/email-starter-policy.js.map +1 -0
- package/src/lib/app-utils/email-topics.d.ts +310 -0
- package/src/lib/app-utils/email-topics.js +336 -0
- package/src/lib/app-utils/email-topics.js.map +1 -0
- package/src/lib/app-utils/enabled-plugins-context.d.ts +100 -0
- package/src/lib/app-utils/enabled-plugins-context.js +113 -0
- package/src/lib/app-utils/enabled-plugins-context.js.map +1 -0
- package/src/lib/app-utils/ensure-canvas-root.d.ts +38 -0
- package/src/lib/app-utils/ensure-canvas-root.js +61 -0
- package/src/lib/app-utils/ensure-canvas-root.js.map +1 -0
- package/src/lib/app-utils/entity-picker-context.d.ts +199 -0
- package/src/lib/app-utils/entity-picker-context.js +93 -0
- package/src/lib/app-utils/entity-picker-context.js.map +1 -0
- package/src/lib/app-utils/error-beacon.d.ts +107 -0
- package/src/lib/app-utils/error-beacon.js +296 -0
- package/src/lib/app-utils/error-beacon.js.map +1 -0
- package/src/lib/app-utils/expand-repeatables.d.ts +172 -0
- package/src/lib/app-utils/expand-repeatables.js +299 -0
- package/src/lib/app-utils/expand-repeatables.js.map +1 -0
- package/src/lib/app-utils/foreign-script.d.ts +82 -0
- package/src/lib/app-utils/foreign-script.js +102 -0
- package/src/lib/app-utils/foreign-script.js.map +1 -0
- package/src/lib/app-utils/form-abuse-ceiling.d.ts +146 -0
- package/src/lib/app-utils/form-abuse-ceiling.js +158 -0
- package/src/lib/app-utils/form-abuse-ceiling.js.map +1 -0
- package/src/lib/app-utils/form-contract.d.ts +198 -0
- package/src/lib/app-utils/form-contract.js +282 -0
- package/src/lib/app-utils/form-contract.js.map +1 -0
- package/src/lib/app-utils/form-dataset-binding.d.ts +50 -0
- package/src/lib/app-utils/form-dataset-binding.js +74 -0
- package/src/lib/app-utils/form-dataset-binding.js.map +1 -0
- package/src/lib/app-utils/forms.d.ts +727 -0
- package/src/lib/app-utils/forms.js +777 -0
- package/src/lib/app-utils/forms.js.map +1 -0
- package/src/lib/app-utils/functions.d.ts +188 -0
- package/src/lib/app-utils/functions.js +529 -0
- package/src/lib/app-utils/functions.js.map +1 -0
- package/src/lib/app-utils/guarded-version-save.d.ts +91 -0
- package/src/lib/app-utils/guarded-version-save.js +131 -0
- package/src/lib/app-utils/guarded-version-save.js.map +1 -0
- package/src/lib/app-utils/health-report.d.ts +1766 -0
- package/src/lib/app-utils/health-report.js +2072 -0
- package/src/lib/app-utils/health-report.js.map +1 -0
- package/src/lib/app-utils/host-naming.d.ts +135 -0
- package/src/lib/app-utils/host-naming.js +188 -0
- package/src/lib/app-utils/host-naming.js.map +1 -0
- package/src/lib/app-utils/host-permissions.d.ts +76 -0
- package/src/lib/app-utils/host-permissions.js +119 -0
- package/src/lib/app-utils/host-permissions.js.map +1 -0
- package/src/lib/app-utils/host-tokens.d.ts +228 -0
- package/src/lib/app-utils/host-tokens.js +304 -0
- package/src/lib/app-utils/host-tokens.js.map +1 -0
- package/src/lib/app-utils/idp-profile.d.ts +83 -0
- package/src/lib/app-utils/idp-profile.js +268 -0
- package/src/lib/app-utils/idp-profile.js.map +1 -0
- package/src/lib/app-utils/image-upload-types.d.ts +49 -0
- package/src/lib/app-utils/image-upload-types.js +86 -0
- package/src/lib/app-utils/image-upload-types.js.map +1 -0
- package/src/lib/app-utils/index.d.ts +18 -0
- package/src/lib/app-utils/index.js +23 -0
- package/src/lib/app-utils/index.js.map +1 -0
- package/src/lib/app-utils/internal-traffic.d.ts +197 -0
- package/src/lib/app-utils/internal-traffic.js +288 -0
- package/src/lib/app-utils/internal-traffic.js.map +1 -0
- package/src/lib/app-utils/lineal-order.d.ts +62 -0
- package/src/lib/app-utils/lineal-order.js +65 -0
- package/src/lib/app-utils/lineal-order.js.map +1 -0
- package/src/lib/app-utils/link-references.d.ts +36 -0
- package/src/lib/app-utils/link-references.js +89 -0
- package/src/lib/app-utils/link-references.js.map +1 -0
- package/src/lib/app-utils/link-target-search-context.d.ts +123 -0
- package/src/lib/app-utils/link-target-search-context.js +221 -0
- package/src/lib/app-utils/link-target-search-context.js.map +1 -0
- package/src/lib/app-utils/list-assignment-policy.d.ts +169 -0
- package/src/lib/app-utils/list-assignment-policy.js +170 -0
- package/src/lib/app-utils/list-assignment-policy.js.map +1 -0
- package/src/lib/app-utils/list-import.d.ts +158 -0
- package/src/lib/app-utils/list-import.js +332 -0
- package/src/lib/app-utils/list-import.js.map +1 -0
- package/src/lib/app-utils/llms-txt.d.ts +104 -0
- package/src/lib/app-utils/llms-txt.js +144 -0
- package/src/lib/app-utils/llms-txt.js.map +1 -0
- package/src/lib/app-utils/local-storage-budget.d.ts +75 -0
- package/src/lib/app-utils/local-storage-budget.js +153 -0
- package/src/lib/app-utils/local-storage-budget.js.map +1 -0
- package/src/lib/app-utils/lockdown.d.ts +698 -0
- package/src/lib/app-utils/lockdown.js +929 -0
- package/src/lib/app-utils/lockdown.js.map +1 -0
- package/src/lib/app-utils/margin-utilization.d.ts +267 -0
- package/src/lib/app-utils/margin-utilization.js +351 -0
- package/src/lib/app-utils/margin-utilization.js.map +1 -0
- package/src/lib/app-utils/markdown-lite.d.ts +297 -0
- package/src/lib/app-utils/markdown-lite.js +705 -0
- package/src/lib/app-utils/markdown-lite.js.map +1 -0
- package/src/lib/app-utils/marketing-consent.d.ts +704 -0
- package/src/lib/app-utils/marketing-consent.js +783 -0
- package/src/lib/app-utils/marketing-consent.js.map +1 -0
- package/src/lib/app-utils/marketplace-listing-visibility.d.ts +120 -0
- package/src/lib/app-utils/marketplace-listing-visibility.js +139 -0
- package/src/lib/app-utils/marketplace-listing-visibility.js.map +1 -0
- package/src/lib/app-utils/marketplace-overrides.d.ts +271 -0
- package/src/lib/app-utils/marketplace-overrides.js +462 -0
- package/src/lib/app-utils/marketplace-overrides.js.map +1 -0
- package/src/lib/app-utils/marketplace-provenance.d.ts +150 -0
- package/src/lib/app-utils/marketplace-provenance.js +136 -0
- package/src/lib/app-utils/marketplace-provenance.js.map +1 -0
- package/src/lib/app-utils/marketplace-theme.d.ts +237 -0
- package/src/lib/app-utils/marketplace-theme.js +525 -0
- package/src/lib/app-utils/marketplace-theme.js.map +1 -0
- package/src/lib/app-utils/marketplace-update-state.d.ts +119 -0
- package/src/lib/app-utils/marketplace-update-state.js +132 -0
- package/src/lib/app-utils/marketplace-update-state.js.map +1 -0
- package/src/lib/app-utils/marketplace-verification.d.ts +95 -0
- package/src/lib/app-utils/marketplace-verification.js +81 -0
- package/src/lib/app-utils/marketplace-verification.js.map +1 -0
- package/src/lib/app-utils/measure-node-map.d.ts +76 -0
- package/src/lib/app-utils/measure-node-map.js +111 -0
- package/src/lib/app-utils/measure-node-map.js.map +1 -0
- package/src/lib/app-utils/media-alt.d.ts +55 -0
- package/src/lib/app-utils/media-alt.js +58 -0
- package/src/lib/app-utils/media-alt.js.map +1 -0
- package/src/lib/app-utils/media-asset-facts.d.ts +125 -0
- package/src/lib/app-utils/media-asset-facts.js +467 -0
- package/src/lib/app-utils/media-asset-facts.js.map +1 -0
- package/src/lib/app-utils/media-cdn-scope.d.ts +65 -0
- package/src/lib/app-utils/media-cdn-scope.js +75 -0
- package/src/lib/app-utils/media-cdn-scope.js.map +1 -0
- package/src/lib/app-utils/media-folders.d.ts +161 -0
- package/src/lib/app-utils/media-folders.js +230 -0
- package/src/lib/app-utils/media-folders.js.map +1 -0
- package/src/lib/app-utils/media-metadata.d.ts +277 -0
- package/src/lib/app-utils/media-metadata.js +388 -0
- package/src/lib/app-utils/media-metadata.js.map +1 -0
- package/src/lib/app-utils/media-picker-context.d.ts +93 -0
- package/src/lib/app-utils/media-picker-context.js +26 -0
- package/src/lib/app-utils/media-picker-context.js.map +1 -0
- package/src/lib/app-utils/media-quarantine.d.ts +247 -0
- package/src/lib/app-utils/media-quarantine.js +323 -0
- package/src/lib/app-utils/media-quarantine.js.map +1 -0
- package/src/lib/app-utils/media-ref.d.ts +661 -0
- package/src/lib/app-utils/media-ref.js +1055 -0
- package/src/lib/app-utils/media-ref.js.map +1 -0
- package/src/lib/app-utils/media-takedown-reach.d.ts +126 -0
- package/src/lib/app-utils/media-takedown-reach.js +143 -0
- package/src/lib/app-utils/media-takedown-reach.js.map +1 -0
- package/src/lib/app-utils/member-email-aliases.d.ts +180 -0
- package/src/lib/app-utils/member-email-aliases.js +217 -0
- package/src/lib/app-utils/member-email-aliases.js.map +1 -0
- package/src/lib/app-utils/merge-node-sx.d.ts +47 -0
- package/src/lib/app-utils/merge-node-sx.js +123 -0
- package/src/lib/app-utils/merge-node-sx.js.map +1 -0
- package/src/lib/app-utils/name-match.d.ts +155 -0
- package/src/lib/app-utils/name-match.js +175 -0
- package/src/lib/app-utils/name-match.js.map +1 -0
- package/src/lib/app-utils/name-search.d.ts +117 -0
- package/src/lib/app-utils/name-search.js +145 -0
- package/src/lib/app-utils/name-search.js.map +1 -0
- package/src/lib/app-utils/node-capabilities.d.ts +85 -0
- package/src/lib/app-utils/node-capabilities.js +88 -0
- package/src/lib/app-utils/node-capabilities.js.map +1 -0
- package/src/lib/app-utils/node-definition-sanitizer.d.ts +164 -0
- package/src/lib/app-utils/node-definition-sanitizer.js +402 -0
- package/src/lib/app-utils/node-definition-sanitizer.js.map +1 -0
- package/src/lib/app-utils/node-identity.d.ts +47 -0
- package/src/lib/app-utils/node-identity.js +50 -0
- package/src/lib/app-utils/node-identity.js.map +1 -0
- package/src/lib/app-utils/node-interactions.d.ts +102 -0
- package/src/lib/app-utils/node-interactions.js +192 -0
- package/src/lib/app-utils/node-interactions.js.map +1 -0
- package/src/lib/app-utils/node-url-policy.d.ts +54 -0
- package/src/lib/app-utils/node-url-policy.js +72 -0
- package/src/lib/app-utils/node-url-policy.js.map +1 -0
- package/src/lib/app-utils/notifications.d.ts +71 -0
- package/src/lib/app-utils/notifications.js +101 -0
- package/src/lib/app-utils/notifications.js.map +1 -0
- package/src/lib/app-utils/onboarding-deep-link.d.ts +120 -0
- package/src/lib/app-utils/onboarding-deep-link.js +142 -0
- package/src/lib/app-utils/onboarding-deep-link.js.map +1 -0
- package/src/lib/app-utils/operator-identity.d.ts +207 -0
- package/src/lib/app-utils/operator-identity.js +186 -0
- package/src/lib/app-utils/operator-identity.js.map +1 -0
- package/src/lib/app-utils/org-billing-doc.d.ts +231 -0
- package/src/lib/app-utils/org-billing-doc.js +238 -0
- package/src/lib/app-utils/org-billing-doc.js.map +1 -0
- package/src/lib/app-utils/org-override-reason.d.ts +100 -0
- package/src/lib/app-utils/org-override-reason.js +116 -0
- package/src/lib/app-utils/org-override-reason.js.map +1 -0
- package/src/lib/app-utils/org-permissions.d.ts +194 -0
- package/src/lib/app-utils/org-permissions.js +357 -0
- package/src/lib/app-utils/org-permissions.js.map +1 -0
- package/src/lib/app-utils/org-roles.d.ts +72 -0
- package/src/lib/app-utils/org-roles.js +131 -0
- package/src/lib/app-utils/org-roles.js.map +1 -0
- package/src/lib/app-utils/organizations.d.ts +407 -0
- package/src/lib/app-utils/organizations.js +511 -0
- package/src/lib/app-utils/organizations.js.map +1 -0
- package/src/lib/app-utils/page-header-actions-context.d.ts +83 -0
- package/src/lib/app-utils/page-header-actions-context.js +58 -0
- package/src/lib/app-utils/page-header-actions-context.js.map +1 -0
- package/src/lib/app-utils/page-header-record-context.d.ts +80 -0
- package/src/lib/app-utils/page-header-record-context.js +64 -0
- package/src/lib/app-utils/page-header-record-context.js.map +1 -0
- package/src/lib/app-utils/page-markdown.d.ts +103 -0
- package/src/lib/app-utils/page-markdown.js +385 -0
- package/src/lib/app-utils/page-markdown.js.map +1 -0
- package/src/lib/app-utils/paid-media-source.d.ts +90 -0
- package/src/lib/app-utils/paid-media-source.js +184 -0
- package/src/lib/app-utils/paid-media-source.js.map +1 -0
- package/src/lib/app-utils/palette-sx.d.ts +34 -0
- package/src/lib/app-utils/palette-sx.js +150 -0
- package/src/lib/app-utils/palette-sx.js.map +1 -0
- package/src/lib/app-utils/password-policy.d.ts +47 -0
- package/src/lib/app-utils/password-policy.js +46 -0
- package/src/lib/app-utils/password-policy.js.map +1 -0
- package/src/lib/app-utils/payments-configured.d.ts +84 -0
- package/src/lib/app-utils/payments-configured.js +88 -0
- package/src/lib/app-utils/payments-configured.js.map +1 -0
- package/src/lib/app-utils/person-erasure.d.ts +126 -0
- package/src/lib/app-utils/person-erasure.js +121 -0
- package/src/lib/app-utils/person-erasure.js.map +1 -0
- package/src/lib/app-utils/person-key.d.ts +32 -0
- package/src/lib/app-utils/person-key.js +62 -0
- package/src/lib/app-utils/person-key.js.map +1 -0
- package/src/lib/app-utils/plan-entitlements.d.ts +2756 -0
- package/src/lib/app-utils/plan-entitlements.js +4085 -0
- package/src/lib/app-utils/plan-entitlements.js.map +1 -0
- package/src/lib/app-utils/platform-ad-conversions.d.ts +122 -0
- package/src/lib/app-utils/platform-ad-conversions.js +174 -0
- package/src/lib/app-utils/platform-ad-conversions.js.map +1 -0
- package/src/lib/app-utils/platform-advertising-tags.d.ts +139 -0
- package/src/lib/app-utils/platform-advertising-tags.js +203 -0
- package/src/lib/app-utils/platform-advertising-tags.js.map +1 -0
- package/src/lib/app-utils/platform-brand.d.ts +151 -0
- package/src/lib/app-utils/platform-brand.js +175 -0
- package/src/lib/app-utils/platform-brand.js.map +1 -0
- package/src/lib/app-utils/platform-consent-default.d.ts +142 -0
- package/src/lib/app-utils/platform-consent-default.js +295 -0
- package/src/lib/app-utils/platform-consent-default.js.map +1 -0
- package/src/lib/app-utils/platform-marketing-consent.d.ts +151 -0
- package/src/lib/app-utils/platform-marketing-consent.js +182 -0
- package/src/lib/app-utils/platform-marketing-consent.js.map +1 -0
- package/src/lib/app-utils/platform-marketing-host.d.ts +33 -0
- package/src/lib/app-utils/platform-marketing-host.js +97 -0
- package/src/lib/app-utils/platform-marketing-host.js.map +1 -0
- package/src/lib/app-utils/platform-visitor-consent.d.ts +252 -0
- package/src/lib/app-utils/platform-visitor-consent.js +533 -0
- package/src/lib/app-utils/platform-visitor-consent.js.map +1 -0
- package/src/lib/app-utils/plugin-api-cross-origin.d.ts +61 -0
- package/src/lib/app-utils/plugin-api-cross-origin.js +202 -0
- package/src/lib/app-utils/plugin-api-cross-origin.js.map +1 -0
- package/src/lib/app-utils/plugin-api-rate-limit.d.ts +192 -0
- package/src/lib/app-utils/plugin-api-rate-limit.js +270 -0
- package/src/lib/app-utils/plugin-api-rate-limit.js.map +1 -0
- package/src/lib/app-utils/plugin-artifact-path.d.ts +32 -0
- package/src/lib/app-utils/plugin-artifact-path.js +33 -0
- package/src/lib/app-utils/plugin-artifact-path.js.map +1 -0
- package/src/lib/app-utils/plugin-bundle-checks.d.ts +148 -0
- package/src/lib/app-utils/plugin-bundle-checks.js +989 -0
- package/src/lib/app-utils/plugin-bundle-checks.js.map +1 -0
- package/src/lib/app-utils/plugin-manifest.d.ts +516 -0
- package/src/lib/app-utils/plugin-manifest.js +687 -0
- package/src/lib/app-utils/plugin-manifest.js.map +1 -0
- package/src/lib/app-utils/published-legal-pages.d.ts +71 -0
- package/src/lib/app-utils/published-legal-pages.js +90 -0
- package/src/lib/app-utils/published-legal-pages.js.map +1 -0
- package/src/lib/app-utils/publisher-agreement.d.ts +254 -0
- package/src/lib/app-utils/publisher-agreement.js +274 -0
- package/src/lib/app-utils/publisher-agreement.js.map +1 -0
- package/src/lib/app-utils/publisher-attestation.d.ts +99 -0
- package/src/lib/app-utils/publisher-attestation.js +158 -0
- package/src/lib/app-utils/publisher-attestation.js.map +1 -0
- package/src/lib/app-utils/recipient-email-render.d.ts +216 -0
- package/src/lib/app-utils/recipient-email-render.js +221 -0
- package/src/lib/app-utils/recipient-email-render.js.map +1 -0
- package/src/lib/app-utils/redispatch-caught-error.d.ts +38 -0
- package/src/lib/app-utils/redispatch-caught-error.js +46 -0
- package/src/lib/app-utils/redispatch-caught-error.js.map +1 -0
- package/src/lib/app-utils/registering-plugin.d.ts +19 -0
- package/src/lib/app-utils/registering-plugin.js +38 -0
- package/src/lib/app-utils/registering-plugin.js.map +1 -0
- package/src/lib/app-utils/release-flags.d.ts +283 -0
- package/src/lib/app-utils/release-flags.js +518 -0
- package/src/lib/app-utils/release-flags.js.map +1 -0
- package/src/lib/app-utils/repair-canvas-nodes.d.ts +130 -0
- package/src/lib/app-utils/repair-canvas-nodes.js +298 -0
- package/src/lib/app-utils/repair-canvas-nodes.js.map +1 -0
- package/src/lib/app-utils/repeat-infringer.d.ts +166 -0
- package/src/lib/app-utils/repeat-infringer.js +188 -0
- package/src/lib/app-utils/repeat-infringer.js.map +1 -0
- package/src/lib/app-utils/repeat-sources.d.ts +115 -0
- package/src/lib/app-utils/repeat-sources.js +86 -0
- package/src/lib/app-utils/repeat-sources.js.map +1 -0
- package/src/lib/app-utils/request-geo.d.ts +114 -0
- package/src/lib/app-utils/request-geo.js +247 -0
- package/src/lib/app-utils/request-geo.js.map +1 -0
- package/src/lib/app-utils/request-ip.d.ts +213 -0
- package/src/lib/app-utils/request-ip.js +344 -0
- package/src/lib/app-utils/request-ip.js.map +1 -0
- package/src/lib/app-utils/resolve-named-tokens.d.ts +26 -0
- package/src/lib/app-utils/resolve-named-tokens.js +59 -0
- package/src/lib/app-utils/resolve-named-tokens.js.map +1 -0
- package/src/lib/app-utils/responsive-typography-sx.d.ts +77 -0
- package/src/lib/app-utils/responsive-typography-sx.js +122 -0
- package/src/lib/app-utils/responsive-typography-sx.js.map +1 -0
- package/src/lib/app-utils/reusable-component-keys.d.ts +135 -0
- package/src/lib/app-utils/reusable-component-keys.js +140 -0
- package/src/lib/app-utils/reusable-component-keys.js.map +1 -0
- package/src/lib/app-utils/reusable-prop-values.d.ts +199 -0
- package/src/lib/app-utils/reusable-prop-values.js +494 -0
- package/src/lib/app-utils/reusable-prop-values.js.map +1 -0
- package/src/lib/app-utils/safe-json-ld.d.ts +29 -0
- package/src/lib/app-utils/safe-json-ld.js +37 -0
- package/src/lib/app-utils/safe-json-ld.js.map +1 -0
- package/src/lib/app-utils/sanitize-svg.d.ts +55 -0
- package/src/lib/app-utils/sanitize-svg.js +460 -0
- package/src/lib/app-utils/sanitize-svg.js.map +1 -0
- package/src/lib/app-utils/scheme-sx.d.ts +84 -0
- package/src/lib/app-utils/scheme-sx.js +148 -0
- package/src/lib/app-utils/scheme-sx.js.map +1 -0
- package/src/lib/app-utils/scope-tokens.d.ts +249 -0
- package/src/lib/app-utils/scope-tokens.js +331 -0
- package/src/lib/app-utils/scope-tokens.js.map +1 -0
- package/src/lib/app-utils/screen-link-context-value.d.ts +57 -0
- package/src/lib/app-utils/screen-link-context-value.js +43 -0
- package/src/lib/app-utils/screen-link-context-value.js.map +1 -0
- package/src/lib/app-utils/screen-link-context.d.ts +185 -0
- package/src/lib/app-utils/screen-link-context.js +304 -0
- package/src/lib/app-utils/screen-link-context.js.map +1 -0
- package/src/lib/app-utils/screen-link-value.d.ts +269 -0
- package/src/lib/app-utils/screen-link-value.js +384 -0
- package/src/lib/app-utils/screen-link-value.js.map +1 -0
- package/src/lib/app-utils/screen-route.d.ts +669 -0
- package/src/lib/app-utils/screen-route.js +751 -0
- package/src/lib/app-utils/screen-route.js.map +1 -0
- package/src/lib/app-utils/screen-seo-fields.d.ts +37 -0
- package/src/lib/app-utils/screen-seo-fields.js +42 -0
- package/src/lib/app-utils/screen-seo-fields.js.map +1 -0
- package/src/lib/app-utils/search-indexing.d.ts +162 -0
- package/src/lib/app-utils/search-indexing.js +207 -0
- package/src/lib/app-utils/search-indexing.js.map +1 -0
- package/src/lib/app-utils/seo-listing-fields.d.ts +70 -0
- package/src/lib/app-utils/seo-listing-fields.js +75 -0
- package/src/lib/app-utils/seo-listing-fields.js.map +1 -0
- package/src/lib/app-utils/seo-locale.d.ts +119 -0
- package/src/lib/app-utils/seo-locale.js +133 -0
- package/src/lib/app-utils/seo-locale.js.map +1 -0
- package/src/lib/app-utils/seo-title-variables.d.ts +149 -0
- package/src/lib/app-utils/seo-title-variables.js +190 -0
- package/src/lib/app-utils/seo-title-variables.js.map +1 -0
- package/src/lib/app-utils/seo-title.d.ts +70 -0
- package/src/lib/app-utils/seo-title.js +117 -0
- package/src/lib/app-utils/seo-title.js.map +1 -0
- package/src/lib/app-utils/server.d.ts +174 -0
- package/src/lib/app-utils/server.js +314 -0
- package/src/lib/app-utils/server.js.map +1 -0
- package/src/lib/app-utils/site-context.d.ts +106 -0
- package/src/lib/app-utils/site-context.js +100 -0
- package/src/lib/app-utils/site-context.js.map +1 -0
- package/src/lib/app-utils/sitemap.d.ts +117 -0
- package/src/lib/app-utils/sitemap.js +183 -0
- package/src/lib/app-utils/sitemap.js.map +1 -0
- package/src/lib/app-utils/social-image.d.ts +112 -0
- package/src/lib/app-utils/social-image.js +191 -0
- package/src/lib/app-utils/social-image.js.map +1 -0
- package/src/lib/app-utils/starter-templates.d.ts +99 -0
- package/src/lib/app-utils/starter-templates.js +579 -0
- package/src/lib/app-utils/starter-templates.js.map +1 -0
- package/src/lib/app-utils/stored-nodes.d.ts +120 -0
- package/src/lib/app-utils/stored-nodes.js +174 -0
- package/src/lib/app-utils/stored-nodes.js.map +1 -0
- package/src/lib/app-utils/strip-undefined.d.ts +59 -0
- package/src/lib/app-utils/strip-undefined.js +95 -0
- package/src/lib/app-utils/strip-undefined.js.map +1 -0
- package/src/lib/app-utils/stripe-deployment-mode.d.ts +47 -0
- package/src/lib/app-utils/stripe-deployment-mode.js +70 -0
- package/src/lib/app-utils/stripe-deployment-mode.js.map +1 -0
- package/src/lib/app-utils/support-tiers.d.ts +108 -0
- package/src/lib/app-utils/support-tiers.js +201 -0
- package/src/lib/app-utils/support-tiers.js.map +1 -0
- package/src/lib/app-utils/timezone-geo-hint.d.ts +36 -0
- package/src/lib/app-utils/timezone-geo-hint.js +180 -0
- package/src/lib/app-utils/timezone-geo-hint.js.map +1 -0
- package/src/lib/app-utils/upload-cors.d.ts +155 -0
- package/src/lib/app-utils/upload-cors.js +254 -0
- package/src/lib/app-utils/upload-cors.js.map +1 -0
- package/src/lib/app-utils/upload-inspection.d.ts +159 -0
- package/src/lib/app-utils/upload-inspection.js +539 -0
- package/src/lib/app-utils/upload-inspection.js.map +1 -0
- package/src/lib/app-utils/url-slug.d.ts +40 -0
- package/src/lib/app-utils/url-slug.js +42 -0
- package/src/lib/app-utils/url-slug.js.map +1 -0
- package/src/lib/app-utils/usage-budget.d.ts +429 -0
- package/src/lib/app-utils/usage-budget.js +421 -0
- package/src/lib/app-utils/usage-budget.js.map +1 -0
- package/src/lib/app-utils/variables.d.ts +96 -0
- package/src/lib/app-utils/variables.js +233 -0
- package/src/lib/app-utils/variables.js.map +1 -0
- package/src/lib/app-utils/video-asset-facts.d.ts +61 -0
- package/src/lib/app-utils/video-asset-facts.js +70 -0
- package/src/lib/app-utils/video-asset-facts.js.map +1 -0
- package/src/lib/app-utils/video-object.d.ts +89 -0
- package/src/lib/app-utils/video-object.js +245 -0
- package/src/lib/app-utils/video-object.js.map +1 -0
- package/src/lib/app-utils/visitor-consent.d.ts +757 -0
- package/src/lib/app-utils/visitor-consent.js +981 -0
- package/src/lib/app-utils/visitor-consent.js.map +1 -0
- package/src/lib/app-utils/visitor-record-ceiling.d.ts +223 -0
- package/src/lib/app-utils/visitor-record-ceiling.js +215 -0
- package/src/lib/app-utils/visitor-record-ceiling.js.map +1 -0
- package/src/lib/app-utils/web-vitals-rum.d.ts +53 -0
- package/src/lib/app-utils/web-vitals-rum.js +278 -0
- package/src/lib/app-utils/web-vitals-rum.js.map +1 -0
- package/src/lib/app-utils/webhook-delivery.d.ts +324 -0
- package/src/lib/app-utils/webhook-delivery.js +413 -0
- package/src/lib/app-utils/webhook-delivery.js.map +1 -0
- package/src/lib/app-utils/where-used.d.ts +57 -0
- package/src/lib/app-utils/where-used.js +59 -0
- package/src/lib/app-utils/where-used.js.map +1 -0
- package/src/lib/app-utils/wistia-embed.d.ts +86 -0
- package/src/lib/app-utils/wistia-embed.js +119 -0
- package/src/lib/app-utils/wistia-embed.js.map +1 -0
- package/src/lib/app-utils/workflows.d.ts +136 -0
- package/src/lib/app-utils/workflows.js +346 -0
- package/src/lib/app-utils/workflows.js.map +1 -0
- package/src/lib/canvas-manager/canvas-manager-tree.d.ts +109 -0
- package/src/lib/canvas-manager/canvas-manager-tree.js +139 -0
- package/src/lib/canvas-manager/canvas-manager-tree.js.map +1 -0
- package/src/lib/canvas-manager/canvas-manager.d.ts +549 -0
- package/src/lib/canvas-manager/canvas-manager.js +1311 -0
- package/src/lib/canvas-manager/canvas-manager.js.map +1 -0
- package/src/lib/canvas-manager/index.d.ts +20 -0
- package/src/lib/canvas-manager/index.js +21 -0
- package/src/lib/canvas-manager/index.js.map +1 -0
- package/src/lib/canvas-manager/stores/index.d.ts +17 -0
- package/src/lib/canvas-manager/stores/index.js +18 -0
- package/src/lib/canvas-manager/stores/index.js.map +1 -0
- package/src/lib/canvas-manager/stores/node.store.d.ts +30 -0
- package/src/lib/canvas-manager/stores/node.store.js +45 -0
- package/src/lib/canvas-manager/stores/node.store.js.map +1 -0
- package/src/lib/components-manager/components-manager.d.ts +56 -0
- package/src/lib/components-manager/components-manager.js +191 -0
- package/src/lib/components-manager/components-manager.js.map +1 -0
- package/src/lib/components-manager/index.d.ts +18 -0
- package/src/lib/components-manager/index.js +19 -0
- package/src/lib/components-manager/index.js.map +1 -0
- package/src/lib/emit-manager/emit-manager.d.ts +56 -0
- package/src/lib/emit-manager/emit-manager.js +60 -0
- package/src/lib/emit-manager/emit-manager.js.map +1 -0
- package/src/lib/emit-manager/index.d.ts +18 -0
- package/src/lib/emit-manager/index.js +19 -0
- package/src/lib/emit-manager/index.js.map +1 -0
- package/src/lib/foundation/constants/_internal.d.ts +18 -0
- package/src/lib/foundation/constants/_internal.js +62 -0
- package/src/lib/foundation/constants/_internal.js.map +1 -0
- package/src/lib/foundation/constants/app.d.ts +23 -0
- package/src/lib/foundation/constants/app.js +25 -0
- package/src/lib/foundation/constants/app.js.map +1 -0
- package/src/lib/foundation/constants/canvas.d.ts +18 -0
- package/src/lib/foundation/constants/canvas.js +18 -0
- package/src/lib/foundation/constants/canvas.js.map +1 -0
- package/src/lib/foundation/constants/components.d.ts +54 -0
- package/src/lib/foundation/constants/components.js +61 -0
- package/src/lib/foundation/constants/components.js.map +1 -0
- package/src/lib/foundation/constants/shared.d.ts +50 -0
- package/src/lib/foundation/constants/shared.js +49 -0
- package/src/lib/foundation/constants/shared.js.map +1 -0
- package/src/lib/foundation/constants/symbol.d.ts +63 -0
- package/src/lib/foundation/constants/symbol.js +75 -0
- package/src/lib/foundation/constants/symbol.js.map +1 -0
- package/src/lib/foundation/definitions/components.types.d.ts +372 -0
- package/src/lib/foundation/definitions/components.types.js +180 -0
- package/src/lib/foundation/definitions/components.types.js.map +1 -0
- package/src/lib/foundation/definitions/contact.types.d.ts +73 -0
- package/src/lib/foundation/definitions/contact.types.js +107 -0
- package/src/lib/foundation/definitions/contact.types.js.map +1 -0
- package/src/lib/foundation/definitions/host-content-collections.d.ts +137 -0
- package/src/lib/foundation/definitions/host-content-collections.js +219 -0
- package/src/lib/foundation/definitions/host-content-collections.js.map +1 -0
- package/src/lib/foundation/definitions/org-billing.types.d.ts +1361 -0
- package/src/lib/foundation/definitions/org-billing.types.js +77 -0
- package/src/lib/foundation/definitions/org-billing.types.js.map +1 -0
- package/src/lib/foundation/definitions/organization.types.d.ts +307 -0
- package/src/lib/foundation/definitions/organization.types.js +42 -0
- package/src/lib/foundation/definitions/organization.types.js.map +1 -0
- package/src/lib/foundation/definitions/platform.types.d.ts +1326 -0
- package/src/lib/foundation/definitions/platform.types.js +124 -0
- package/src/lib/foundation/definitions/platform.types.js.map +1 -0
- package/src/lib/foundation/definitions/property-kinds.d.ts +189 -0
- package/src/lib/foundation/definitions/property-kinds.js +565 -0
- package/src/lib/foundation/definitions/property-kinds.js.map +1 -0
- package/src/lib/foundation/definitions/shared.d.ts +23 -0
- package/src/lib/foundation/definitions/shared.js +18 -0
- package/src/lib/foundation/definitions/shared.js.map +1 -0
- package/src/lib/foundation/definitions/write-deny-coverage.util.d.ts +249 -0
- package/src/lib/foundation/definitions/write-deny-coverage.util.js +499 -0
- package/src/lib/foundation/definitions/write-deny-coverage.util.js.map +1 -0
- package/src/lib/foundation/index.d.ts +32 -0
- package/src/lib/foundation/index.js +67 -0
- package/src/lib/foundation/index.js.map +1 -0
- package/src/lib/lifecycle.d.ts +24 -0
- package/src/lib/lifecycle.js +39 -0
- package/src/lib/lifecycle.js.map +1 -0
- package/src/lib/mst/common.d.ts +17 -0
- package/src/lib/mst/common.js +23 -0
- package/src/lib/mst/common.js.map +1 -0
- package/src/lib/mst/index.d.ts +19 -0
- package/src/lib/mst/index.js +20 -0
- package/src/lib/mst/index.js.map +1 -0
- package/src/lib/mst/json.d.ts +22 -0
- package/src/lib/mst/json.js +23 -0
- package/src/lib/mst/json.js.map +1 -0
- package/src/lib/mst/types.d.ts +20 -0
- package/src/lib/mst/types.js +18 -0
- package/src/lib/mst/types.js.map +1 -0
- package/src/lib/plugin-manager/billing-webhook-hooks.d.ts +77 -0
- package/src/lib/plugin-manager/billing-webhook-hooks.js +55 -0
- package/src/lib/plugin-manager/billing-webhook-hooks.js.map +1 -0
- package/src/lib/plugin-manager/commerce-zone-props.d.ts +172 -0
- package/src/lib/plugin-manager/commerce-zone-props.js +31 -0
- package/src/lib/plugin-manager/commerce-zone-props.js.map +1 -0
- package/src/lib/plugin-manager/custom-fields.d.ts +60 -0
- package/src/lib/plugin-manager/custom-fields.js +39 -0
- package/src/lib/plugin-manager/custom-fields.js.map +1 -0
- package/src/lib/plugin-manager/editor-sessions.d.ts +109 -0
- package/src/lib/plugin-manager/editor-sessions.js +137 -0
- package/src/lib/plugin-manager/editor-sessions.js.map +1 -0
- package/src/lib/plugin-manager/enabled-plugins.d.ts +438 -0
- package/src/lib/plugin-manager/enabled-plugins.js +403 -0
- package/src/lib/plugin-manager/enabled-plugins.js.map +1 -0
- package/src/lib/plugin-manager/feature-plugins.d.ts +1314 -0
- package/src/lib/plugin-manager/feature-plugins.js +609 -0
- package/src/lib/plugin-manager/feature-plugins.js.map +1 -0
- package/src/lib/plugin-manager/first-party-plugins.generated.d.ts +11 -0
- package/src/lib/plugin-manager/first-party-plugins.generated.js +149 -0
- package/src/lib/plugin-manager/first-party-plugins.generated.js.map +1 -0
- package/src/lib/plugin-manager/index.d.ts +42 -0
- package/src/lib/plugin-manager/index.js +46 -0
- package/src/lib/plugin-manager/index.js.map +1 -0
- package/src/lib/plugin-manager/install-presets.d.ts +93 -0
- package/src/lib/plugin-manager/install-presets.js +86 -0
- package/src/lib/plugin-manager/install-presets.js.map +1 -0
- package/src/lib/plugin-manager/media-delivery-provider.d.ts +124 -0
- package/src/lib/plugin-manager/media-delivery-provider.js +53 -0
- package/src/lib/plugin-manager/media-delivery-provider.js.map +1 -0
- package/src/lib/plugin-manager/order-fulfilment.d.ts +142 -0
- package/src/lib/plugin-manager/order-fulfilment.js +104 -0
- package/src/lib/plugin-manager/order-fulfilment.js.map +1 -0
- package/src/lib/plugin-manager/plugin-activity-actions.d.ts +122 -0
- package/src/lib/plugin-manager/plugin-activity-actions.js +140 -0
- package/src/lib/plugin-manager/plugin-activity-actions.js.map +1 -0
- package/src/lib/plugin-manager/plugin-bridge.d.ts +98 -0
- package/src/lib/plugin-manager/plugin-bridge.js +154 -0
- package/src/lib/plugin-manager/plugin-bridge.js.map +1 -0
- package/src/lib/plugin-manager/plugin-config.d.ts +148 -0
- package/src/lib/plugin-manager/plugin-config.js +228 -0
- package/src/lib/plugin-manager/plugin-config.js.map +1 -0
- package/src/lib/plugin-manager/plugin-console-crons.d.ts +139 -0
- package/src/lib/plugin-manager/plugin-console-crons.js +177 -0
- package/src/lib/plugin-manager/plugin-console-crons.js.map +1 -0
- package/src/lib/plugin-manager/plugin-contact-capture.d.ts +220 -0
- package/src/lib/plugin-manager/plugin-contact-capture.js +89 -0
- package/src/lib/plugin-manager/plugin-contact-capture.js.map +1 -0
- package/src/lib/plugin-manager/plugin-contributions.d.ts +244 -0
- package/src/lib/plugin-manager/plugin-contributions.js +283 -0
- package/src/lib/plugin-manager/plugin-contributions.js.map +1 -0
- package/src/lib/plugin-manager/plugin-entitlement-keys.d.ts +169 -0
- package/src/lib/plugin-manager/plugin-entitlement-keys.js +84 -0
- package/src/lib/plugin-manager/plugin-entitlement-keys.js.map +1 -0
- package/src/lib/plugin-manager/plugin-entitlements.d.ts +181 -0
- package/src/lib/plugin-manager/plugin-entitlements.js +188 -0
- package/src/lib/plugin-manager/plugin-entitlements.js.map +1 -0
- package/src/lib/plugin-manager/plugin-events.d.ts +145 -0
- package/src/lib/plugin-manager/plugin-events.js +79 -0
- package/src/lib/plugin-manager/plugin-events.js.map +1 -0
- package/src/lib/plugin-manager/plugin-figures.d.ts +251 -0
- package/src/lib/plugin-manager/plugin-figures.js +252 -0
- package/src/lib/plugin-manager/plugin-figures.js.map +1 -0
- package/src/lib/plugin-manager/plugin-host-collections.d.ts +146 -0
- package/src/lib/plugin-manager/plugin-host-collections.js +116 -0
- package/src/lib/plugin-manager/plugin-host-collections.js.map +1 -0
- package/src/lib/plugin-manager/plugin-jobs.d.ts +130 -0
- package/src/lib/plugin-manager/plugin-jobs.js +182 -0
- package/src/lib/plugin-manager/plugin-jobs.js.map +1 -0
- package/src/lib/plugin-manager/plugin-loader.d.ts +86 -0
- package/src/lib/plugin-manager/plugin-loader.js +223 -0
- package/src/lib/plugin-manager/plugin-loader.js.map +1 -0
- package/src/lib/plugin-manager/plugin-manager.d.ts +95 -0
- package/src/lib/plugin-manager/plugin-manager.js +343 -0
- package/src/lib/plugin-manager/plugin-manager.js.map +1 -0
- package/src/lib/plugin-manager/plugin-metered-lines.d.ts +97 -0
- package/src/lib/plugin-manager/plugin-metered-lines.js +123 -0
- package/src/lib/plugin-manager/plugin-metered-lines.js.map +1 -0
- package/src/lib/plugin-manager/plugin-org-erasure.d.ts +52 -0
- package/src/lib/plugin-manager/plugin-org-erasure.js +100 -0
- package/src/lib/plugin-manager/plugin-org-erasure.js.map +1 -0
- package/src/lib/plugin-manager/plugin-permissions.d.ts +69 -0
- package/src/lib/plugin-manager/plugin-permissions.js +77 -0
- package/src/lib/plugin-manager/plugin-permissions.js.map +1 -0
- package/src/lib/plugin-manager/plugin-person-erasure.d.ts +58 -0
- package/src/lib/plugin-manager/plugin-person-erasure.js +109 -0
- package/src/lib/plugin-manager/plugin-person-erasure.js.map +1 -0
- package/src/lib/plugin-manager/plugin-record-cards.d.ts +99 -0
- package/src/lib/plugin-manager/plugin-record-cards.js +59 -0
- package/src/lib/plugin-manager/plugin-record-cards.js.map +1 -0
- package/src/lib/plugin-manager/plugin-record-facts.d.ts +111 -0
- package/src/lib/plugin-manager/plugin-record-facts.js +51 -0
- package/src/lib/plugin-manager/plugin-record-facts.js.map +1 -0
- package/src/lib/plugin-manager/plugin-record-routes.d.ts +129 -0
- package/src/lib/plugin-manager/plugin-record-routes.js +93 -0
- package/src/lib/plugin-manager/plugin-record-routes.js.map +1 -0
- package/src/lib/plugin-manager/plugin-record-timeline.d.ts +147 -0
- package/src/lib/plugin-manager/plugin-record-timeline.js +39 -0
- package/src/lib/plugin-manager/plugin-record-timeline.js.map +1 -0
- package/src/lib/plugin-manager/plugin-resource-drafts.d.ts +137 -0
- package/src/lib/plugin-manager/plugin-resource-drafts.js +51 -0
- package/src/lib/plugin-manager/plugin-resource-drafts.js.map +1 -0
- package/src/lib/plugin-manager/plugin-services.d.ts +94 -0
- package/src/lib/plugin-manager/plugin-services.js +153 -0
- package/src/lib/plugin-manager/plugin-services.js.map +1 -0
- package/src/lib/plugin-manager/plugin-styles-ui.d.ts +71 -0
- package/src/lib/plugin-manager/plugin-styles-ui.js +80 -0
- package/src/lib/plugin-manager/plugin-styles-ui.js.map +1 -0
- package/src/lib/plugin-manager/plugin-styles.d.ts +176 -0
- package/src/lib/plugin-manager/plugin-styles.js +186 -0
- package/src/lib/plugin-manager/plugin-styles.js.map +1 -0
- package/src/lib/plugin-manager/plugin-subprocessors.d.ts +135 -0
- package/src/lib/plugin-manager/plugin-subprocessors.js +129 -0
- package/src/lib/plugin-manager/plugin-subprocessors.js.map +1 -0
- package/src/lib/plugin-manager/plugin-tax-profile.d.ts +84 -0
- package/src/lib/plugin-manager/plugin-tax-profile.js +39 -0
- package/src/lib/plugin-manager/plugin-tax-profile.js.map +1 -0
- package/src/lib/plugin-manager/plugin-user-erasure.d.ts +53 -0
- package/src/lib/plugin-manager/plugin-user-erasure.js +84 -0
- package/src/lib/plugin-manager/plugin-user-erasure.js.map +1 -0
- package/src/lib/plugin-manager/plugin-zones.d.ts +121 -0
- package/src/lib/plugin-manager/plugin-zones.js +74 -0
- package/src/lib/plugin-manager/plugin-zones.js.map +1 -0
- package/src/lib/plugin-manager/realm-plugins.d.ts +112 -0
- package/src/lib/plugin-manager/realm-plugins.js +196 -0
- package/src/lib/plugin-manager/realm-plugins.js.map +1 -0
- package/src/lib/plugin-manager/realm-server.d.ts +54 -0
- package/src/lib/plugin-manager/realm-server.js +88 -0
- package/src/lib/plugin-manager/realm-server.js.map +1 -0
- package/src/lib/plugin-manager/record-zone-props.d.ts +126 -0
- package/src/lib/plugin-manager/record-zone-props.js +31 -0
- package/src/lib/plugin-manager/record-zone-props.js.map +1 -0
- package/src/lib/plugin-manager/site-page-hooks.d.ts +102 -0
- package/src/lib/plugin-manager/site-page-hooks.js +114 -0
- package/src/lib/plugin-manager/site-page-hooks.js.map +1 -0
- package/src/lib/plugin-manager/site-runtime.d.ts +57 -0
- package/src/lib/plugin-manager/site-runtime.js +25 -0
- package/src/lib/plugin-manager/site-runtime.js.map +1 -0
- package/src/lib/plugin-manager/usage-alert-contributors.d.ts +115 -0
- package/src/lib/plugin-manager/usage-alert-contributors.js +106 -0
- package/src/lib/plugin-manager/usage-alert-contributors.js.map +1 -0
- package/src/lib/types/ast.d.ts +199 -0
- package/src/lib/types/ast.js +20 -0
- package/src/lib/types/ast.js.map +1 -0
- package/src/lib/types/index.d.ts +20 -0
- package/src/lib/types/index.js +21 -0
- package/src/lib/types/index.js.map +1 -0
- package/src/lib/types/nodes.d.ts +608 -0
- package/src/lib/types/nodes.js +28 -0
- package/src/lib/types/nodes.js.map +1 -0
- package/src/lib/types/routing.d.ts +17 -0
- package/src/lib/types/routing.js +18 -0
- package/src/lib/types/routing.js.map +1 -0
- package/src/lib/types/screen.d.ts +23 -0
- package/src/lib/types/screen.js +18 -0
- package/src/lib/types/screen.js.map +1 -0
- package/src/lib/utils.d.ts +25 -0
- package/src/lib/utils.js +42 -0
- package/src/lib/utils.js.map +1 -0
- package/src/server.d.ts +37 -0
- package/src/server.js +55 -0
- package/src/server.js.map +1 -0
|
@@ -0,0 +1,547 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/ import { DOCS_SITE_ORIGIN, docsDocumentFrequency, tokenize } from "./docs-retrieval.js";
|
|
17
|
+
/**
|
|
18
|
+
* Retrieval-first answering for Aglyn Assist (AGL-2486) — the deflection gate.
|
|
19
|
+
*
|
|
20
|
+
* Most assist traffic is "how do I X", and the answer to "how do I X" is
|
|
21
|
+
* already written down in `apps/docs/docs`. Sending that question to a model
|
|
22
|
+
* so the model can read the docs section back to the user pays provider money
|
|
23
|
+
* to reformat prose we wrote ourselves. This module decides when retrieval is
|
|
24
|
+
* confident enough to hand the docs straight over, and composes the answer
|
|
25
|
+
* when it is. Escalation to the model is what happens the rest of the time —
|
|
26
|
+
* it is the fallback, not the default.
|
|
27
|
+
*
|
|
28
|
+
* ## The one rule: never fabricate
|
|
29
|
+
*
|
|
30
|
+
* A deflected answer contains exactly two kinds of text:
|
|
31
|
+
*
|
|
32
|
+
* 1. Fixed template strings from this file, which say nothing about the
|
|
33
|
+
* product — they name the page and introduce the quote.
|
|
34
|
+
* 2. Section text copied VERBATIM out of the docs index, with the URL of
|
|
35
|
+
* the page it came from.
|
|
36
|
+
*
|
|
37
|
+
* There is no summarisation, no paraphrase and no stitching of adjacent
|
|
38
|
+
* sections into a claim neither one makes. The spec asserts it by
|
|
39
|
+
* RECONSTRUCTION — "never fabricate — every word is template or verbatim
|
|
40
|
+
* docs" — stripping the template from a composed answer and requiring what is
|
|
41
|
+
* left to be a prefix of a real section's `text`. That property is the whole
|
|
42
|
+
* safety argument, because a wrong retrieval answer is worse than an
|
|
43
|
+
* escalation — it is confidently wrong prose delivered to a paying customer
|
|
44
|
+
* with a citation under it, which is the shape people trust most.
|
|
45
|
+
*
|
|
46
|
+
* ## What "confident" means
|
|
47
|
+
*
|
|
48
|
+
* Seven conditions, ALL of which must hold. Any one failing escalates; there
|
|
49
|
+
* is no partial-credit path where a weak match produces a hedged answer,
|
|
50
|
+
* because a hedged wrong answer is still a wrong answer and it has already
|
|
51
|
+
* cost the user the click.
|
|
52
|
+
*
|
|
53
|
+
* 1. **The question stands on its own.** A follow-up is usually not
|
|
54
|
+
* self-contained: "does that work on the free plan?" retrieves the
|
|
55
|
+
* billing pages beautifully and answers a question nobody asked. The
|
|
56
|
+
* conversation is the missing half and only the model has it.
|
|
57
|
+
*
|
|
58
|
+
* The gate is NOT "no prior turn" (AGL-2486). Not every follow-up leans
|
|
59
|
+
* on the transcript: the second question in a thread is very often a
|
|
60
|
+
* fresh, complete question that happens to be asked second. Refusing all
|
|
61
|
+
* of them means a thread answers its first question from the docs and
|
|
62
|
+
* then escalates forever — and on a deployment with no AI provider
|
|
63
|
+
* key that reads as "Aglyn Assist is not configured",
|
|
64
|
+
* one question in, to a user who just watched it work. A product that
|
|
65
|
+
* answers exactly once per thread is worse than one that never answers,
|
|
66
|
+
* because the second refusal looks like a fault rather than a limit.
|
|
67
|
+
*
|
|
68
|
+
* So the gate now asks whether THIS question stands alone, and holds a
|
|
69
|
+
* raised bar when it does — see {@link questionStandsAlone} and the
|
|
70
|
+
* `FOLLOW_UP_*` constants.
|
|
71
|
+
* 2. **Enough question.** At least {@link MIN_QUESTION_TOKENS} distinct
|
|
72
|
+
* content tokens after stop-word removal. Below that there is not enough
|
|
73
|
+
* of a question to be confident ABOUT.
|
|
74
|
+
* 3. **Not a generative request.** "write me a hero headline" is the copy
|
|
75
|
+
* assistant's job, not a docs lookup, and no docs page answers it.
|
|
76
|
+
* 4. **Not a diagnostic.** "why isn't my domain verifying" has a
|
|
77
|
+
* troubleshooting page, and dumping that page at someone whose actual
|
|
78
|
+
* problem is one of nine listed causes is exactly the confidently-wrong
|
|
79
|
+
* failure. Diagnostics need the workspace's own state, which is the
|
|
80
|
+
* level-2 context only the model gets.
|
|
81
|
+
* 5. **Absolute score.** The top section scores at least
|
|
82
|
+
* {@link MIN_TOP_SCORE}.
|
|
83
|
+
* 6. **Page dominance.** The winning page beats the best RIVAL page by at
|
|
84
|
+
* least {@link MIN_PAGE_MARGIN}. Measured against the runner-up page
|
|
85
|
+
* rather than as a share of the whole retrieved set, because the set is
|
|
86
|
+
* six sections wide: a page that is unambiguously right still holds a
|
|
87
|
+
* minority of a six-way split the moment three neighbouring pages use the
|
|
88
|
+
* same nouns, and a share test reads that dilution as doubt. And the
|
|
89
|
+
* comparison is page-to-page, not section-to-section — sections of ONE
|
|
90
|
+
* page scoring alike is agreement, which a section margin scores as a tie.
|
|
91
|
+
* 7. **Substance.** The winning section carries at least
|
|
92
|
+
* {@link MIN_SECTION_CHARS} of text. A three-word stub under a heading is
|
|
93
|
+
* a pointer, not an answer.
|
|
94
|
+
*
|
|
95
|
+
* Below the bar the request proceeds exactly as it did before this module
|
|
96
|
+
* existed: the same sections are still retrieved and still ground the model's
|
|
97
|
+
* prompt. Deflection removes model calls; it never removes grounding.
|
|
98
|
+
*
|
|
99
|
+
* ## The thresholds are measured, not guessed
|
|
100
|
+
*
|
|
101
|
+
* `docs-deflection.spec.ts` carries a fixed set of realistic questions —
|
|
102
|
+
* positives written in user vocabulary rather than lifted from docs headings,
|
|
103
|
+
* and negatives that MUST escalate — and asserts a floor on the deflection
|
|
104
|
+
* rate and a ceiling of zero on the negatives. Retuning a constant here
|
|
105
|
+
* without rerunning that spec is how a threshold ends up set by whoever
|
|
106
|
+
* touched it last.
|
|
107
|
+
*/ /**
|
|
108
|
+
* Distinct content tokens a question needs before it can be answered.
|
|
109
|
+
*
|
|
110
|
+
* Two, not three, and the difference is most of the corpus: "how do I install
|
|
111
|
+
* a plugin", "what are dataset relations" and "how do I cancel my
|
|
112
|
+
* subscription" all reduce to exactly two content tokens once the stop words
|
|
113
|
+
* go, and every one of them is a plain docs lookup. Three excluded them all.
|
|
114
|
+
*
|
|
115
|
+
* Two is safe here only because the gates below are not a checklist a weak
|
|
116
|
+
* question can pass by being short: a two-token question must have BOTH
|
|
117
|
+
* tokens carried by the winning page (the IDF weighting cannot rescue it —
|
|
118
|
+
* there is nothing generic to discount), and the page must still clear the
|
|
119
|
+
* score floor and out-score its rival. "is my site down" has two tokens and
|
|
120
|
+
* fails on dominance, not on length.
|
|
121
|
+
*/ const MIN_QUESTION_TOKENS = 2;
|
|
122
|
+
/**
|
|
123
|
+
* Absolute floor on the winning section's retrieval score.
|
|
124
|
+
*
|
|
125
|
+
* The scorer gives 2.5 for a title hit, 2 for a heading hit and up to ~2.2 per
|
|
126
|
+
* body term — about 6.7 for one term landing everywhere at once. 5 is
|
|
127
|
+
* therefore roughly "two question terms landed and at least one of them hit
|
|
128
|
+
* the page's own statement of topic". Below that the match is incidental
|
|
129
|
+
* vocabulary rather than a page about the thing.
|
|
130
|
+
*
|
|
131
|
+
* Measured down from 6, which cost five ordinary lookups scoring 4.4–5.9
|
|
132
|
+
* ("how do I cancel my subscription", "how do I set up sso for my team") and
|
|
133
|
+
* bought nothing: the negative set does not move between the two values,
|
|
134
|
+
* because what actually stops those is coverage and dominance, not the floor.
|
|
135
|
+
*/ const MIN_TOP_SCORE = 5;
|
|
136
|
+
/**
|
|
137
|
+
* How far the winning page must out-score the best rival page.
|
|
138
|
+
*
|
|
139
|
+
* 1.3x — the winner needs a visible lead, not a photo finish. Two pages
|
|
140
|
+
* within 30% of each other on the same question means retrieval genuinely
|
|
141
|
+
* does not know which one the user meant, and picking is a coin flip dressed
|
|
142
|
+
* up as an answer.
|
|
143
|
+
*
|
|
144
|
+
* A question that retrieves only ONE page has no rival and passes this gate
|
|
145
|
+
* outright; the score floor and coverage are what bound it there.
|
|
146
|
+
*/ const MIN_PAGE_MARGIN = 1.3;
|
|
147
|
+
/**
|
|
148
|
+
* Weighted fraction of the question the winning page must actually contain.
|
|
149
|
+
* Coverage and score answer different questions: score says the page matched
|
|
150
|
+
* strongly, coverage says the page did not IGNORE part of what was asked.
|
|
151
|
+
* "how do I password protect a screen on the free plan" scores highly on the
|
|
152
|
+
* site-protection page while silently dropping "free plan", and the answer
|
|
153
|
+
* that comes back is then wrong in the one way that matters.
|
|
154
|
+
*
|
|
155
|
+
* ⚠️ WEIGHTED BY IDF, and an unweighted version of this test is why nine
|
|
156
|
+
* perfectly ordinary questions escalated in the first measurement. "how do I
|
|
157
|
+
* make a reusable component" covers `reusable` and `component` and misses
|
|
158
|
+
* `make`, because the page says "create" — 2/3, under the bar, escalated. The
|
|
159
|
+
* miss carried no information: `make` appears in a third of the corpus, so
|
|
160
|
+
* its absence from one page says nothing, while `reusable` appearing says
|
|
161
|
+
* almost everything. Counting tokens equally lets the most common words in
|
|
162
|
+
* English veto a match on the rarest. Weighting by how rare a term is in THIS
|
|
163
|
+
* corpus makes the test ask what it always meant to ask — did the page cover
|
|
164
|
+
* the DISTINCTIVE part of the question.
|
|
165
|
+
*/ const MIN_COVERAGE = 0.7;
|
|
166
|
+
/**
|
|
167
|
+
* The relaxed coverage floor, reachable ONLY by a page that has also won
|
|
168
|
+
* overwhelmingly ({@link STRONG_PAGE_MARGIN}).
|
|
169
|
+
*
|
|
170
|
+
* Coverage and dominance are evidence about the same thing from opposite
|
|
171
|
+
* directions, and holding both as independent hard floors throws away the
|
|
172
|
+
* cases where one is emphatic. "how do I edit text directly on the canvas"
|
|
173
|
+
* covers 0.68 — a hair under the bar, and the miss is `directly`, which the
|
|
174
|
+
* text-editing page never says — while winning so completely that every
|
|
175
|
+
* retrieved section belongs to it and there is no rival page to divide by.
|
|
176
|
+
* There is no reading of that evidence in which the text-editing page is the
|
|
177
|
+
* wrong page, and escalating it pays a provider to agree.
|
|
178
|
+
*
|
|
179
|
+
* The floor still binds, and it binds on questions that HAVE cleared
|
|
180
|
+
* {@link STRONG_PAGE_MARGIN}: "how do I customise the error screens" wins its
|
|
181
|
+
* page by 4.1x and still escalates at 0.42, because a page that ignores that
|
|
182
|
+
* much of the question is not answering it however clearly it wins. That is
|
|
183
|
+
* the case this pair of numbers is calibrated to keep out.
|
|
184
|
+
*
|
|
185
|
+
* ⚠️ Both figures are measurements over the CURRENT `apps/docs` corpus, and
|
|
186
|
+
* the corpus moves. `docs-deflection.spec.ts` asserts the first one's band
|
|
187
|
+
* rather than only its verdict, so a worked example that drifts out of the
|
|
188
|
+
* band fails there by name instead of going quietly wrong here.
|
|
189
|
+
*/ const RELAXED_COVERAGE = 0.6;
|
|
190
|
+
/** The margin that buys {@link RELAXED_COVERAGE}. */ const STRONG_PAGE_MARGIN = 3;
|
|
191
|
+
/**
|
|
192
|
+
* ── The follow-up bar (AGL-2486) ──────────────────────────────────────────
|
|
193
|
+
*
|
|
194
|
+
* A question asked mid-thread is held to a HIGHER standard than the same
|
|
195
|
+
* question asked first, and the asymmetry is the whole idea rather than
|
|
196
|
+
* timidity about a new path.
|
|
197
|
+
*
|
|
198
|
+
* On turn one, a mediocre match costs a mediocre answer to the question that
|
|
199
|
+
* was actually asked, and the closing line invites the user to ask again.
|
|
200
|
+
* Mid-thread, a mediocre match means something else as well: it is EVIDENCE
|
|
201
|
+
* that the words in front of us are not the whole question. A thread is where
|
|
202
|
+
* ellipsis lives, so "retrieval is unsure" and "the missing half is in the
|
|
203
|
+
* transcript" are the same observation seen twice. Only an emphatic match —
|
|
204
|
+
* one where the page is right whatever came before — may be answered without
|
|
205
|
+
* reading the conversation.
|
|
206
|
+
*
|
|
207
|
+
* The calibration case is the second question, "how do I add an
|
|
208
|
+
* element to my page": top score 7.9, and the winning page beats its rival by
|
|
209
|
+
* 1.80 with a coming-soon LAUNCH GUIDE, because that guide happens to say
|
|
210
|
+
* "add", "element" and "page". As a first question that is retrieval doing
|
|
211
|
+
* its honest best. As a follow-up it is a coin flip that also ignores the
|
|
212
|
+
* conversation, and it escalates.
|
|
213
|
+
*/ const FOLLOW_UP_MIN_TOP_SCORE = 8;
|
|
214
|
+
/** @see FOLLOW_UP_MIN_TOP_SCORE — 1.3x is a lead; 2x is not arguable. */ const FOLLOW_UP_MIN_PAGE_MARGIN = 2;
|
|
215
|
+
/**
|
|
216
|
+
* A follow-up must ASK something, not merely name a topic.
|
|
217
|
+
*
|
|
218
|
+
* Mid-thread, a bare fragment — "the free plan?", "on mobile" — is the shape
|
|
219
|
+
* ellipsis takes: the verb it belongs to was in the previous turn, and the
|
|
220
|
+
* fragment is a modifier of a question we cannot see. A first turn cannot be
|
|
221
|
+
* elliptical in that way, which is why this cue is required only when
|
|
222
|
+
* something precedes it.
|
|
223
|
+
*
|
|
224
|
+
* The count of tokens was tried here first and thrown away: it excluded "how
|
|
225
|
+
* do I install a plugin" and "how do I create a site" — two content tokens
|
|
226
|
+
* each, and both complete questions that a user asks second as readily as
|
|
227
|
+
* first. Length is not what separates a question from a fragment; a verb is.
|
|
228
|
+
*/ const QUESTION_CUES = /\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;
|
|
229
|
+
/**
|
|
230
|
+
* Words and shapes that make a question depend on what came before it.
|
|
231
|
+
*
|
|
232
|
+
* Deliberately BROAD, and the asymmetry of the costs is why: a false positive
|
|
233
|
+
* here escalates a question that could have been answered from the docs — the
|
|
234
|
+
* behaviour that existed for every follow-up until this change, so the worst
|
|
235
|
+
* case is the status quo. A false negative answers a question nobody asked,
|
|
236
|
+
* with a citation under it, in a thread where the user can see we had the
|
|
237
|
+
* context and ignored it. These patterns are only ever consulted for a turn
|
|
238
|
+
* WITH history; a first question may say "that" as much as it likes.
|
|
239
|
+
*/ const CONTEXT_DEPENDENT_PATTERNS = [
|
|
240
|
+
// Pronouns and demonstratives standing in for a noun in the transcript.
|
|
241
|
+
// "does IT work on mobile", "how do I move THOSE".
|
|
242
|
+
/\b(it|its|it'?s|they|them|their|theirs|he|him|his|she|her|hers)\b/i,
|
|
243
|
+
/\b(that|this|these|those)\b/i,
|
|
244
|
+
// Naming an item of the previous answer by its position in it.
|
|
245
|
+
/\b(the|either|any|another|each)\s+(other|first|second|third|last|next|same|previous|latter|former)\b/i,
|
|
246
|
+
/\b(other|another|either)\s+one\b/i,
|
|
247
|
+
// Opening by attaching to the previous turn rather than starting a question.
|
|
248
|
+
/^\s*(and|but|so|or|then|also|plus|what about|how about|ok(ay)?|yes|no|yeah|nope|thanks?)\b/i,
|
|
249
|
+
// Elliptical follow-ups that carry the previous turn's verb phrase over.
|
|
250
|
+
/\b(why not|instead|as well|again|neither|both)\b/i
|
|
251
|
+
];
|
|
252
|
+
/** Minimum characters of section text before a section counts as an answer. */ const MIN_SECTION_CHARS = 200;
|
|
253
|
+
/** Sections of the winning page quoted verbatim, at most. */ const MAX_QUOTED_SECTIONS = 2;
|
|
254
|
+
/** Total verbatim characters in one deflected answer. */ const MAX_ANSWER_CHARS = 2600;
|
|
255
|
+
/**
|
|
256
|
+
* A request is generative when it asks for something to be WRITTEN, not
|
|
257
|
+
* explained. Anchored to the start of a word and paired with the objects
|
|
258
|
+
* people actually name, because "how do I create a redirect" is a docs
|
|
259
|
+
* question and "create a headline for my hero" is not.
|
|
260
|
+
*/ const GENERATIVE_PATTERNS = [
|
|
261
|
+
/\b(write|draft|compose|generate|rewrite|reword|rephrase|summari[sz]e|translate|brainstorm|suggest)\b/i,
|
|
262
|
+
/\b(make|build|create|give)\s+(me|us)\b/i,
|
|
263
|
+
/\b(come up with|help me write)\b/i
|
|
264
|
+
];
|
|
265
|
+
/**
|
|
266
|
+
* A request is diagnostic when it describes something not working. These have
|
|
267
|
+
* docs pages and must still escalate: the page lists every cause, and the
|
|
268
|
+
* user has exactly one of them. Only the model, with the level-2 view context,
|
|
269
|
+
* can narrow it — and when it cannot, saying so is better than quoting nine
|
|
270
|
+
* causes at someone.
|
|
271
|
+
*/ const DIAGNOSTIC_PATTERNS = [
|
|
272
|
+
/\bwhy\s+(is|are|isn'?t|aren'?t|does|doesn'?t|did|didn'?t|won'?t|can'?t|cannot|do)\b/i,
|
|
273
|
+
/\b(not working|isn'?t working|doesn'?t work|stopped working|no longer works)\b/i,
|
|
274
|
+
/\b(was|were|is|are|never)\s+not\s+\w+ed\b/i,
|
|
275
|
+
/\b(broken|failing|failed|stuck|blank|missing|502|404|500)\b/i,
|
|
276
|
+
/\b(troubleshoot|debug|diagnose)\b/i,
|
|
277
|
+
// "error" needs a verb of appearance in front of it, within a clause.
|
|
278
|
+
// Bare `\berrors?\b` reads "how do I customise the error screens" as a
|
|
279
|
+
// support ticket — the docs page for error screens is titled with the word,
|
|
280
|
+
// so the one question the pattern must not catch is the one it caught.
|
|
281
|
+
/\b(getting|got|see|seeing|shows?|showing|throws?|returns?|says?|hit)\b[^.?!]{0,40}\berrors?\b/i
|
|
282
|
+
];
|
|
283
|
+
function refuse(refusal, topScore = 0, pageMargin = 0, coverage = 0) {
|
|
284
|
+
return {
|
|
285
|
+
answered: false,
|
|
286
|
+
refusal,
|
|
287
|
+
answer: '',
|
|
288
|
+
quoted: [],
|
|
289
|
+
page: '',
|
|
290
|
+
topScore,
|
|
291
|
+
pageMargin,
|
|
292
|
+
coverage
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Inverse document frequency for one token, over the docs corpus.
|
|
297
|
+
*
|
|
298
|
+
* Smoothed (`+1` inside the log's argument and on the denominator) so a token
|
|
299
|
+
* absent from the index — a product name we have not documented, a typo —
|
|
300
|
+
* gets a large but finite weight rather than a division by zero or an
|
|
301
|
+
* infinity that would swallow every other term in the question.
|
|
302
|
+
*/ function tokenWeight(token) {
|
|
303
|
+
var _frequency_get;
|
|
304
|
+
const { frequency, sections } = docsDocumentFrequency();
|
|
305
|
+
const seen = (_frequency_get = frequency.get(token)) != null ? _frequency_get : 0;
|
|
306
|
+
return Math.log(1 + sections / (1 + seen));
|
|
307
|
+
}
|
|
308
|
+
/** The docs-site URL for one section. */ export function sectionUrl(section) {
|
|
309
|
+
return `${DOCS_SITE_ORIGIN}${section.path}${section.anchor}`;
|
|
310
|
+
}
|
|
311
|
+
/** `Title — Heading`, or just the title on a page intro. */ export function sectionLabel(section) {
|
|
312
|
+
return section.heading ? `${section.title} — ${section.heading}` : section.title;
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Trim verbatim text to `limit` characters on a sentence boundary, so a quote
|
|
316
|
+
* never ends mid-clause. Returns the text unchanged when it already fits.
|
|
317
|
+
*
|
|
318
|
+
* A truncated quote is still verbatim — it is a PREFIX of the section, which
|
|
319
|
+
* is what the spec's substring check asserts. Cutting on a boundary matters
|
|
320
|
+
* for a different reason: a sentence stopped halfway reads as a broken
|
|
321
|
+
* feature, and the user cannot tell whether the missing half contradicted the
|
|
322
|
+
* visible one.
|
|
323
|
+
*/ export function trimToSentence(text, limit) {
|
|
324
|
+
const trimmed = text.trim();
|
|
325
|
+
if (trimmed.length <= limit) return trimmed;
|
|
326
|
+
const window = trimmed.slice(0, limit);
|
|
327
|
+
const lastStop = Math.max(window.lastIndexOf('. '), window.lastIndexOf('! '), window.lastIndexOf('? '));
|
|
328
|
+
// A boundary in the first third would throw most of the quote away; better
|
|
329
|
+
// a hard cut with an ellipsis than an answer reduced to one sentence.
|
|
330
|
+
if (lastStop > limit / 3) return window.slice(0, lastStop + 1);
|
|
331
|
+
return `${window.trimEnd()}…`;
|
|
332
|
+
}
|
|
333
|
+
/** Question intent, ahead of any retrieval work. */ export function questionIsAnswerableFromDocs(question) {
|
|
334
|
+
const tokens = new Set(tokenize(question));
|
|
335
|
+
if (tokens.size < MIN_QUESTION_TOKENS) return 'too-short';
|
|
336
|
+
for (const pattern of GENERATIVE_PATTERNS){
|
|
337
|
+
if (pattern.test(question)) return 'generative';
|
|
338
|
+
}
|
|
339
|
+
for (const pattern of DIAGNOSTIC_PATTERNS){
|
|
340
|
+
if (pattern.test(question)) return 'diagnostic';
|
|
341
|
+
}
|
|
342
|
+
return null;
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* Whether a question can be read WITHOUT the conversation it was asked in.
|
|
346
|
+
*
|
|
347
|
+
* Only consulted for a turn that has history — see
|
|
348
|
+
* {@link CONTEXT_DEPENDENT_PATTERNS} for why the test errs towards "no", and
|
|
349
|
+
* the class docstring for why the gate is no longer simply "did anything
|
|
350
|
+
* precede this".
|
|
351
|
+
*
|
|
352
|
+
* Purely lexical, and that is a real limit worth naming: "how do I do the
|
|
353
|
+
* same for a blog post" is caught by `the same`, while "how do I change the
|
|
354
|
+
* colour" after a paragraph about buttons is not — nothing in those words
|
|
355
|
+
* says which colour. What saves that case is not this function but the raised
|
|
356
|
+
* evidence bar behind it, which such a question does not clear. The two gates
|
|
357
|
+
* are one argument in two halves: this one reads the question, that one reads
|
|
358
|
+
* the retrieval, and a follow-up must pass both.
|
|
359
|
+
*/ export function questionStandsAlone(question) {
|
|
360
|
+
if (!QUESTION_CUES.test(question)) return false;
|
|
361
|
+
for (const pattern of CONTEXT_DEPENDENT_PATTERNS){
|
|
362
|
+
if (pattern.test(question)) return false;
|
|
363
|
+
}
|
|
364
|
+
return true;
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* Decide whether the retrieved sections answer the question on their own, and
|
|
368
|
+
* compose the answer when they do.
|
|
369
|
+
*
|
|
370
|
+
* `hasHistory` is passed rather than derived because the caller holds the
|
|
371
|
+
* clamped history and this module must not grow an opinion about how history
|
|
372
|
+
* is budgeted. It is not a hard gate any more (AGL-2486): a turn with history
|
|
373
|
+
* must additionally stand on its own words and clear the raised `FOLLOW_UP_*`
|
|
374
|
+
* bar, and escalates when it does not.
|
|
375
|
+
*/ export function deflectToDocs(question, scored, hasHistory) {
|
|
376
|
+
if (hasHistory && !questionStandsAlone(question)) return refuse('follow-up');
|
|
377
|
+
const intent = questionIsAnswerableFromDocs(question);
|
|
378
|
+
if (intent) return refuse(intent);
|
|
379
|
+
if (!scored.length) return refuse('low-score');
|
|
380
|
+
const minTopScore = hasHistory ? FOLLOW_UP_MIN_TOP_SCORE : MIN_TOP_SCORE;
|
|
381
|
+
const minPageMargin = hasHistory ? FOLLOW_UP_MIN_PAGE_MARGIN : MIN_PAGE_MARGIN;
|
|
382
|
+
const top = scored[0];
|
|
383
|
+
const topScore = top.score;
|
|
384
|
+
if (!(topScore >= minTopScore)) return refuse('low-score', topScore);
|
|
385
|
+
// Score by PAGE. Sections of one page agreeing is the signal; treating them
|
|
386
|
+
// as rivals is how a strong, unambiguous match reads as a tie.
|
|
387
|
+
const perPage = new Map();
|
|
388
|
+
for (const entry of scored){
|
|
389
|
+
var _perPage_get;
|
|
390
|
+
perPage.set(entry.section.path, ((_perPage_get = perPage.get(entry.section.path)) != null ? _perPage_get : 0) + entry.score);
|
|
391
|
+
}
|
|
392
|
+
// The winning page is the highest-scoring PAGE, not the home of the
|
|
393
|
+
// highest-scoring section — three mid-scoring sections of one page can beat
|
|
394
|
+
// one strong section elsewhere, and when they do, that page is the answer.
|
|
395
|
+
let winner = '';
|
|
396
|
+
let winnerScore = 0;
|
|
397
|
+
let rivalScore = 0;
|
|
398
|
+
for (const [path, score] of perPage){
|
|
399
|
+
if (score > winnerScore) {
|
|
400
|
+
rivalScore = winnerScore;
|
|
401
|
+
winner = path;
|
|
402
|
+
winnerScore = score;
|
|
403
|
+
} else if (score > rivalScore) {
|
|
404
|
+
rivalScore = score;
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
// No rival is not a tie — it is the cleanest possible result, one page and
|
|
408
|
+
// nothing else. `Infinity` would be honest but propagates badly through the
|
|
409
|
+
// telemetry, so a lone winner reports its own score as the margin.
|
|
410
|
+
const pageMargin = rivalScore > 0 ? winnerScore / rivalScore : winnerScore;
|
|
411
|
+
if (!(pageMargin >= minPageMargin)) return refuse('ambiguous', topScore, pageMargin);
|
|
412
|
+
const pageSections = scored.filter((entry)=>entry.section.path === winner);
|
|
413
|
+
const pageTokens = new Set();
|
|
414
|
+
for (const entry of pageSections){
|
|
415
|
+
for (const token of tokenize(entry.section.title))pageTokens.add(token);
|
|
416
|
+
for (const token of tokenize(entry.section.heading))pageTokens.add(token);
|
|
417
|
+
for (const token of tokenize(entry.section.text))pageTokens.add(token);
|
|
418
|
+
}
|
|
419
|
+
const questionTokens = [
|
|
420
|
+
...new Set(tokenize(question))
|
|
421
|
+
];
|
|
422
|
+
let wanted = 0;
|
|
423
|
+
let covered = 0;
|
|
424
|
+
for (const token of questionTokens){
|
|
425
|
+
const weight = tokenWeight(token);
|
|
426
|
+
wanted += weight;
|
|
427
|
+
if (pageTokens.has(token)) covered += weight;
|
|
428
|
+
}
|
|
429
|
+
const coverage = wanted > 0 ? covered / wanted : 0;
|
|
430
|
+
// The relaxed floor is a FIRST-TURN allowance. It exists because coverage
|
|
431
|
+
// and dominance are evidence about the same thing, so an emphatic winner
|
|
432
|
+
// may carry a coverage miss — but mid-thread a coverage miss has a second
|
|
433
|
+
// reading: the part of the question the page ignored may be the part the
|
|
434
|
+
// conversation supplied. Turn one cannot mean that; a follow-up can, so it
|
|
435
|
+
// pays full coverage.
|
|
436
|
+
const coveredEnough = coverage >= MIN_COVERAGE || !hasHistory && coverage >= RELAXED_COVERAGE && pageMargin >= STRONG_PAGE_MARGIN;
|
|
437
|
+
if (!coveredEnough) {
|
|
438
|
+
return refuse('low-coverage', topScore, pageMargin, coverage);
|
|
439
|
+
}
|
|
440
|
+
const usable = pageSections.filter((entry)=>entry.section.text.trim().length >= MIN_SECTION_CHARS);
|
|
441
|
+
if (!usable.length) return refuse('thin-section', topScore, pageMargin, coverage);
|
|
442
|
+
const quoted = usable.slice(0, MAX_QUOTED_SECTIONS).map((entry)=>entry.section);
|
|
443
|
+
return {
|
|
444
|
+
answered: true,
|
|
445
|
+
refusal: null,
|
|
446
|
+
answer: composeDocsAnswer(quoted),
|
|
447
|
+
quoted,
|
|
448
|
+
page: winner,
|
|
449
|
+
topScore,
|
|
450
|
+
pageMargin,
|
|
451
|
+
coverage
|
|
452
|
+
};
|
|
453
|
+
}
|
|
454
|
+
/**
|
|
455
|
+
* The deflected answer: template + verbatim docs + real links, and nothing
|
|
456
|
+
* else. Kept exported so the spec can assert the reconstruction property
|
|
457
|
+
* against it directly rather than through the route.
|
|
458
|
+
*
|
|
459
|
+
* ⚠️ COMPOSED FOR A SURFACE THAT DOES NOT RENDER MARKDOWN. The Assist panel
|
|
460
|
+
* says so in its own docstring — `renderAssistText` turns `[label](url)` and
|
|
461
|
+
* bare URLs into links and renders everything else literally, under
|
|
462
|
+
* `whiteSpace: 'pre-wrap'`. That is a deliberate phase-1 decision, not a gap.
|
|
463
|
+
*
|
|
464
|
+
* This template shipped once with the heading wrapped in `**…**`, and the * besigner drawer duly showed `**Drag-and-drop hierarchy — Moving an element
|
|
465
|
+
* without dragging**`, asterisks and all. The lesson is not "escape the
|
|
466
|
+
* asterisks" — it is that the composer has to know what renders it.
|
|
467
|
+
*
|
|
468
|
+
* So the heading is a bare `[label](url)` on its own line — a LINK, which is
|
|
469
|
+
* 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
|
|
470
|
+
* not. Everything else is carried by NEWLINES, which `pre-wrap` renders,
|
|
471
|
+
* rather than by markup, which it does not.
|
|
472
|
+
*
|
|
473
|
+
* The link has to live in the TEXT, and that is still true now that the
|
|
474
|
+
* `docs` array on the `done` event IS rendered (AGL-2486, `AssistSources`).
|
|
475
|
+
* It was tempting to treat that array as the structural home for the citation
|
|
476
|
+
* even when nothing rendered it; it is still the wrong home, for a different
|
|
477
|
+
* reason. `docs` carries every section RETRIEVED, whereas this template
|
|
478
|
+
* quotes only the sections it actually used — so the array is a superset, and
|
|
479
|
+
* a citation moved there would credit pages this answer never drew a word
|
|
480
|
+
* from. `AssistSources` drops any url already linked in the text, which means
|
|
481
|
+
* a deflected answer renders exactly as it does below and gains no duplicate
|
|
482
|
+
* list underneath.
|
|
483
|
+
*
|
|
484
|
+
* Three specs in `docs-deflection.spec.ts` hold the line — no emphasis
|
|
485
|
+
* markers, no heading markers, and a link still present.
|
|
486
|
+
*
|
|
487
|
+
* The closing line is not decoration. A user who reads this and finds it did
|
|
488
|
+
* not answer them needs to know that asking again in different words reaches
|
|
489
|
+
* something else — otherwise the cheap path looks like the assistant simply
|
|
490
|
+
* being worse, and the next thing they do is stop using it.
|
|
491
|
+
*/ export function composeDocsAnswer(sections) {
|
|
492
|
+
const parts = [];
|
|
493
|
+
let budget = MAX_ANSWER_CHARS;
|
|
494
|
+
for (const section of sections){
|
|
495
|
+
if (budget <= MIN_SECTION_CHARS) break;
|
|
496
|
+
const quote = trimToSentence(section.text, budget);
|
|
497
|
+
budget -= quote.length;
|
|
498
|
+
parts.push(`[${sectionLabel(section)}](${sectionUrl(section)})\n${quote}`);
|
|
499
|
+
}
|
|
500
|
+
parts.push('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.');
|
|
501
|
+
return parts.join('\n\n');
|
|
502
|
+
}
|
|
503
|
+
/** Closest-pages links offered when nothing could be answered outright. */ const MAX_LINKED_SECTIONS = 4;
|
|
504
|
+
/**
|
|
505
|
+
* The graceful degrade: the closest pages we found, and an honest sentence
|
|
506
|
+
* saying why that is all there is (AGL-2486).
|
|
507
|
+
*
|
|
508
|
+
* ## Why this exists
|
|
509
|
+
*
|
|
510
|
+
* A deployment with no AI provider key — which includes every self-hosted
|
|
511
|
+
* one on the day it comes up, and Aglyn's own production today — can answer
|
|
512
|
+
* only what retrieval is confident about. A bare 501 for everything else
|
|
513
|
+
* reaches the panel as "Assist is not configured on this deployment" — and it
|
|
514
|
+
* can arrive on the SECOND question of a thread whose first question was just
|
|
515
|
+
* answered in full. A capability refusal that lands after a working answer
|
|
516
|
+
* reads as a fault, not a limit.
|
|
517
|
+
*
|
|
518
|
+
* The self-host charter says every Aglyn-operated dependency must be
|
|
519
|
+
* configurable AND degrade cleanly. "Degrades cleanly" cannot mean "answers
|
|
520
|
+
* one question per thread and then refuses" — a keyless deployment still has
|
|
521
|
+
* the entire documentation corpus and a retrieval index over it, so the floor
|
|
522
|
+
* is the best pages we found, not nothing.
|
|
523
|
+
*
|
|
524
|
+
* ## What it may and may not say
|
|
525
|
+
*
|
|
526
|
+
* The no-fabrication rule applies here exactly as it does to a deflected
|
|
527
|
+
* answer, and is tighter in one respect: these pages did NOT clear the
|
|
528
|
+
* confidence bar, so this text must not claim they answer the question. It
|
|
529
|
+
* says they are the closest, which is true by construction — they are the
|
|
530
|
+
* top of the retrieval ranking — and every word around them is a fixed
|
|
531
|
+
* template plus a real section label and URL.
|
|
532
|
+
*
|
|
533
|
+
* It also must not name an env var. A user who wanted to read `501` would
|
|
534
|
+
* have opened the network tab; the operator-facing detail stays in the API
|
|
535
|
+
* error body, where an operator looks. This is the plain-English half.
|
|
536
|
+
*/ export function composeDocsLinksAnswer(sections) {
|
|
537
|
+
const links = sections.slice(0, MAX_LINKED_SECTIONS).map((section)=>`[${sectionLabel(section)}](${sectionUrl(section)})`);
|
|
538
|
+
if (!links.length) return '';
|
|
539
|
+
return [
|
|
540
|
+
'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.',
|
|
541
|
+
'These are the closest pages I found:',
|
|
542
|
+
links.join('\n'),
|
|
543
|
+
'If none of them cover it, asking again in different words often lands somewhere better.'
|
|
544
|
+
].join('\n\n');
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
//# sourceMappingURL=docs-deflection.js.map
|
|
@@ -0,0 +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":"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"}
|