@aglyn/plugins-ai 1.0.0-beta.230 → 1.0.0-beta.232
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +17 -17
- package/src/lib/activity/ai-activity-actions.js +8 -4
- package/src/lib/activity/ai-activity-actions.js.map +1 -1
- package/src/lib/components/ai-assist-provider-on-host.component.d.ts +66 -0
- package/src/lib/components/ai-assist-provider-on-host.component.js +78 -0
- package/src/lib/components/ai-assist-provider-on-host.component.js.map +1 -0
- package/src/lib/components/ai-assist-provider.component.js +9 -10
- package/src/lib/components/ai-assist-provider.component.js.map +1 -1
- package/src/lib/components/ai-job-follow.component.js +1 -0
- package/src/lib/components/ai-job-follow.component.js.map +1 -1
- package/src/lib/components/ai-job-links.js +13 -0
- package/src/lib/components/ai-job-links.js.map +1 -1
- package/src/lib/components/ai-job-plan.component.js +3 -1
- package/src/lib/components/ai-job-plan.component.js.map +1 -1
- package/src/lib/components/ai-jobs-list-page.component.js +1 -0
- package/src/lib/components/ai-jobs-list-page.component.js.map +1 -1
- package/src/lib/components/ai-media-create.component.d.ts +20 -7
- package/src/lib/components/ai-media-create.component.js +107 -55
- package/src/lib/components/ai-media-create.component.js.map +1 -1
- package/src/lib/components/ai-permissions-on-host.component.d.ts +3 -46
- package/src/lib/components/ai-permissions-on-host.component.js +5 -53
- package/src/lib/components/ai-permissions-on-host.component.js.map +1 -1
- package/src/lib/components/ai-seo-fields-card.component.js +1 -0
- package/src/lib/components/ai-seo-fields-card.component.js.map +1 -1
- package/src/lib/components/ai-site-build-page.component.js +20 -8
- package/src/lib/components/ai-site-build-page.component.js.map +1 -1
- package/src/lib/components/ai-site-memory-card.component.d.ts +32 -0
- package/src/lib/components/ai-site-memory-card.component.js +187 -0
- package/src/lib/components/ai-site-memory-card.component.js.map +1 -0
- package/src/lib/components/ai-site-start-card.component.js +80 -77
- package/src/lib/components/ai-site-start-card.component.js.map +1 -1
- package/src/lib/components/ai-theme-proposal-card.component.js +4 -0
- package/src/lib/components/ai-theme-proposal-card.component.js.map +1 -1
- package/src/lib/components/ai-usage-strip.component.js +1 -0
- package/src/lib/components/ai-usage-strip.component.js.map +1 -1
- package/src/lib/components/assist-panel.component.d.ts +10 -0
- package/src/lib/components/assist-panel.component.js +119 -9
- package/src/lib/components/assist-panel.component.js.map +1 -1
- package/src/lib/components/assist-signals-page.component.js +2 -0
- package/src/lib/components/assist-signals-page.component.js.map +1 -1
- package/src/lib/components/billing-ai-allotments.component.js +3 -0
- package/src/lib/components/billing-ai-allotments.component.js.map +1 -1
- package/src/lib/components/billing-ai-top-users.component.js +1 -0
- package/src/lib/components/billing-ai-top-users.component.js.map +1 -1
- package/src/lib/components/billing-assist-overage-card.component.js +2 -0
- package/src/lib/components/billing-assist-overage-card.component.js.map +1 -1
- package/src/lib/components/member-ai-usage-card.component.js +10 -0
- package/src/lib/components/member-ai-usage-card.component.js.map +1 -1
- package/src/lib/components/staff-org-ai-card.component.js +1 -0
- package/src/lib/components/staff-org-ai-card.component.js.map +1 -1
- package/src/lib/components/staff-org-ai-conversations.component.d.ts +23 -0
- package/src/lib/components/staff-org-ai-conversations.component.js +346 -0
- package/src/lib/components/staff-org-ai-conversations.component.js.map +1 -0
- package/src/lib/jobs/ai-build-capabilities.d.ts +13 -1
- package/src/lib/jobs/ai-build-capabilities.js +101 -7
- package/src/lib/jobs/ai-build-capabilities.js.map +1 -1
- package/src/lib/jobs/ai-build-unit-outcome.js +4 -2
- package/src/lib/jobs/ai-build-unit-outcome.js.map +1 -1
- package/src/lib/jobs/ai-business-profile-prefill.d.ts +29 -0
- package/src/lib/jobs/ai-business-profile-prefill.js +85 -0
- package/src/lib/jobs/ai-business-profile-prefill.js.map +1 -0
- package/src/lib/jobs/ai-job-auto-confirm.d.ts +8 -0
- package/src/lib/jobs/ai-job-auto-confirm.js +30 -6
- package/src/lib/jobs/ai-job-auto-confirm.js.map +1 -1
- package/src/lib/jobs/ai-job-build-step.js +14 -1
- package/src/lib/jobs/ai-job-build-step.js.map +1 -1
- package/src/lib/jobs/ai-job-edit-step.d.ts +225 -0
- package/src/lib/jobs/ai-job-edit-step.js +631 -0
- package/src/lib/jobs/ai-job-edit-step.js.map +1 -0
- package/src/lib/jobs/ai-job-generation.d.ts +8 -0
- package/src/lib/jobs/ai-job-generation.js +13 -2
- package/src/lib/jobs/ai-job-generation.js.map +1 -1
- package/src/lib/jobs/ai-job-insight-step.js +29 -5
- package/src/lib/jobs/ai-job-insight-step.js.map +1 -1
- package/src/lib/jobs/ai-job-layout-language.d.ts +78 -0
- package/src/lib/jobs/ai-job-layout-language.js +200 -0
- package/src/lib/jobs/ai-job-layout-language.js.map +1 -0
- package/src/lib/jobs/ai-job-layout-site-pages.d.ts +13 -2
- package/src/lib/jobs/ai-job-layout-site-pages.js +18 -2
- package/src/lib/jobs/ai-job-layout-site-pages.js.map +1 -1
- package/src/lib/jobs/ai-job-layout-step.d.ts +5 -0
- package/src/lib/jobs/ai-job-layout-step.js +107 -6
- package/src/lib/jobs/ai-job-layout-step.js.map +1 -1
- package/src/lib/jobs/ai-job-logic-step.d.ts +20 -0
- package/src/lib/jobs/ai-job-logic-step.js +87 -6
- package/src/lib/jobs/ai-job-logic-step.js.map +1 -1
- package/src/lib/jobs/ai-job-page-language.d.ts +194 -0
- package/src/lib/jobs/ai-job-page-language.js +418 -0
- package/src/lib/jobs/ai-job-page-language.js.map +1 -0
- package/src/lib/jobs/ai-job-page-sections.d.ts +37 -1
- package/src/lib/jobs/ai-job-page-sections.js +93 -11
- package/src/lib/jobs/ai-job-page-sections.js.map +1 -1
- package/src/lib/jobs/ai-job-page-step.d.ts +4 -4
- package/src/lib/jobs/ai-job-page-step.js +115 -14
- package/src/lib/jobs/ai-job-page-step.js.map +1 -1
- package/src/lib/jobs/ai-job-plan-step.d.ts +20 -6
- package/src/lib/jobs/ai-job-plan-step.js +62 -22
- package/src/lib/jobs/ai-job-plan-step.js.map +1 -1
- package/src/lib/jobs/ai-job-site-content.d.ts +163 -0
- package/src/lib/jobs/ai-job-site-content.js +443 -0
- package/src/lib/jobs/ai-job-site-content.js.map +1 -0
- package/src/lib/jobs/ai-job-site-look.d.ts +112 -0
- package/src/lib/jobs/ai-job-site-look.js +322 -0
- package/src/lib/jobs/ai-job-site-look.js.map +1 -0
- package/src/lib/jobs/ai-job-site-step.d.ts +30 -5
- package/src/lib/jobs/ai-job-site-step.js +183 -27
- package/src/lib/jobs/ai-job-site-step.js.map +1 -1
- package/src/lib/jobs/ai-job-workflow-step.js +2 -2
- package/src/lib/jobs/ai-job-workflow-step.js.map +1 -1
- package/src/lib/jobs/ai-jobs-notify.d.ts +6 -1
- package/src/lib/jobs/ai-jobs-notify.js +15 -3
- package/src/lib/jobs/ai-jobs-notify.js.map +1 -1
- package/src/lib/jobs/ai-jobs.d.ts +1 -1
- package/src/lib/jobs/ai-jobs.js +17 -8
- package/src/lib/jobs/ai-jobs.js.map +1 -1
- package/src/lib/jobs/ai-layout-full-height.d.ts +40 -0
- package/src/lib/jobs/ai-layout-full-height.js +82 -0
- package/src/lib/jobs/ai-layout-full-height.js.map +1 -0
- package/src/lib/jobs/ai-layout-site-facts.d.ts +54 -0
- package/src/lib/jobs/ai-layout-site-facts.js +153 -0
- package/src/lib/jobs/ai-layout-site-facts.js.map +1 -0
- package/src/lib/layout-language/ai-layout-compiler.d.ts +154 -0
- package/src/lib/layout-language/ai-layout-compiler.js +1235 -0
- package/src/lib/layout-language/ai-layout-compiler.js.map +1 -0
- package/src/lib/layout-language/ai-layout-copy.d.ts +73 -0
- package/src/lib/layout-language/ai-layout-copy.js +137 -0
- package/src/lib/layout-language/ai-layout-copy.js.map +1 -0
- package/src/lib/layout-language/ai-layout-frame.d.ts +52 -0
- package/src/lib/layout-language/ai-layout-frame.js +458 -0
- package/src/lib/layout-language/ai-layout-frame.js.map +1 -0
- package/src/lib/layout-language/ai-layout-gaps.d.ts +63 -0
- package/src/lib/layout-language/ai-layout-gaps.js +345 -0
- package/src/lib/layout-language/ai-layout-gaps.js.map +1 -0
- package/src/lib/layout-language/ai-layout-language.d.ts +168 -0
- package/src/lib/layout-language/ai-layout-language.js +529 -0
- package/src/lib/layout-language/ai-layout-language.js.map +1 -0
- package/src/lib/layout-language/ai-layout-links.d.ts +80 -0
- package/src/lib/layout-language/ai-layout-links.js +109 -0
- package/src/lib/layout-language/ai-layout-links.js.map +1 -0
- package/src/lib/layout-language/ai-layout-pictures.d.ts +144 -0
- package/src/lib/layout-language/ai-layout-pictures.js +214 -0
- package/src/lib/layout-language/ai-layout-pictures.js.map +1 -0
- package/src/lib/layout-language/ai-layout-store.d.ts +41 -0
- package/src/lib/layout-language/ai-layout-store.js +75 -0
- package/src/lib/layout-language/ai-layout-store.js.map +1 -0
- package/src/lib/layout-language/ai-layout-tree.d.ts +59 -0
- package/src/lib/layout-language/ai-layout-tree.js +84 -0
- package/src/lib/layout-language/ai-layout-tree.js.map +1 -0
- package/src/lib/lazy-widget.d.ts +45 -0
- package/src/lib/lazy-widget.js +53 -0
- package/src/lib/lazy-widget.js.map +1 -0
- package/src/lib/model/ai-build-job.js +2 -1
- package/src/lib/model/ai-build-job.js.map +1 -1
- package/src/lib/model/ai-build-progress.d.ts +20 -3
- package/src/lib/model/ai-build-progress.js +52 -7
- package/src/lib/model/ai-build-progress.js.map +1 -1
- package/src/lib/model/ai-edit-job.d.ts +109 -0
- package/src/lib/model/ai-edit-job.js +157 -0
- package/src/lib/model/ai-edit-job.js.map +1 -0
- package/src/lib/model/ai-host-publish-context.d.ts +51 -0
- package/src/lib/model/ai-host-publish-context.js +104 -0
- package/src/lib/model/ai-host-publish-context.js.map +1 -0
- package/src/lib/model/ai-job-activity.d.ts +22 -0
- package/src/lib/model/ai-job-activity.js +23 -1
- package/src/lib/model/ai-job-activity.js.map +1 -1
- package/src/lib/model/ai-job-failure-copy.d.ts +38 -1
- package/src/lib/model/ai-job-failure-copy.js +56 -1
- package/src/lib/model/ai-job-failure-copy.js.map +1 -1
- package/src/lib/model/ai-job-notice.d.ts +3 -1
- package/src/lib/model/ai-job-notice.js +31 -9
- package/src/lib/model/ai-job-notice.js.map +1 -1
- package/src/lib/model/ai-jobs.types.d.ts +22 -1
- package/src/lib/model/ai-jobs.types.js.map +1 -1
- package/src/lib/model/ai-logic-job.d.ts +18 -1
- package/src/lib/model/ai-logic-job.js +24 -3
- package/src/lib/model/ai-logic-job.js.map +1 -1
- package/src/lib/model/ai-media-credits.d.ts +8 -4
- package/src/lib/model/ai-media-credits.js +11 -4
- package/src/lib/model/ai-media-credits.js.map +1 -1
- package/src/lib/model/ai-media-kinds.d.ts +68 -0
- package/src/lib/model/ai-media-kinds.js +98 -0
- package/src/lib/model/ai-media-kinds.js.map +1 -0
- package/src/lib/model/ai-site-build-progress.d.ts +9 -1
- package/src/lib/model/ai-site-build-progress.js +54 -14
- package/src/lib/model/ai-site-build-progress.js.map +1 -1
- package/src/lib/model/ai-site-context.d.ts +111 -0
- package/src/lib/model/ai-site-context.js +222 -0
- package/src/lib/model/ai-site-context.js.map +1 -0
- package/src/lib/model/ai-site-job.d.ts +18 -2
- package/src/lib/model/ai-site-job.js +21 -5
- package/src/lib/model/ai-site-job.js.map +1 -1
- package/src/lib/model/ai-site-kinds.d.ts +164 -0
- package/src/lib/model/ai-site-kinds.js +1942 -0
- package/src/lib/model/ai-site-kinds.js.map +1 -0
- package/src/lib/model/ai-site-look.d.ts +150 -0
- package/src/lib/model/ai-site-look.js +1236 -0
- package/src/lib/model/ai-site-look.js.map +1 -0
- package/src/lib/model/ai-site-memory.d.ts +80 -0
- package/src/lib/model/ai-site-memory.js +171 -0
- package/src/lib/model/ai-site-memory.js.map +1 -0
- package/src/lib/model/ai-site-start-seo.d.ts +1 -1
- package/src/lib/model/ai-site-start.d.ts +15 -3
- package/src/lib/model/ai-site-start.js +21 -4
- package/src/lib/model/ai-site-start.js.map +1 -1
- package/src/lib/model/assist-follow-up.d.ts +92 -0
- package/src/lib/model/assist-follow-up.js +128 -0
- package/src/lib/model/assist-follow-up.js.map +1 -0
- package/src/lib/plugin-config.js +2 -0
- package/src/lib/plugin-config.js.map +1 -1
- package/src/lib/plugin.js +99 -48
- package/src/lib/plugin.js.map +1 -1
- package/src/lib/providers/anthropic.d.ts +9 -1
- package/src/lib/providers/anthropic.js +143 -9
- package/src/lib/providers/anthropic.js.map +1 -1
- package/src/lib/providers/catalog.d.ts +38 -8
- package/src/lib/providers/catalog.js +106 -14
- package/src/lib/providers/catalog.js.map +1 -1
- package/src/lib/providers/contract.d.ts +29 -0
- package/src/lib/providers/contract.js.map +1 -1
- package/src/lib/providers/image-contract.d.ts +22 -1
- package/src/lib/providers/image-contract.js +40 -1
- package/src/lib/providers/image-contract.js.map +1 -1
- package/src/lib/providers/image-endpoints.d.ts +24 -0
- package/src/lib/providers/image-endpoints.js +28 -0
- package/src/lib/providers/image-endpoints.js.map +1 -0
- package/src/lib/providers/model-choice.js +23 -2
- package/src/lib/providers/model-choice.js.map +1 -1
- package/src/lib/providers/routing.js +18 -0
- package/src/lib/providers/routing.js.map +1 -1
- package/src/lib/providers/vertex-image-endpoint.d.ts +48 -0
- package/src/lib/providers/vertex-image-endpoint.js +80 -0
- package/src/lib/providers/vertex-image-endpoint.js.map +1 -0
- package/src/lib/providers/vertex-image.d.ts +13 -27
- package/src/lib/providers/vertex-image.js +15 -42
- package/src/lib/providers/vertex-image.js.map +1 -1
- package/src/lib/runtime/ai-blog-post-generation.d.ts +62 -0
- package/src/lib/runtime/ai-blog-post-generation.js +89 -0
- package/src/lib/runtime/ai-blog-post-generation.js.map +1 -0
- package/src/lib/runtime/ai-dev-env.d.ts +53 -0
- package/src/lib/runtime/ai-dev-env.js +72 -0
- package/src/lib/runtime/ai-dev-env.js.map +1 -0
- package/src/lib/runtime/ai-dev-replay.d.ts +116 -0
- package/src/lib/runtime/ai-dev-replay.js +313 -0
- package/src/lib/runtime/ai-dev-replay.js.map +1 -0
- package/src/lib/runtime/ai-doctrine-validators.d.ts +82 -0
- package/src/lib/runtime/ai-doctrine-validators.js +436 -4
- package/src/lib/runtime/ai-doctrine-validators.js.map +1 -1
- package/src/lib/runtime/ai-doctrine.js +16 -3
- package/src/lib/runtime/ai-doctrine.js.map +1 -1
- package/src/lib/runtime/ai-eval-live.js +4 -0
- package/src/lib/runtime/ai-eval-live.js.map +1 -1
- package/src/lib/runtime/ai-eval.d.ts +13 -1
- package/src/lib/runtime/ai-eval.js +84 -1
- package/src/lib/runtime/ai-eval.js.map +1 -1
- package/src/lib/runtime/ai-icon-library.d.ts +257 -0
- package/src/lib/runtime/ai-icon-library.js +254 -0
- package/src/lib/runtime/ai-icon-library.js.map +1 -0
- package/src/lib/runtime/ai-live-batch.d.ts +45 -0
- package/src/lib/runtime/ai-live-batch.js +89 -0
- package/src/lib/runtime/ai-live-batch.js.map +1 -0
- package/src/lib/runtime/ai-node-tree.d.ts +9 -0
- package/src/lib/runtime/ai-node-tree.js +30 -4
- package/src/lib/runtime/ai-node-tree.js.map +1 -1
- package/src/lib/runtime/ai-palette.d.ts +6 -0
- package/src/lib/runtime/ai-palette.generated.js +70 -0
- package/src/lib/runtime/ai-palette.generated.js.map +1 -1
- package/src/lib/runtime/ai-palette.js.map +1 -1
- package/src/lib/runtime/ai-runtime.js +46 -2
- package/src/lib/runtime/ai-runtime.js.map +1 -1
- package/src/lib/runtime/site-context.d.ts +58 -0
- package/src/lib/runtime/site-context.js +127 -0
- package/src/lib/runtime/site-context.js.map +1 -0
- package/src/lib/server/ai-admin-conversations.d.ts +22 -0
- package/src/lib/server/ai-admin-conversations.js +197 -0
- package/src/lib/server/ai-admin-conversations.js.map +1 -0
- package/src/lib/server/ai-media-image.d.ts +5 -5
- package/src/lib/server/ai-media-image.js +25 -11
- package/src/lib/server/ai-media-image.js.map +1 -1
- package/src/lib/server/ai-media-raster-prompt.d.ts +34 -0
- package/src/lib/server/ai-media-raster-prompt.js +53 -0
- package/src/lib/server/ai-media-raster-prompt.js.map +1 -0
- package/src/lib/server/assist-chat.d.ts +11 -0
- package/src/lib/server/assist-chat.js +57 -18
- package/src/lib/server/assist-chat.js.map +1 -1
- package/src/lib/server/assist-edit-applied.js +16 -3
- package/src/lib/server/assist-edit-applied.js.map +1 -1
- package/src/lib/server/assist-view-context.d.ts +19 -1
- package/src/lib/server/assist-view-context.js +38 -1
- package/src/lib/server/assist-view-context.js.map +1 -1
- package/src/lib/server.js +10 -0
- package/src/lib/server.js.map +1 -1
- package/src/lib/subprocessors.js +17 -1
- package/src/lib/subprocessors.js.map +1 -1
- package/src/lib/tools/ai-blog-post-tool.d.ts +60 -0
- package/src/lib/tools/ai-blog-post-tool.js +175 -0
- package/src/lib/tools/ai-blog-post-tool.js.map +1 -0
- package/src/lib/tools/ai-workflow-tool.d.ts +6 -2
- package/src/lib/tools/ai-workflow-tool.js +16 -14
- package/src/lib/tools/ai-workflow-tool.js.map +1 -1
- package/src/lib/usage/assist-usage.d.ts +3 -0
- package/src/lib/usage/assist-usage.js +4 -2
- package/src/lib/usage/assist-usage.js.map +1 -1
- package/src/lib/usage/staff-org-ai-conversations.d.ts +103 -0
- package/src/lib/usage/staff-org-ai-conversations.js +152 -0
- package/src/lib/usage/staff-org-ai-conversations.js.map +1 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/providers/anthropic.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 { aiModelIdsForProvider, estimateAiBilledUsd, aiCatalogEntry } from './catalog'\nimport {\n AiUpstreamError,\n type AiAccountProblem,\n aiRawOutputOf,\n aiStoppedAtCeiling,\n aiTokenCount,\n aiToolInputOf,\n type AiMessage,\n type AiModelDescriptor,\n type AiProvider,\n type AiProviderRequest,\n type AiResult,\n type AiStreamEvent,\n type AiToolSchemaLimits,\n type AiToolUse,\n type AiUsage,\n} from './contract'\n\n/**\n * The Anthropic adapter (AGL-2903, behind the contract since AGL-2939):\n * the Messages API over raw `fetch`. No provider SDK is installed, and the\n * meter prices by model id from the catalog, so nothing an SDK would add\n * is used here. This file and the catalog are the only places in the\n * plugin that name the vendor's URL, header or model ids.\n *\n * ── Errors (AGL-2815) ─────────────────────────────────────────────────────\n *\n * Provider error text describes OUR account with the vendor — a key, a rate\n * limit, a balance — and names the vendor to a white-label org's users. It\n * never leaves this module as a message: a non-2xx answer becomes an\n * `AiUpstreamError` carrying the status, whether the failure is retryable\n * and a fixed customer-safe sentence; the provider's body goes to\n * `console.error` beside the request id, where an operator can find it.\n * A `refusal` stop is not an error at all — the tokens were spent and the\n * model answered — so it comes back as a typed `AiRefusal` result.\n */\n\nexport const ANTHROPIC_PROVIDER_ID = 'anthropic'\nexport const ANTHROPIC_API_KEY_ENV = 'ANTHROPIC_API_KEY'\nconst ANTHROPIC_HOST = 'api.anthropic.com'\nconst ANTHROPIC_URL = `https://${ANTHROPIC_HOST}/v1/messages`\nconst ANTHROPIC_VERSION = '2023-06-01'\n\n/** The Messages API accepts at most this many `cache_control` markers. */\nexport const ANTHROPIC_MAX_CACHE_BREAKPOINTS = 4\n\n/**\n * What the Messages API compiles of one request's strict schemas, as its\n * structured-outputs documentation states the limits: 20 strict tools, 24\n * optional parameters and 16 parameters with union types, each a total over\n * every strict schema the request carries. Past any of them the request is\n * refused with a 400 before the model runs.\n *\n * `compiledSchemaBytes` is not one of those. The API also refuses a request\n * whose schemas compile to too large a grammar — \"Simplify your tool schemas\n * or reduce the number of strict tools\" — and states no size for it, so this\n * bound is measured rather than read (AGL-3096). Its evidence is two live\n * requests for the automation draft, the largest strict schema anything here\n * sends:\n *\n * - 8,757 bytes, refused for grammar size (`req_011CfC6Fif9iJvmKPTRgtLdp`,\n * 2026-09-19), with 1 strict tool, 0 optional parameters and 2 unions:\n * every published count was green;\n * - 3,807 bytes, served (`req_011CfELn62WVLeaNzwK4TWgb`, 2026-09-20), the\n * same tool with the guard lifted out of the steps' union and one variant\n * per set of fields.\n *\n * Everything else the plugin sends is smaller still, the next largest being\n * the theme tool at 2,410 bytes. The bound sits at what has been served, so a\n * schema that grows past it has to be proved live before the bound moves.\n */\nexport const ANTHROPIC_TOOL_SCHEMA_LIMITS: AiToolSchemaLimits = {\n strictTools: 20,\n optionalParameters: 24,\n unionParameters: 16,\n compiledSchemaBytes: 3_807,\n}\n\n/**\n * Whether a provider failure is the kind that clears on its own. Matched on\n * the status AND the error type, because the in-stream `error` event has no\n * status to go by.\n */\nexport function anthropicFailureIsRetryable(\n status: number | null,\n errorType: string | undefined,\n): boolean {\n return (\n status === 429 ||\n status === 529 ||\n errorType === 'rate_limit_error' ||\n errorType === 'overloaded_error'\n )\n}\n\n/**\n * Whether a failure is about the platform's Anthropic account rather than the\n * request (AGL-3377): a refused key, or a balance too low to answer.\n */\nexport function anthropicAccountProblem(\n status: number | null,\n error: { type?: string; message?: string } | null | undefined,\n): AiAccountProblem | null {\n if (status === 401 || status === 403) return 'credentials'\n if (error?.type === 'authentication_error' || error?.type === 'permission_error') {\n return 'credentials'\n }\n if (error?.type === 'billing_error' || /credit balance/i.test(error?.message ?? '')) {\n return 'credit'\n }\n return null\n}\n\n/** Anthropic's `usage` object, in the meter's shape. Missing fields read 0. */\nexport function anthropicUsageFrom(usage: unknown): AiUsage {\n const record = (usage ?? {}) as Record<string, unknown>\n // Part of `output_tokens`, and carried only where the response breaks them\n // down, so an answer that reports none says nothing rather than zero.\n const details = record['output_tokens_details']\n const thinking =\n details && typeof details === 'object'\n ? (details as Record<string, unknown>)['thinking_tokens']\n : undefined\n return {\n inputTokens: aiTokenCount(record['input_tokens']),\n outputTokens: aiTokenCount(record['output_tokens']),\n cacheReadTokens: aiTokenCount(record['cache_read_input_tokens']),\n cacheWriteTokens: aiTokenCount(record['cache_creation_input_tokens']),\n ...(thinking === undefined ? {} : { thinkingTokens: aiTokenCount(thinking) }),\n }\n}\n\n/**\n * The Messages API body for a request. Exported so a spec can assert the\n * wire shape without a network. The cache-prefix rule is enforced by the\n * runtime before the request reaches any adapter; this maps the surviving\n * breakpoints onto `cache_control` and refuses only the count the API\n * itself refuses.\n */\nexport function buildAnthropicRequestBody(\n input: Omit<AiProviderRequest, 'apiKey' | 'signal'> & { stream: boolean },\n): Record<string, unknown> {\n const breakpoints = input.system.filter((block) => block.cacheBreakpoint)\n if (breakpoints.length > ANTHROPIC_MAX_CACHE_BREAKPOINTS) {\n throw new Error(\n `${breakpoints.length} cache breakpoints; the Messages API allows ${ANTHROPIC_MAX_CACHE_BREAKPOINTS}`,\n )\n }\n const system = input.system.map((block) => ({\n type: 'text',\n text: block.text,\n ...(block.cacheBreakpoint ? { cache_control: { type: 'ephemeral' } } : {}),\n }))\n const tools = input.tools?.map((tool) => ({\n name: tool.name,\n description: tool.description,\n input_schema: { ...tool.inputSchema, additionalProperties: false },\n strict: true,\n }))\n // A model that rejects an explicit thinking setting gets none, whatever\n // the door asked for, and no effort either: effort rides the same rule\n // (see the contract), and the catalog says which models those are.\n const settable = aiCatalogEntry(input.model)?.capabilities.thinking !== false\n const thinking = settable ? input.thinking : undefined\n const effort = settable ? input.effort : undefined\n return {\n model: input.model,\n max_tokens: input.maxTokens,\n ...(input.stream ? { stream: true } : {}),\n ...(thinking === 'off'\n ? { thinking: { type: 'disabled' } }\n : thinking === 'adaptive'\n ? { thinking: { type: 'adaptive' } }\n : {}),\n ...(effort ? { output_config: { effort } } : {}),\n ...(system.length ? { system } : {}),\n messages: input.messages.map((message) => ({\n role: message.role,\n content: anthropicContentOf(message),\n })),\n ...(tools?.length ? { tools, tool_choice: { type: 'auto' } } : {}),\n }\n}\n\n/**\n * A turn's content in the Messages API's shape: a text-only turn as the\n * string it is, and a turn with pictures as content blocks in order, each\n * picture a base64 image block (AGL-2916).\n */\nfunction anthropicContentOf(message: AiMessage): string | Array<Record<string, unknown>> {\n if (typeof message.content === 'string') return message.content\n return message.content.map((part) =>\n part.type === 'image'\n ? { type: 'image', source: { type: 'base64', media_type: part.mediaType, data: part.data } }\n : { type: 'text', text: part.text },\n )\n}\n\n/** The provider's request id, when it sent one — the log's join key. */\nfunction requestIdOf(response: Response): string | null {\n return response.headers?.get?.('request-id') ?? null\n}\n\nasync function send(\n input: AiProviderRequest,\n stream: boolean,\n): Promise<Response> {\n const body = buildAnthropicRequestBody({ ...input, stream })\n const response = await fetch(ANTHROPIC_URL, {\n method: 'POST',\n headers: {\n 'x-api-key': input.apiKey,\n 'anthropic-version': ANTHROPIC_VERSION,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(body),\n ...(input.signal ? { signal: input.signal } : {}),\n })\n if (!response.ok || (stream && !response.body)) {\n const requestId = requestIdOf(response)\n const payload = (await response.json().catch(() => null)) as {\n error?: { type?: string; message?: string }\n } | null\n console.error('ai upstream error', {\n provider: ANTHROPIC_PROVIDER_ID,\n status: response.status,\n requestId,\n model: input.model,\n error: payload?.error ?? null,\n })\n throw new AiUpstreamError(\n response.status,\n anthropicFailureIsRetryable(response.status, payload?.error?.type),\n requestId,\n anthropicAccountProblem(response.status, payload?.error),\n )\n }\n return response\n}\n\nasync function complete(input: AiProviderRequest): Promise<AiResult> {\n const response = await send(input, false)\n const payload = (await response.json()) as {\n content?: Array<Record<string, unknown>>\n stop_reason?: unknown\n usage?: unknown\n }\n const blocks = Array.isArray(payload?.content) ? payload.content : []\n const text = blocks\n .filter((block) => block?.['type'] === 'text')\n .map((block) => String(block['text'] ?? ''))\n .join('')\n const toolUse: AiToolUse[] = blocks\n .filter((block) => block?.['type'] === 'tool_use')\n .map((block) => ({\n name: String(block['name'] ?? ''),\n input: aiToolInputOf(block['input']),\n }))\n const usage = anthropicUsageFrom(payload?.usage)\n const estCostUsd = estimateAiBilledUsd(usage, input.model)\n const stopReason =\n typeof payload?.stop_reason === 'string' && payload.stop_reason\n ? payload.stop_reason\n : null\n if (stopReason === 'refusal') {\n return { kind: 'refusal', text, usage, estCostUsd, stopReason }\n }\n return {\n kind: 'completion',\n text,\n toolUse,\n usage,\n estCostUsd,\n stopReason,\n // The blocks as the provider answered them, for a call its ceiling cut\n // off (AGL-3143): `toolUse` holds only what still parsed out of them.\n ...(aiStoppedAtCeiling(stopReason) ? { rawOutput: aiRawOutputOf(blocks) } : {}),\n }\n}\n\nasync function stream(input: AiProviderRequest): Promise<AsyncIterable<AiStreamEvent>> {\n const response = await send(input, true)\n return streamEvents(\n response.body as ReadableStream<Uint8Array>,\n input.model,\n requestIdOf(response),\n )\n}\n\n/**\n * Anthropic's SSE stream as contract events. Usage is taken from\n * `message_start` (input and cache figures) and `message_delta` (the\n * output count, and any cumulative input figures a newer API sends); the\n * `done` event carries whatever was known when the body ended, so a stream\n * cut short still meters what it cost.\n */\nasync function* streamEvents(\n body: ReadableStream<Uint8Array>,\n model: string,\n requestId: string | null,\n): AsyncGenerator<AiStreamEvent> {\n const decoder = new TextDecoder()\n const reader = body.getReader()\n const usage: AiUsage = {\n inputTokens: 0,\n outputTokens: 0,\n cacheReadTokens: 0,\n cacheWriteTokens: 0,\n }\n let stopReason: string | null = null\n /** Tool-use blocks in flight, by content index; input arrives in pieces. */\n const tools = new Map<number, { name: string; json: string }>()\n /**\n * What each tool call was actually written in, in the order its block\n * opened (AGL-3143). The `tool` events below carry only as much of these\n * as `aiToolInputOf` could still parse, so for a call the ceiling cut off\n * this is the one place the emitted bytes survive.\n */\n const written: string[] = []\n let buffer = ''\n let drained = false\n try {\n for (;;) {\n const { done, value } = await reader.read()\n if (done) {\n drained = true\n break\n }\n buffer += decoder.decode(value, { stream: true })\n const lines = buffer.split('\\n')\n buffer = lines.pop() ?? ''\n for (const line of lines) {\n if (!line.startsWith('data: ')) continue\n let event: Record<string, unknown>\n try {\n event = JSON.parse(line.slice('data: '.length))\n } catch {\n continue\n }\n const index = Number(event['index'])\n switch (event['type']) {\n case 'message_start': {\n const start = anthropicUsageFrom(\n (event['message'] as { usage?: unknown } | undefined)?.usage,\n )\n usage.inputTokens = start.inputTokens\n usage.cacheReadTokens = start.cacheReadTokens\n usage.cacheWriteTokens = start.cacheWriteTokens\n break\n }\n case 'content_block_start': {\n const block = event['content_block'] as\n | { type?: string; name?: string }\n | undefined\n if (block?.type === 'tool_use') {\n tools.set(index, { name: String(block.name ?? ''), json: '' })\n }\n break\n }\n case 'content_block_delta': {\n const delta = event['delta'] as\n | { type?: string; text?: string; partial_json?: string }\n | undefined\n if (delta?.type === 'text_delta' && delta.text) {\n yield { type: 'delta', text: delta.text }\n } else if (delta?.type === 'input_json_delta') {\n const tool = tools.get(index)\n if (tool) tool.json += delta.partial_json ?? ''\n }\n break\n }\n case 'content_block_stop': {\n const tool = tools.get(index)\n if (tool) {\n tools.delete(index)\n written.push(tool.json)\n yield { type: 'tool', name: tool.name, input: aiToolInputOf(tool.json) }\n }\n break\n }\n case 'message_delta': {\n const delta = anthropicUsageFrom(event['usage'])\n usage.outputTokens = delta.outputTokens || usage.outputTokens\n usage.inputTokens = delta.inputTokens || usage.inputTokens\n usage.cacheReadTokens = delta.cacheReadTokens || usage.cacheReadTokens\n usage.cacheWriteTokens = delta.cacheWriteTokens || usage.cacheWriteTokens\n // Kept where the breakdown is reported and left absent where it\n // is not (AGL-3143), never set to a zero the provider did not\n // send. A stream needs it for the reason a completion does: it\n // is the figure that accounts for a spent ceiling first, and it\n // arrives in the same usage object as the four above.\n if (delta.thinkingTokens !== undefined) usage.thinkingTokens = delta.thinkingTokens\n const reason = (event['delta'] as { stop_reason?: unknown } | undefined)\n ?.stop_reason\n if (typeof reason === 'string' && reason) stopReason = reason\n break\n }\n case 'error': {\n const error = event['error'] as\n | { type?: string; message?: string }\n | undefined\n console.error('ai upstream stream error', {\n provider: ANTHROPIC_PROVIDER_ID,\n requestId,\n model,\n error: error ?? null,\n })\n yield { type: 'error', retryable: anthropicFailureIsRetryable(null, error?.type) }\n break\n }\n default:\n break\n }\n }\n }\n } finally {\n // A consumer that stops iterating early — a client that hung up — must\n // not leave the provider generating into a socket nobody reads: cancel\n // tells the upstream to stop, and the tokens it has already produced are\n // the only ones billed.\n if (!drained) await reader.cancel().catch(() => undefined)\n reader.releaseLock()\n }\n // A message the ceiling ends mid-block never reaches that block's stop\n // event, so what it had written is still held in flight.\n for (const tool of tools.values()) written.push(tool.json)\n yield {\n type: 'done',\n usage,\n estCostUsd: estimateAiBilledUsd(usage, model),\n stopReason,\n // What the model emitted into its tool calls, for a stream its ceiling\n // cut off (AGL-3143): the `tool` events carry only what parsed out.\n ...(aiStoppedAtCeiling(stopReason) ? { rawOutput: aiRawOutputOf(written.join('')) } : {}),\n }\n}\n\nexport const anthropicProvider: AiProvider = {\n id: ANTHROPIC_PROVIDER_ID,\n label: 'Anthropic',\n apiKeyEnv: ANTHROPIC_API_KEY_ENV,\n readApiKey: () => process.env.ANTHROPIC_API_KEY?.trim() || undefined,\n endpointHost: ANTHROPIC_HOST,\n toolSchemaLimits: ANTHROPIC_TOOL_SCHEMA_LIMITS,\n models(): readonly AiModelDescriptor[] {\n return aiModelIdsForProvider(ANTHROPIC_PROVIDER_ID)\n .map((id) => aiCatalogEntry(id))\n .filter((entry): entry is NonNullable<typeof entry> => Boolean(entry))\n },\n complete,\n stream,\n}\n"],"names":["aiModelIdsForProvider","estimateAiBilledUsd","aiCatalogEntry","AiUpstreamError","aiRawOutputOf","aiStoppedAtCeiling","aiTokenCount","aiToolInputOf","ANTHROPIC_PROVIDER_ID","ANTHROPIC_API_KEY_ENV","ANTHROPIC_HOST","ANTHROPIC_URL","ANTHROPIC_VERSION","ANTHROPIC_MAX_CACHE_BREAKPOINTS","ANTHROPIC_TOOL_SCHEMA_LIMITS","strictTools","optionalParameters","unionParameters","compiledSchemaBytes","anthropicFailureIsRetryable","status","errorType","anthropicAccountProblem","error","type","test","message","anthropicUsageFrom","usage","record","details","thinking","undefined","inputTokens","outputTokens","cacheReadTokens","cacheWriteTokens","thinkingTokens","buildAnthropicRequestBody","input","breakpoints","system","filter","block","cacheBreakpoint","length","Error","map","text","cache_control","tools","tool","name","description","input_schema","inputSchema","additionalProperties","strict","settable","model","capabilities","effort","max_tokens","maxTokens","stream","output_config","messages","role","content","anthropicContentOf","tool_choice","part","source","media_type","mediaType","data","requestIdOf","response","headers","get","send","body","fetch","method","apiKey","JSON","stringify","signal","ok","payload","requestId","json","catch","console","provider","complete","blocks","Array","isArray","String","join","toolUse","estCostUsd","stopReason","stop_reason","kind","rawOutput","streamEvents","decoder","TextDecoder","reader","getReader","Map","written","buffer","drained","lines","done","value","read","decode","split","pop","line","startsWith","event","parse","slice","index","Number","start","set","delta","partial_json","delete","push","reason","retryable","cancel","releaseLock","values","anthropicProvider","id","label","apiKeyEnv","readApiKey","process","env","ANTHROPIC_API_KEY","trim","endpointHost","toolSchemaLimits","models","entry","Boolean"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/providers/anthropic.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 { aiModelIdsForProvider, estimateAiBilledUsd, aiCatalogEntry } from './catalog'\nimport {\n AiUpstreamError,\n type AiAccountProblem,\n type AiBatchOptions,\n type AiEffort,\n aiRawOutputOf,\n aiStoppedAtCeiling,\n aiTokenCount,\n aiToolInputOf,\n type AiMessage,\n type AiModelDescriptor,\n type AiProvider,\n type AiProviderRequest,\n type AiResult,\n type AiStreamEvent,\n type AiToolSchemaLimits,\n type AiToolUse,\n type AiUsage,\n} from './contract'\n\n/**\n * The Anthropic adapter (AGL-2903, behind the contract since AGL-2939):\n * the Messages API over raw `fetch`. No provider SDK is installed, and the\n * meter prices by model id from the catalog, so nothing an SDK would add\n * is used here. This file and the catalog are the only places in the\n * plugin that name the vendor's URL, header or model ids.\n *\n * ── Errors (AGL-2815) ─────────────────────────────────────────────────────\n *\n * Provider error text describes OUR account with the vendor — a key, a rate\n * limit, a balance — and names the vendor to a white-label org's users. It\n * never leaves this module as a message: a non-2xx answer becomes an\n * `AiUpstreamError` carrying the status, whether the failure is retryable\n * and a fixed customer-safe sentence; the provider's body goes to\n * `console.error` beside the request id, where an operator can find it.\n * A `refusal` stop is not an error at all — the tokens were spent and the\n * model answered — so it comes back as a typed `AiRefusal` result.\n */\n\nexport const ANTHROPIC_PROVIDER_ID = 'anthropic'\nexport const ANTHROPIC_API_KEY_ENV = 'ANTHROPIC_API_KEY'\nconst ANTHROPIC_HOST = 'api.anthropic.com'\nconst ANTHROPIC_URL = `https://${ANTHROPIC_HOST}/v1/messages`\nconst ANTHROPIC_BATCHES_URL = `https://${ANTHROPIC_HOST}/v1/messages/batches`\nconst ANTHROPIC_VERSION = '2023-06-01'\n\n/** The Messages API accepts at most this many `cache_control` markers. */\nexport const ANTHROPIC_MAX_CACHE_BREAKPOINTS = 4\n\n/**\n * What the Messages API compiles of one request's strict schemas, as its\n * structured-outputs documentation states the limits: 20 strict tools, 24\n * optional parameters and 16 parameters with union types, each a total over\n * every strict schema the request carries. Past any of them the request is\n * refused with a 400 before the model runs.\n *\n * `compiledSchemaBytes` is not one of those. The API also refuses a request\n * whose schemas compile to too large a grammar — \"Simplify your tool schemas\n * or reduce the number of strict tools\" — and states no size for it, so this\n * bound is measured rather than read (AGL-3096). Its evidence is two live\n * requests for the automation draft, the largest strict schema anything here\n * sends:\n *\n * - 8,757 bytes, refused for grammar size (`req_011CfC6Fif9iJvmKPTRgtLdp`,\n * 2026-09-19), with 1 strict tool, 0 optional parameters and 2 unions:\n * every published count was green;\n * - 3,807 bytes, served (`req_011CfELn62WVLeaNzwK4TWgb`, 2026-09-20), the\n * same tool with the guard lifted out of the steps' union and one variant\n * per set of fields.\n *\n * Everything else the plugin sends is smaller still, the next largest being\n * the theme tool at 2,410 bytes. The bound sits at what has been served, so a\n * schema that grows past it has to be proved live before the bound moves.\n */\nexport const ANTHROPIC_TOOL_SCHEMA_LIMITS: AiToolSchemaLimits = {\n strictTools: 20,\n optionalParameters: 24,\n unionParameters: 16,\n compiledSchemaBytes: 3_807,\n}\n\n/**\n * Whether a provider failure is the kind that clears on its own. Matched on\n * the status AND the error type, because the in-stream `error` event has no\n * status to go by.\n */\nexport function anthropicFailureIsRetryable(\n status: number | null,\n errorType: string | undefined,\n): boolean {\n return (\n status === 429 ||\n status === 529 ||\n errorType === 'rate_limit_error' ||\n errorType === 'overloaded_error'\n )\n}\n\n/**\n * Whether a failure is about the platform's Anthropic account rather than the\n * request (AGL-3377): a refused key, or a balance too low to answer.\n */\nexport function anthropicAccountProblem(\n status: number | null,\n error: { type?: string; message?: string } | null | undefined,\n): AiAccountProblem | null {\n if (status === 401 || status === 403) return 'credentials'\n if (error?.type === 'authentication_error' || error?.type === 'permission_error') {\n return 'credentials'\n }\n if (error?.type === 'billing_error' || /credit balance/i.test(error?.message ?? '')) {\n return 'credit'\n }\n return null\n}\n\n/** Anthropic's `usage` object, in the meter's shape. Missing fields read 0. */\nexport function anthropicUsageFrom(usage: unknown): AiUsage {\n const record = (usage ?? {}) as Record<string, unknown>\n // Part of `output_tokens`, and carried only where the response breaks them\n // down, so an answer that reports none says nothing rather than zero.\n const details = record['output_tokens_details']\n const thinking =\n details && typeof details === 'object'\n ? (details as Record<string, unknown>)['thinking_tokens']\n : undefined\n return {\n inputTokens: aiTokenCount(record['input_tokens']),\n outputTokens: aiTokenCount(record['output_tokens']),\n cacheReadTokens: aiTokenCount(record['cache_read_input_tokens']),\n cacheWriteTokens: aiTokenCount(record['cache_creation_input_tokens']),\n ...(thinking === undefined ? {} : { thinkingTokens: aiTokenCount(thinking) }),\n }\n}\n\n/**\n * How \"thinking off\" is said to a model that refuses `{type: \"disabled\"}`.\n * Claude Sonnet 5.5 turns it off only through `between_tools` (accepted at\n * effort high or below, which is every effort the contract names); Claude\n * Opus 5.5 cannot turn it off at all, so the field is left out and the\n * model's adaptive thinking runs. Every other model takes `disabled`.\n */\nconst ANTHROPIC_THINKING_OFF: Readonly<Record<string, 'between_tools' | 'omit'>> = {\n 'claude-sonnet-5-5': 'between_tools',\n 'claude-opus-5-5': 'omit',\n}\n\n/**\n * The effort a request that names none is sent, for a model whose own\n * default is lower than its siblings': Claude Opus 5.5 defaults to medium,\n * where Claude Opus 5 defaults to high.\n */\nconst ANTHROPIC_DEFAULT_EFFORT: Readonly<Record<string, AiEffort>> = {\n 'claude-opus-5-5': 'high',\n}\n\n/**\n * The Messages API body for a request. Exported so a spec can assert the\n * wire shape without a network. The cache-prefix rule is enforced by the\n * runtime before the request reaches any adapter; this maps the surviving\n * breakpoints onto `cache_control` and refuses only the count the API\n * itself refuses.\n */\nexport function buildAnthropicRequestBody(\n input: Omit<AiProviderRequest, 'apiKey' | 'signal'> & { stream: boolean },\n): Record<string, unknown> {\n const breakpoints = input.system.filter((block) => block.cacheBreakpoint)\n if (breakpoints.length > ANTHROPIC_MAX_CACHE_BREAKPOINTS) {\n throw new Error(\n `${breakpoints.length} cache breakpoints; the Messages API allows ${ANTHROPIC_MAX_CACHE_BREAKPOINTS}`,\n )\n }\n // One lifetime for every breakpoint: the API refuses a longer-lived entry\n // after a shorter one, and a request asks for one or the other.\n const cacheControl = input.cacheTtl === '1h' ? { type: 'ephemeral', ttl: '1h' } : { type: 'ephemeral' }\n const system = input.system.map((block) => ({\n type: 'text',\n text: block.text,\n ...(block.cacheBreakpoint ? { cache_control: cacheControl } : {}),\n }))\n const tools = input.tools?.map((tool) => ({\n name: tool.name,\n description: tool.description,\n input_schema: { ...tool.inputSchema, additionalProperties: false },\n strict: true,\n }))\n // A model that rejects an explicit thinking setting gets none, whatever\n // the door asked for, and no effort either: effort rides the same rule\n // (see the contract), and the catalog says which models those are.\n const settable = aiCatalogEntry(input.model)?.capabilities.thinking !== false\n const thinking = settable ? input.thinking : undefined\n const effort = settable ? (input.effort ?? ANTHROPIC_DEFAULT_EFFORT[input.model]) : undefined\n const thinkingOff = ANTHROPIC_THINKING_OFF[input.model] ?? 'disabled'\n return {\n model: input.model,\n max_tokens: input.maxTokens,\n ...(input.stream ? { stream: true } : {}),\n ...(thinking === 'off'\n ? thinkingOff === 'omit'\n ? {}\n : { thinking: { type: thinkingOff } }\n : thinking === 'adaptive'\n ? { thinking: { type: 'adaptive' } }\n : {}),\n ...(effort ? { output_config: { effort } } : {}),\n ...(system.length ? { system } : {}),\n messages: input.messages.map((message) => ({\n role: message.role,\n content: anthropicContentOf(message),\n })),\n ...(tools?.length ? { tools, tool_choice: { type: 'auto' } } : {}),\n }\n}\n\n/**\n * A turn's content in the Messages API's shape: a text-only turn as the\n * string it is, and a turn with pictures as content blocks in order, each\n * picture a base64 image block (AGL-2916).\n */\nfunction anthropicContentOf(message: AiMessage): string | Array<Record<string, unknown>> {\n if (typeof message.content === 'string') return message.content\n return message.content.map((part) =>\n part.type === 'image'\n ? { type: 'image', source: { type: 'base64', media_type: part.mediaType, data: part.data } }\n : { type: 'text', text: part.text },\n )\n}\n\n/** The provider's request id, when it sent one — the log's join key. */\nfunction requestIdOf(response: Response): string | null {\n return response.headers?.get?.('request-id') ?? null\n}\n\nasync function send(\n input: AiProviderRequest,\n stream: boolean,\n): Promise<Response> {\n const body = buildAnthropicRequestBody({ ...input, stream })\n const response = await fetch(ANTHROPIC_URL, {\n method: 'POST',\n headers: {\n 'x-api-key': input.apiKey,\n 'anthropic-version': ANTHROPIC_VERSION,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(body),\n ...(input.signal ? { signal: input.signal } : {}),\n })\n if (!response.ok || (stream && !response.body)) {\n const requestId = requestIdOf(response)\n const payload = (await response.json().catch(() => null)) as {\n error?: { type?: string; message?: string }\n } | null\n console.error('ai upstream error', {\n provider: ANTHROPIC_PROVIDER_ID,\n status: response.status,\n requestId,\n model: input.model,\n error: payload?.error ?? null,\n })\n throw new AiUpstreamError(\n response.status,\n anthropicFailureIsRetryable(response.status, payload?.error?.type),\n requestId,\n anthropicAccountProblem(response.status, payload?.error),\n )\n }\n return response\n}\n\nasync function complete(input: AiProviderRequest): Promise<AiResult> {\n const response = await send(input, false)\n return anthropicResultFrom(await response.json(), input.model)\n}\n\n/**\n * A Messages API answer as the contract's result: the shape `complete` reads\n * off the wire and a batch's succeeded entry carries. `priceFactor` is what a\n * discount leaves of the price (a batch's half).\n */\nexport function anthropicResultFrom(raw: unknown, model: string, priceFactor = 1): AiResult {\n const payload = raw as {\n content?: Array<Record<string, unknown>>\n stop_reason?: unknown\n usage?: unknown\n } | null\n const blocks = Array.isArray(payload?.content) ? payload.content : []\n const text = blocks\n .filter((block) => block?.['type'] === 'text')\n .map((block) => String(block['text'] ?? ''))\n .join('')\n const toolUse: AiToolUse[] = blocks\n .filter((block) => block?.['type'] === 'tool_use')\n .map((block) => ({\n name: String(block['name'] ?? ''),\n input: aiToolInputOf(block['input']),\n }))\n const usage = anthropicUsageFrom(payload?.usage)\n const estCostUsd = Math.round(estimateAiBilledUsd(usage, model) * priceFactor * 1_000_000) / 1_000_000\n const stopReason =\n typeof payload?.stop_reason === 'string' && payload.stop_reason\n ? payload.stop_reason\n : null\n if (stopReason === 'refusal') {\n return { kind: 'refusal', text, usage, estCostUsd, stopReason }\n }\n return {\n kind: 'completion',\n text,\n toolUse,\n usage,\n estCostUsd,\n stopReason,\n // The blocks as the provider answered them, for a call its ceiling cut\n // off (AGL-3143): `toolUse` holds only what still parsed out of them.\n ...(aiStoppedAtCeiling(stopReason) ? { rawOutput: aiRawOutputOf(blocks) } : {}),\n }\n}\n\nasync function stream(input: AiProviderRequest): Promise<AsyncIterable<AiStreamEvent>> {\n const response = await send(input, true)\n return streamEvents(\n response.body as ReadableStream<Uint8Array>,\n input.model,\n requestIdOf(response),\n )\n}\n\n/**\n * Anthropic's SSE stream as contract events. Usage is taken from\n * `message_start` (input and cache figures) and `message_delta` (the\n * output count, and any cumulative input figures a newer API sends); the\n * `done` event carries whatever was known when the body ended, so a stream\n * cut short still meters what it cost.\n */\nasync function* streamEvents(\n body: ReadableStream<Uint8Array>,\n model: string,\n requestId: string | null,\n): AsyncGenerator<AiStreamEvent> {\n const decoder = new TextDecoder()\n const reader = body.getReader()\n const usage: AiUsage = {\n inputTokens: 0,\n outputTokens: 0,\n cacheReadTokens: 0,\n cacheWriteTokens: 0,\n }\n let stopReason: string | null = null\n /** Tool-use blocks in flight, by content index; input arrives in pieces. */\n const tools = new Map<number, { name: string; json: string }>()\n /**\n * What each tool call was actually written in, in the order its block\n * opened (AGL-3143). The `tool` events below carry only as much of these\n * as `aiToolInputOf` could still parse, so for a call the ceiling cut off\n * this is the one place the emitted bytes survive.\n */\n const written: string[] = []\n let buffer = ''\n let drained = false\n try {\n for (;;) {\n const { done, value } = await reader.read()\n if (done) {\n drained = true\n break\n }\n buffer += decoder.decode(value, { stream: true })\n const lines = buffer.split('\\n')\n buffer = lines.pop() ?? ''\n for (const line of lines) {\n if (!line.startsWith('data: ')) continue\n let event: Record<string, unknown>\n try {\n event = JSON.parse(line.slice('data: '.length))\n } catch {\n continue\n }\n const index = Number(event['index'])\n switch (event['type']) {\n case 'message_start': {\n const start = anthropicUsageFrom(\n (event['message'] as { usage?: unknown } | undefined)?.usage,\n )\n usage.inputTokens = start.inputTokens\n usage.cacheReadTokens = start.cacheReadTokens\n usage.cacheWriteTokens = start.cacheWriteTokens\n break\n }\n case 'content_block_start': {\n const block = event['content_block'] as\n | { type?: string; name?: string }\n | undefined\n if (block?.type === 'tool_use') {\n tools.set(index, { name: String(block.name ?? ''), json: '' })\n }\n break\n }\n case 'content_block_delta': {\n const delta = event['delta'] as\n | { type?: string; text?: string; partial_json?: string }\n | undefined\n if (delta?.type === 'text_delta' && delta.text) {\n yield { type: 'delta', text: delta.text }\n } else if (delta?.type === 'input_json_delta') {\n const tool = tools.get(index)\n if (tool) tool.json += delta.partial_json ?? ''\n }\n break\n }\n case 'content_block_stop': {\n const tool = tools.get(index)\n if (tool) {\n tools.delete(index)\n written.push(tool.json)\n yield { type: 'tool', name: tool.name, input: aiToolInputOf(tool.json) }\n }\n break\n }\n case 'message_delta': {\n const delta = anthropicUsageFrom(event['usage'])\n usage.outputTokens = delta.outputTokens || usage.outputTokens\n usage.inputTokens = delta.inputTokens || usage.inputTokens\n usage.cacheReadTokens = delta.cacheReadTokens || usage.cacheReadTokens\n usage.cacheWriteTokens = delta.cacheWriteTokens || usage.cacheWriteTokens\n // Kept where the breakdown is reported and left absent where it\n // is not (AGL-3143), never set to a zero the provider did not\n // send. A stream needs it for the reason a completion does: it\n // is the figure that accounts for a spent ceiling first, and it\n // arrives in the same usage object as the four above.\n if (delta.thinkingTokens !== undefined) usage.thinkingTokens = delta.thinkingTokens\n const reason = (event['delta'] as { stop_reason?: unknown } | undefined)\n ?.stop_reason\n if (typeof reason === 'string' && reason) stopReason = reason\n break\n }\n case 'error': {\n const error = event['error'] as\n | { type?: string; message?: string }\n | undefined\n console.error('ai upstream stream error', {\n provider: ANTHROPIC_PROVIDER_ID,\n requestId,\n model,\n error: error ?? null,\n })\n yield { type: 'error', retryable: anthropicFailureIsRetryable(null, error?.type) }\n break\n }\n default:\n break\n }\n }\n }\n } finally {\n // A consumer that stops iterating early — a client that hung up — must\n // not leave the provider generating into a socket nobody reads: cancel\n // tells the upstream to stop, and the tokens it has already produced are\n // the only ones billed.\n if (!drained) await reader.cancel().catch(() => undefined)\n reader.releaseLock()\n }\n // A message the ceiling ends mid-block never reaches that block's stop\n // event, so what it had written is still held in flight.\n for (const tool of tools.values()) written.push(tool.json)\n yield {\n type: 'done',\n usage,\n estCostUsd: estimateAiBilledUsd(usage, model),\n stopReason,\n // What the model emitted into its tool calls, for a stream its ceiling\n // cut off (AGL-3143): the `tool` events carry only what parsed out.\n ...(aiStoppedAtCeiling(stopReason) ? { rawOutput: aiRawOutputOf(written.join('')) } : {}),\n }\n}\n\n/** What a batch's discount leaves of a request's price. */\nexport const ANTHROPIC_BATCH_PRICE_FACTOR = 0.5\n\nfunction batchHeaders(apiKey: string): Record<string, string> {\n return {\n 'x-api-key': apiKey,\n 'anthropic-version': ANTHROPIC_VERSION,\n 'Content-Type': 'application/json',\n }\n}\n\n/** A batch call that did not answer 2xx, as the contract's error. */\nasync function batchFailure(response: Response, model: string): Promise<AiUpstreamError> {\n const requestId = requestIdOf(response)\n const payload = (await response.json().catch(() => null)) as {\n error?: { type?: string; message?: string }\n } | null\n console.error('ai upstream batch error', {\n provider: ANTHROPIC_PROVIDER_ID,\n status: response.status,\n requestId,\n model,\n error: payload?.error ?? null,\n })\n return new AiUpstreamError(\n response.status,\n anthropicFailureIsRetryable(response.status, payload?.error?.type),\n requestId,\n anthropicAccountProblem(response.status, payload?.error),\n )\n}\n\n/**\n * Many requests through the Message Batches API (AGL-3660): created as one\n * batch, polled until it has ended, its results read by `custom_id` — they\n * come back in any order — and each turned into the result `complete` would\n * have returned, at half the price. Development only: the live evals' batch\n * mode is the one caller, and no door waits minutes for an answer.\n */\nasync function completeBatch(\n requests: readonly AiProviderRequest[],\n options: AiBatchOptions = {},\n): Promise<Array<AiResult | Error>> {\n if (!requests.length) return []\n const apiKey = requests[0].apiKey\n const model = requests[0].model\n const pollMs = options.pollMs ?? 10_000\n const timeoutMs = options.timeoutMs ?? 60 * 60_000\n const created = await fetch(ANTHROPIC_BATCHES_URL, {\n method: 'POST',\n headers: batchHeaders(apiKey),\n body: JSON.stringify({\n requests: requests.map((request, index) => {\n const { apiKey: _key, signal: _signal, ...rest } = request\n return { custom_id: `r${index}`, params: buildAnthropicRequestBody({ ...rest, stream: false }) }\n }),\n }),\n })\n if (!created.ok) throw await batchFailure(created, model)\n let batch = (await created.json()) as { id: string; processing_status?: string; results_url?: string | null }\n const deadline = Date.now() + timeoutMs\n while (batch.processing_status !== 'ended') {\n if (Date.now() > deadline) {\n await fetch(`${ANTHROPIC_BATCHES_URL}/${batch.id}/cancel`, { method: 'POST', headers: batchHeaders(apiKey) }).catch(\n () => undefined,\n )\n throw new Error(`batch ${batch.id} did not end within ${timeoutMs} ms; it was canceled`)\n }\n await new Promise((resolve) => setTimeout(resolve, pollMs))\n const polled = await fetch(`${ANTHROPIC_BATCHES_URL}/${batch.id}`, { headers: batchHeaders(apiKey) })\n if (!polled.ok) throw await batchFailure(polled, model)\n batch = (await polled.json()) as typeof batch\n }\n if (!batch.results_url) throw new Error(`batch ${batch.id} ended with no results`)\n const results = await fetch(batch.results_url, { headers: batchHeaders(apiKey) })\n if (!results.ok) throw await batchFailure(results, model)\n const byId = new Map<string, { type?: string; message?: unknown; error?: unknown }>()\n for (const line of (await results.text()).split('\\n')) {\n if (!line.trim()) continue\n const entry = JSON.parse(line) as { custom_id: string; result?: { type?: string; message?: unknown; error?: unknown } }\n byId.set(entry.custom_id, entry.result ?? {})\n }\n return requests.map((request, index) => {\n const result = byId.get(`r${index}`)\n if (result?.type === 'succeeded') {\n return anthropicResultFrom(result.message, request.model, ANTHROPIC_BATCH_PRICE_FACTOR)\n }\n console.error('ai batch request not answered', {\n provider: ANTHROPIC_PROVIDER_ID,\n batchId: batch.id,\n customId: `r${index}`,\n result: result?.type ?? 'missing',\n error: result?.error ?? null,\n })\n return new AiUpstreamError(null, result?.type === 'expired' || result?.type === 'errored', batch.id, null)\n })\n}\n\nexport const anthropicProvider: AiProvider = {\n id: ANTHROPIC_PROVIDER_ID,\n label: 'Anthropic',\n apiKeyEnv: ANTHROPIC_API_KEY_ENV,\n readApiKey: () => process.env.ANTHROPIC_API_KEY?.trim() || undefined,\n endpointHost: ANTHROPIC_HOST,\n toolSchemaLimits: ANTHROPIC_TOOL_SCHEMA_LIMITS,\n models(): readonly AiModelDescriptor[] {\n return aiModelIdsForProvider(ANTHROPIC_PROVIDER_ID)\n .map((id) => aiCatalogEntry(id))\n .filter((entry): entry is NonNullable<typeof entry> => Boolean(entry))\n },\n complete,\n stream,\n completeBatch,\n}\n"],"names":["aiModelIdsForProvider","estimateAiBilledUsd","aiCatalogEntry","AiUpstreamError","aiRawOutputOf","aiStoppedAtCeiling","aiTokenCount","aiToolInputOf","ANTHROPIC_PROVIDER_ID","ANTHROPIC_API_KEY_ENV","ANTHROPIC_HOST","ANTHROPIC_URL","ANTHROPIC_BATCHES_URL","ANTHROPIC_VERSION","ANTHROPIC_MAX_CACHE_BREAKPOINTS","ANTHROPIC_TOOL_SCHEMA_LIMITS","strictTools","optionalParameters","unionParameters","compiledSchemaBytes","anthropicFailureIsRetryable","status","errorType","anthropicAccountProblem","error","type","test","message","anthropicUsageFrom","usage","record","details","thinking","undefined","inputTokens","outputTokens","cacheReadTokens","cacheWriteTokens","thinkingTokens","ANTHROPIC_THINKING_OFF","ANTHROPIC_DEFAULT_EFFORT","buildAnthropicRequestBody","input","breakpoints","system","filter","block","cacheBreakpoint","length","Error","cacheControl","cacheTtl","ttl","map","text","cache_control","tools","tool","name","description","input_schema","inputSchema","additionalProperties","strict","settable","model","capabilities","effort","thinkingOff","max_tokens","maxTokens","stream","output_config","messages","role","content","anthropicContentOf","tool_choice","part","source","media_type","mediaType","data","requestIdOf","response","headers","get","send","body","fetch","method","apiKey","JSON","stringify","signal","ok","payload","requestId","json","catch","console","provider","complete","anthropicResultFrom","raw","priceFactor","blocks","Array","isArray","String","join","toolUse","estCostUsd","Math","round","stopReason","stop_reason","kind","rawOutput","streamEvents","decoder","TextDecoder","reader","getReader","Map","written","buffer","drained","lines","done","value","read","decode","split","pop","line","startsWith","event","parse","slice","index","Number","start","set","delta","partial_json","delete","push","reason","retryable","cancel","releaseLock","values","ANTHROPIC_BATCH_PRICE_FACTOR","batchHeaders","batchFailure","completeBatch","requests","options","pollMs","timeoutMs","created","request","_key","_signal","rest","custom_id","params","batch","deadline","Date","now","processing_status","id","Promise","resolve","setTimeout","polled","results_url","results","byId","entry","trim","result","batchId","customId","anthropicProvider","label","apiKeyEnv","readApiKey","process","env","ANTHROPIC_API_KEY","endpointHost","toolSchemaLimits","models","Boolean"],"mappings":"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"}
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
*/
|
|
17
17
|
import type { PluginSubprocessorDeclaration } from '@aglyn/aglyn/plugin-manager/plugin-subprocessors';
|
|
18
18
|
import type { AiModelDescriptor, AiUsage } from './contract';
|
|
19
|
+
import type { AiImageSize } from './image-contract';
|
|
19
20
|
/**
|
|
20
21
|
* The model catalog (AGL-2939): every model id the plugin will route to,
|
|
21
22
|
* with its provider, its display name, its capabilities and its list rates.
|
|
@@ -76,6 +77,8 @@ export interface AiCatalogRates {
|
|
|
76
77
|
* once so the pair cannot drift.
|
|
77
78
|
*/
|
|
78
79
|
export declare function aiRatesAtList(inputPerMTok: number, outputPerMTok: number): AiCatalogRates;
|
|
80
|
+
/** {@link aiRatesAtList} for a model whose cache read is not a tenth of its input price. */
|
|
81
|
+
export declare function aiRatesAtListWithCacheRead(inputPerMTok: number, outputPerMTok: number, cacheReadPerMTok: number): AiCatalogRates;
|
|
79
82
|
export interface AiCatalogEntry extends AiModelDescriptor, AiCatalogRates {
|
|
80
83
|
/**
|
|
81
84
|
* The tier a routing decision reads: `fast` for short, constrained
|
|
@@ -149,7 +152,7 @@ export declare const ANTHROPIC_CRM_ASSISTANCE_DISCLOSED: AnthropicCrmAssistanceW
|
|
|
149
152
|
* wording the Subprocessors row and Privacy Policy section 2 were
|
|
150
153
|
* republished with on October 5, 2026 (legal v10), before
|
|
151
154
|
* `release_crm_assist_whole_record` may be turned on. The catalog row below
|
|
152
|
-
* carries it
|
|
155
|
+
* carries it in `dataReceived`.
|
|
153
156
|
*/
|
|
154
157
|
export declare const ANTHROPIC_CRM_ASSISTANCE_WHOLE_RECORD: AnthropicCrmAssistanceWording;
|
|
155
158
|
/** The Anthropic row's data cell, with CRM assistance worded as `crm` words it. */
|
|
@@ -190,6 +193,12 @@ export declare const AI_MODEL_CATALOG: readonly AiCatalogEntry[];
|
|
|
190
193
|
*
|
|
191
194
|
* A credit is $0.001 of billed spend (`ASSIST_CREDIT_COST_USD`), so the
|
|
192
195
|
* default model's picture is 101 credits before its prompt and thinking.
|
|
196
|
+
*
|
|
197
|
+
* Every per-picture figure on a row is the 1K picture's. A 512 px picture —
|
|
198
|
+
* what the Free plan makes — is written as fewer image tokens at the same
|
|
199
|
+
* per-token rate (`AI_IMAGE_SIZE_OUTPUT_TOKENS`), so it is priced at the 1K
|
|
200
|
+
* figure scaled by its share of tokens: $0.04482 from the provider and
|
|
201
|
+
* $0.06723 billed on the default model, before its prompt and thinking.
|
|
193
202
|
*/
|
|
194
203
|
export interface AiImageCatalogEntry extends AiCatalogRates {
|
|
195
204
|
id: string;
|
|
@@ -213,10 +222,29 @@ export declare const AI_IMAGE_BILLED_MARKUP = 1.5;
|
|
|
213
222
|
* `AI_IMAGE_BILLED_MARKUP`.
|
|
214
223
|
*/
|
|
215
224
|
export declare function aiImageRatesAtMarkup(providerUsdPerImage: number, inputPerMTok: number, outputPerMTok: number): Pick<AiImageCatalogEntry, 'providerUsdPerImage' | 'billedUsdPerImage' | 'providerRates' | 'billedRates'>;
|
|
225
|
+
/**
|
|
226
|
+
* The image-output tokens Google writes a picture as, by size (AGL-3602),
|
|
227
|
+
* read from the usage of real Gemini 3.1 Flash Image answers on 2026-10-07:
|
|
228
|
+
* 747 at 512 px and 1,120 at 1K. A row's per-picture figures are the 1K
|
|
229
|
+
* picture's; a 512 px picture is priced at its share of them.
|
|
230
|
+
*/
|
|
231
|
+
export declare const AI_IMAGE_SIZE_OUTPUT_TOKENS: Readonly<Record<AiImageSize, number>>;
|
|
216
232
|
/** The image model a photo is made with when the operator names none. */
|
|
217
233
|
export declare const AI_IMAGE_DEFAULT_MODEL = "gemini-3.1-flash-image";
|
|
218
234
|
/** The image provider's id: Google's models on Vertex AI. */
|
|
219
235
|
export declare const AI_IMAGE_VERTEX_PROVIDER_ID = "google-vertex";
|
|
236
|
+
/**
|
|
237
|
+
* The image providers' rows on the published subprocessor list, kept apart
|
|
238
|
+
* from `AI_CATALOG_PROVIDERS` for the reason the image catalog is kept apart
|
|
239
|
+
* from the text one: a settings form offers text providers from that list,
|
|
240
|
+
* and an image provider answers no conversation. The host is the adapter's
|
|
241
|
+
* published endpoint (`VERTEX_IMAGE_PUBLISHED_HOST`).
|
|
242
|
+
*
|
|
243
|
+
* Google's row is dated to its change-log entry on `/legal/subprocessors`,
|
|
244
|
+
* published with the Privacy Policy §2 sentence naming Google for image
|
|
245
|
+
* generation (legal v12).
|
|
246
|
+
*/
|
|
247
|
+
export declare const AI_IMAGE_CATALOG_PROVIDERS: readonly AiCatalogProvider[];
|
|
220
248
|
export declare const AI_IMAGE_MODEL_CATALOG: readonly AiImageCatalogEntry[];
|
|
221
249
|
/**
|
|
222
250
|
* The per-picture rates an unknown image model id is priced at: the dearest
|
|
@@ -226,17 +254,19 @@ export declare const AI_IMAGE_MODEL_CATALOG: readonly AiImageCatalogEntry[];
|
|
|
226
254
|
export declare const AI_IMAGE_FALLBACK_RATES: Pick<AiImageCatalogEntry, 'providerUsdPerImage' | 'billedUsdPerImage'>;
|
|
227
255
|
/** The image catalog row for a model id, or `undefined` for an unknown id. */
|
|
228
256
|
export declare function aiImageCatalogEntry(modelId: string): AiImageCatalogEntry | undefined;
|
|
229
|
-
/** What the provider charges us for one picture from `modelId
|
|
230
|
-
export declare function aiImageProviderUsdPerImage(modelId: string): number;
|
|
231
|
-
/** What one picture from `modelId` draws from a customer's credits. */
|
|
232
|
-
export declare function aiImageBilledUsdPerImage(modelId: string): number;
|
|
257
|
+
/** What the provider charges us for one picture from `modelId`, at `size` (1K when absent). */
|
|
258
|
+
export declare function aiImageProviderUsdPerImage(modelId: string, size?: AiImageSize): number;
|
|
259
|
+
/** What one picture from `modelId` at `size` (1K when absent) draws from a customer's credits. */
|
|
260
|
+
export declare function aiImageBilledUsdPerImage(modelId: string, size?: AiImageSize): number;
|
|
233
261
|
/**
|
|
234
262
|
* Usage as the meter prices it: a text exchange's tokens, and, for a door
|
|
235
|
-
* that makes pictures, how many it delivered
|
|
236
|
-
* text exchange, which prices exactly
|
|
263
|
+
* that makes pictures, how many it delivered and at what size (1K when
|
|
264
|
+
* absent). `images` is absent on every text exchange, which prices exactly
|
|
265
|
+
* as it always did.
|
|
237
266
|
*/
|
|
238
267
|
export type AiMeteredUsage = AiUsage & {
|
|
239
268
|
images?: number;
|
|
269
|
+
imageSize?: AiImageSize;
|
|
240
270
|
};
|
|
241
271
|
/** The dearest known tier, used when a model id is not in the catalog. */
|
|
242
272
|
export declare const AI_FALLBACK_RATES: AiTokenRates;
|
|
@@ -290,7 +320,7 @@ export declare function aiModelIdsForProvider(providerId: string): string[];
|
|
|
290
320
|
* incident override, an org's own setting, a cheaper model for a cheap
|
|
291
321
|
* step — is one row rather than a search through the doors (AGL-2937).
|
|
292
322
|
*/
|
|
293
|
-
export type AiStepKind = 'assist.chat' | 'copy.element' | 'copy.section' | 'copy.blog' | 'generate.section' | 'job.component' | 'job.crm' | 'job.experiment' | 'job.form' | 'job.insight' | 'job.layout' | 'job.logic' | 'job.template' | 'job.page' | 'job.products' | 'job.seo' | 'job.text' | 'job.theme' | 'job.plan' | 'job.email' | 'job.campaign' | 'job.workflow';
|
|
323
|
+
export type AiStepKind = 'assist.chat' | 'copy.element' | 'copy.section' | 'copy.blog' | 'generate.section' | 'job.component' | 'job.crm' | 'job.edit' | 'job.experiment' | 'job.form' | 'job.insight' | 'job.layout' | 'job.logic' | 'job.template' | 'job.page' | 'job.products' | 'job.seo' | 'job.text' | 'job.theme' | 'job.plan' | 'job.email' | 'job.campaign' | 'job.workflow';
|
|
294
324
|
/** The tier each step kind is served from when no setting overrides it. */
|
|
295
325
|
export declare const AI_STEP_TIERS: Record<AiStepKind, AiCatalogEntry['tier']>;
|
|
296
326
|
/** The first catalog model of a tier on a provider, or the provider's first model. */
|
|
@@ -31,6 +31,15 @@
|
|
|
31
31
|
billedRates: aiRatesPerMTok(inputPerMTok, outputPerMTok)
|
|
32
32
|
};
|
|
33
33
|
}
|
|
34
|
+
/** {@link aiRatesAtList} for a model whose cache read is not a tenth of its input price. */ export function aiRatesAtListWithCacheRead(inputPerMTok, outputPerMTok, cacheReadPerMTok) {
|
|
35
|
+
const rates = _extends({}, aiRatesPerMTok(inputPerMTok, outputPerMTok), {
|
|
36
|
+
cacheReadPerToken: cacheReadPerMTok / 1000000
|
|
37
|
+
});
|
|
38
|
+
return {
|
|
39
|
+
providerRates: rates,
|
|
40
|
+
billedRates: _extends({}, rates)
|
|
41
|
+
};
|
|
42
|
+
}
|
|
34
43
|
/**
|
|
35
44
|
* The sentinels a docs-only answer is metered under (AGL-2486): not
|
|
36
45
|
* models, but ids the meter sees, priced at zero so a deflected turn lands
|
|
@@ -63,7 +72,7 @@ const OPENAI_COMPATIBLE = 'openai-compatible';
|
|
|
63
72
|
* wording the Subprocessors row and Privacy Policy section 2 were
|
|
64
73
|
* republished with on October 5, 2026 (legal v10), before
|
|
65
74
|
* `release_crm_assist_whole_record` may be turned on. The catalog row below
|
|
66
|
-
* carries it
|
|
75
|
+
* carries it in `dataReceived`.
|
|
67
76
|
*/ export const ANTHROPIC_CRM_ASSISTANCE_WHOLE_RECORD = {
|
|
68
77
|
record: 'For CRM assistance, the opened record as the CRM shows it, with all of its standard and custom fields, including contact details, notes, timeline and related records.',
|
|
69
78
|
never: 'No account identifiers or authentication tokens, and no email address outside an opened CRM record.'
|
|
@@ -83,8 +92,8 @@ const OPENAI_COMPATIBLE = 'openai-compatible';
|
|
|
83
92
|
subprocessor: {
|
|
84
93
|
entity: 'Anthropic, PBC',
|
|
85
94
|
region: 'United States',
|
|
86
|
-
purpose: "AI
|
|
87
|
-
publishedOn: '2026-10-
|
|
95
|
+
purpose: "AI features of the Services, including the Aglyn Assist helper: creating, editing and reviewing content, drafts and settings for a customer’s site, store and CRM, and explaining and summarizing the customer’s own setup and data",
|
|
96
|
+
publishedOn: '2026-10-07',
|
|
88
97
|
reason: "Reached through the AI plugin's Anthropic adapter (`libs/plugins/ai/src/lib/providers/anthropic.ts`) by the doors that call the AI runtime. `libs/plugins/ai/src/lib/server/assist-chat.ts` is gated by `release_assist` AND the key, and a generation job's text step by `release_ai_generative`; `libs/plugins/ai/src/lib/server/ai-assist.ts` carries NO release flag, so setting `{apiKeyEnv}` in production is by itself what starts this flow. `assist-anthropic-subprocessor-gate.spec.ts` holds the per-door detail and is the deeper guard for this one vendor.",
|
|
89
98
|
dataReceived: anthropicDataReceived(ANTHROPIC_CRM_ASSISTANCE_WHOLE_RECORD)
|
|
90
99
|
}
|
|
@@ -108,12 +117,17 @@ const OPENAI_COMPATIBLE = 'openai-compatible';
|
|
|
108
117
|
};
|
|
109
118
|
export const AI_MODEL_CATALOG = [
|
|
110
119
|
{
|
|
111
|
-
|
|
120
|
+
// THE BALANCED TIER'S DEFAULT (AGL-3660): the first balanced row is what
|
|
121
|
+
// `aiDefaultModelFor` answers, so Free, "Auto" and every step routed to
|
|
122
|
+
// balanced run here. Rejects `thinking: {type: "disabled"}` and forced
|
|
123
|
+
// tool choice: the adapter sends thinking off as `between_tools` and
|
|
124
|
+
// every tool call with `tool_choice: auto`.
|
|
125
|
+
id: 'claude-sonnet-5-5',
|
|
112
126
|
provider: ANTHROPIC,
|
|
113
|
-
label: 'Claude Sonnet 5',
|
|
127
|
+
label: 'Claude Sonnet 5.5',
|
|
114
128
|
capabilities: anthropicCapabilities,
|
|
115
129
|
/*
|
|
116
|
-
* THE
|
|
130
|
+
* THE ROWS BILLED ABOVE THEIR PROVIDER RATE (AGL-3015).
|
|
117
131
|
*
|
|
118
132
|
* The balanced tier prices most requests, so this markup is most of the
|
|
119
133
|
* platform's AI margin. It is carried in the rate and not in the credit
|
|
@@ -124,8 +138,25 @@ export const AI_MODEL_CATALOG = [
|
|
|
124
138
|
*
|
|
125
139
|
* Everything that reasons about what we PAY — the margin surfaces, the
|
|
126
140
|
* staff spend meters, the discount guardrail's cost of goods — reads
|
|
127
|
-
* `providerRates`, which is the vendor's published list.
|
|
128
|
-
|
|
141
|
+
* `providerRates`, which is the vendor's published list. Sonnet 5.5's
|
|
142
|
+
* list is Sonnet 5's, except a cache read: $0.10/MTok, a twentieth of
|
|
143
|
+
* input. A customer is billed exactly what Sonnet 5 billed, so the
|
|
144
|
+
* balanced tier's prices do not move when its default does.
|
|
145
|
+
*/ providerRates: _extends({}, aiRatesPerMTok(2, 10), {
|
|
146
|
+
cacheReadPerToken: 0.1 / 1000000
|
|
147
|
+
}),
|
|
148
|
+
billedRates: aiRatesPerMTok(3, 15),
|
|
149
|
+
tier: 'balanced',
|
|
150
|
+
cacheMinTokens: 512
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
// The balanced default until AGL-3660, kept so a workspace that chose it
|
|
154
|
+
// and every recording that names it still resolve, at the same rates.
|
|
155
|
+
id: 'claude-sonnet-5',
|
|
156
|
+
provider: ANTHROPIC,
|
|
157
|
+
label: 'Claude Sonnet 5',
|
|
158
|
+
capabilities: anthropicCapabilities,
|
|
159
|
+
providerRates: aiRatesPerMTok(2, 10),
|
|
129
160
|
billedRates: aiRatesPerMTok(3, 15),
|
|
130
161
|
tier: 'balanced',
|
|
131
162
|
cacheMinTokens: 1024
|
|
@@ -163,6 +194,20 @@ export const AI_MODEL_CATALOG = [
|
|
|
163
194
|
tier: 'deep',
|
|
164
195
|
cacheMinTokens: 512
|
|
165
196
|
}),
|
|
197
|
+
_extends({
|
|
198
|
+
// Listed for a side-by-side comparison (AGL-3660); the deep tier's
|
|
199
|
+
// default stays claude-opus-5 above. Thinking cannot be disabled and its
|
|
200
|
+
// effort defaults to medium, so the adapter omits thinking where a step
|
|
201
|
+
// asks for it off and names effort high where a step names none — Opus
|
|
202
|
+
// 5's own default. Forced tool choice is refused; the adapter sends auto.
|
|
203
|
+
id: 'claude-opus-5-5',
|
|
204
|
+
provider: ANTHROPIC,
|
|
205
|
+
label: 'Claude Opus 5.5',
|
|
206
|
+
capabilities: anthropicCapabilities
|
|
207
|
+
}, aiRatesAtListWithCacheRead(4, 20, 0.2), {
|
|
208
|
+
tier: 'deep',
|
|
209
|
+
cacheMinTokens: 512
|
|
210
|
+
}),
|
|
166
211
|
_extends({
|
|
167
212
|
id: 'claude-opus-4-8',
|
|
168
213
|
provider: ANTHROPIC,
|
|
@@ -227,8 +272,49 @@ export const AI_MODEL_CATALOG = [
|
|
|
227
272
|
billedRates: aiRatesPerMTok(inputPerMTok * AI_IMAGE_BILLED_MARKUP, outputPerMTok * AI_IMAGE_BILLED_MARKUP)
|
|
228
273
|
};
|
|
229
274
|
}
|
|
275
|
+
/**
|
|
276
|
+
* The image-output tokens Google writes a picture as, by size (AGL-3602),
|
|
277
|
+
* read from the usage of real Gemini 3.1 Flash Image answers on 2026-10-07:
|
|
278
|
+
* 747 at 512 px and 1,120 at 1K. A row's per-picture figures are the 1K
|
|
279
|
+
* picture's; a 512 px picture is priced at its share of them.
|
|
280
|
+
*/ export const AI_IMAGE_SIZE_OUTPUT_TOKENS = {
|
|
281
|
+
'512': 747,
|
|
282
|
+
'1K': 1120
|
|
283
|
+
};
|
|
284
|
+
/** A 1K per-picture figure at `size`, by the size's share of image tokens. */ function atImageSize(usdAt1K, size) {
|
|
285
|
+
var _AI_IMAGE_SIZE_OUTPUT_TOKENS_;
|
|
286
|
+
const tokens = (_AI_IMAGE_SIZE_OUTPUT_TOKENS_ = AI_IMAGE_SIZE_OUTPUT_TOKENS[size != null ? size : '1K']) != null ? _AI_IMAGE_SIZE_OUTPUT_TOKENS_ : AI_IMAGE_SIZE_OUTPUT_TOKENS['1K'];
|
|
287
|
+
return roundUsd(usdAt1K * tokens / AI_IMAGE_SIZE_OUTPUT_TOKENS['1K']);
|
|
288
|
+
}
|
|
230
289
|
/** The image model a photo is made with when the operator names none. */ export const AI_IMAGE_DEFAULT_MODEL = 'gemini-3.1-flash-image';
|
|
231
290
|
/** The image provider's id: Google's models on Vertex AI. */ export const AI_IMAGE_VERTEX_PROVIDER_ID = 'google-vertex';
|
|
291
|
+
/**
|
|
292
|
+
* The image providers' rows on the published subprocessor list, kept apart
|
|
293
|
+
* from `AI_CATALOG_PROVIDERS` for the reason the image catalog is kept apart
|
|
294
|
+
* from the text one: a settings form offers text providers from that list,
|
|
295
|
+
* and an image provider answers no conversation. The host is the adapter's
|
|
296
|
+
* published endpoint (`VERTEX_IMAGE_PUBLISHED_HOST`).
|
|
297
|
+
*
|
|
298
|
+
* Google's row is dated to its change-log entry on `/legal/subprocessors`,
|
|
299
|
+
* published with the Privacy Policy §2 sentence naming Google for image
|
|
300
|
+
* generation (legal v12).
|
|
301
|
+
*/ export const AI_IMAGE_CATALOG_PROVIDERS = [
|
|
302
|
+
{
|
|
303
|
+
id: AI_IMAGE_VERTEX_PROVIDER_ID,
|
|
304
|
+
label: 'Google Vertex AI',
|
|
305
|
+
subprocessor: {
|
|
306
|
+
entity: 'Google LLC (Google Cloud Vertex AI)',
|
|
307
|
+
// The global endpoint, which Google documents as routing and
|
|
308
|
+
// processing a request anywhere in the world, with no data residency
|
|
309
|
+
// guarantee: Google, not Aglyn, chooses the location.
|
|
310
|
+
region: 'Global — Google selects where requests are processed',
|
|
311
|
+
purpose: "AI image generation: creating images for a customer's media library from a description a user writes",
|
|
312
|
+
publishedOn: '2026-10-08',
|
|
313
|
+
reason: "Reached through the AI plugin's Vertex AI image adapter (`libs/plugins/ai/src/lib/providers/vertex-image.ts`) by the Media library's Create with AI door (`libs/plugins/ai/src/lib/server/ai-media-image.ts`) for every kind that is not drawn as SVG, as the platform's own service account. Off unless `AI_IMAGE_VERTEX_PROJECT` names a Google Cloud project; the console offers those kinds only where `NEXT_PUBLIC_AI_IMAGE_PHOTOS` is `on`. The request carries the description and the kind's fixed style wording, the shape and fixed settings, and nothing else.",
|
|
314
|
+
dataReceived: "The description the user writes and the shape requested, and the generated image returned. No account identifiers, email addresses, or other content of the customer's site."
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
];
|
|
232
318
|
export const AI_IMAGE_MODEL_CATALOG = [
|
|
233
319
|
_extends({
|
|
234
320
|
// The default: Google's own replacement for Imagen 4, which Vertex AI
|
|
@@ -259,13 +345,13 @@ export const AI_IMAGE_MODEL_CATALOG = [
|
|
|
259
345
|
/** The image catalog row for a model id, or `undefined` for an unknown id. */ export function aiImageCatalogEntry(modelId) {
|
|
260
346
|
return AI_IMAGE_MODEL_CATALOG.find((entry)=>entry.id === modelId);
|
|
261
347
|
}
|
|
262
|
-
/** What the provider charges us for one picture from `modelId
|
|
348
|
+
/** What the provider charges us for one picture from `modelId`, at `size` (1K when absent). */ export function aiImageProviderUsdPerImage(modelId, size) {
|
|
263
349
|
var _aiImageCatalogEntry;
|
|
264
|
-
return ((_aiImageCatalogEntry = aiImageCatalogEntry(modelId)) != null ? _aiImageCatalogEntry : AI_IMAGE_FALLBACK_RATES).providerUsdPerImage;
|
|
350
|
+
return atImageSize(((_aiImageCatalogEntry = aiImageCatalogEntry(modelId)) != null ? _aiImageCatalogEntry : AI_IMAGE_FALLBACK_RATES).providerUsdPerImage, size);
|
|
265
351
|
}
|
|
266
|
-
/** What one picture from `modelId` draws from a customer's credits. */ export function aiImageBilledUsdPerImage(modelId) {
|
|
352
|
+
/** What one picture from `modelId` at `size` (1K when absent) draws from a customer's credits. */ export function aiImageBilledUsdPerImage(modelId, size) {
|
|
267
353
|
var _aiImageCatalogEntry;
|
|
268
|
-
return ((_aiImageCatalogEntry = aiImageCatalogEntry(modelId)) != null ? _aiImageCatalogEntry : AI_IMAGE_FALLBACK_RATES).billedUsdPerImage;
|
|
354
|
+
return atImageSize(((_aiImageCatalogEntry = aiImageCatalogEntry(modelId)) != null ? _aiImageCatalogEntry : AI_IMAGE_FALLBACK_RATES).billedUsdPerImage, size);
|
|
269
355
|
}
|
|
270
356
|
/** Pictures on a usage record: whole, finite, non-negative, else 0. */ function aiImageCount(usage) {
|
|
271
357
|
var _usage_images;
|
|
@@ -328,14 +414,14 @@ function priceUsage(usage, rate) {
|
|
|
328
414
|
* What one exchange COST US, at the serving model's provider rates, rounded
|
|
329
415
|
* to 6dp. Real money, and the only figure a margin may be taken against.
|
|
330
416
|
*/ export function estimateAiProviderCostUsd(usage, modelId) {
|
|
331
|
-
return roundUsd(priceUsage(usage, aiProviderRatesForModel(modelId)) + aiImageCount(usage) * aiImageProviderUsdPerImage(modelId));
|
|
417
|
+
return roundUsd(priceUsage(usage, aiProviderRatesForModel(modelId)) + aiImageCount(usage) * aiImageProviderUsdPerImage(modelId, usage.imageSize));
|
|
332
418
|
}
|
|
333
419
|
/**
|
|
334
420
|
* What one exchange DRAWS FROM A CUSTOMER, at the serving model's billed
|
|
335
421
|
* rates, rounded to 6dp — the figure `assistCreditsFromUsd` turns into
|
|
336
422
|
* credits. At or above `estimateAiProviderCostUsd` for the same exchange.
|
|
337
423
|
*/ export function estimateAiBilledUsd(usage, modelId) {
|
|
338
|
-
return roundUsd(priceUsage(usage, aiBilledRatesForModel(modelId)) + aiImageCount(usage) * aiImageBilledUsdPerImage(modelId));
|
|
424
|
+
return roundUsd(priceUsage(usage, aiBilledRatesForModel(modelId)) + aiImageCount(usage) * aiImageBilledUsdPerImage(modelId, usage.imageSize));
|
|
339
425
|
}
|
|
340
426
|
/** Every catalog id a provider serves. */ export function aiModelIdsForProvider(providerId) {
|
|
341
427
|
return AI_MODEL_CATALOG.filter((entry)=>entry.provider === providerId).map((entry)=>entry.id);
|
|
@@ -354,6 +440,12 @@ function priceUsage(usage, rate) {
|
|
|
354
440
|
// Short answers through a strict tool, held to the facts the CRM reports
|
|
355
441
|
// about the record the member opened.
|
|
356
442
|
'job.crm': 'fast',
|
|
443
|
+
// A change to a page or a layout the site has (AGL-3616): the Assist edit
|
|
444
|
+
// rung's protocol run as a job, held to the closed world of the document's
|
|
445
|
+
// own element ids and to the palette validators. Finding the element a
|
|
446
|
+
// request means, and changing only it, is the judgment; the chat door that
|
|
447
|
+
// proposes the same edits runs on this tier.
|
|
448
|
+
'job.edit': 'balanced',
|
|
357
449
|
// A/B tests by AI (AGL-2914): variants of one piece of copy, and a
|
|
358
450
|
// result put into words for a verdict code already reached. Short answers
|
|
359
451
|
// through a strict tool, but the judgment a variant sells — which ONE idea
|