@aglyn/plugins-ai 1.0.0-beta.250 → 1.0.0-beta.253
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/components/ai-brief-dialog.component.js +15 -1
- package/src/lib/components/ai-brief-dialog.component.js.map +1 -1
- package/src/lib/components/ai-job-links.js +1 -1
- package/src/lib/components/ai-job-links.js.map +1 -1
- package/src/lib/components/ai-job-plan.component.js +20 -2
- package/src/lib/components/ai-job-plan.component.js.map +1 -1
- package/src/lib/components/ai-jobs-store.d.ts +11 -0
- package/src/lib/components/ai-jobs-store.js +22 -0
- package/src/lib/components/ai-jobs-store.js.map +1 -1
- package/src/lib/jobs/ai-job-crm-step.js +7 -4
- package/src/lib/jobs/ai-job-crm-step.js.map +1 -1
- package/src/lib/jobs/ai-job-drafts.d.ts +24 -0
- package/src/lib/jobs/ai-job-drafts.js +46 -0
- package/src/lib/jobs/ai-job-drafts.js.map +1 -1
- package/src/lib/jobs/ai-job-experiment-step.js +6 -1
- package/src/lib/jobs/ai-job-experiment-step.js.map +1 -1
- package/src/lib/jobs/ai-job-form-dataset.d.ts +6 -1
- package/src/lib/jobs/ai-job-form-dataset.js +7 -2
- package/src/lib/jobs/ai-job-form-dataset.js.map +1 -1
- package/src/lib/jobs/ai-job-form-reuse.d.ts +78 -0
- package/src/lib/jobs/ai-job-form-reuse.js +136 -0
- package/src/lib/jobs/ai-job-form-reuse.js.map +1 -0
- package/src/lib/jobs/ai-job-form-step.d.ts +17 -0
- package/src/lib/jobs/ai-job-form-step.js +63 -11
- package/src/lib/jobs/ai-job-form-step.js.map +1 -1
- package/src/lib/jobs/ai-job-insight-step.js +6 -1
- package/src/lib/jobs/ai-job-insight-step.js.map +1 -1
- package/src/lib/jobs/ai-job-page-language.d.ts +10 -5
- package/src/lib/jobs/ai-job-page-language.js +10 -5
- package/src/lib/jobs/ai-job-page-language.js.map +1 -1
- package/src/lib/jobs/ai-job-plan-step.d.ts +32 -1
- package/src/lib/jobs/ai-job-plan-step.js +53 -2
- package/src/lib/jobs/ai-job-plan-step.js.map +1 -1
- package/src/lib/jobs/ai-job-seo-step.js +5 -3
- package/src/lib/jobs/ai-job-seo-step.js.map +1 -1
- package/src/lib/jobs/ai-job-site-content.d.ts +7 -5
- package/src/lib/jobs/ai-job-site-content.js +7 -5
- package/src/lib/jobs/ai-job-site-content.js.map +1 -1
- package/src/lib/jobs/ai-job-site-datasets.d.ts +1 -1
- package/src/lib/jobs/ai-job-site-datasets.js +2 -2
- package/src/lib/jobs/ai-job-site-datasets.js.map +1 -1
- package/src/lib/jobs/ai-job-site-step.js +2 -1
- package/src/lib/jobs/ai-job-site-step.js.map +1 -1
- package/src/lib/jobs/ai-job-text-step.js +6 -3
- package/src/lib/jobs/ai-job-text-step.js.map +1 -1
- package/src/lib/jobs/ai-layout-stock-photos.d.ts +11 -7
- package/src/lib/jobs/ai-layout-stock-photos.js +25 -10
- package/src/lib/jobs/ai-layout-stock-photos.js.map +1 -1
- package/src/lib/jobs/ai-stock-business-nouns.d.ts +62 -0
- package/src/lib/jobs/ai-stock-business-nouns.js +264 -0
- package/src/lib/jobs/ai-stock-business-nouns.js.map +1 -0
- package/src/lib/layout-language/ai-layout-language.js +5 -1
- package/src/lib/layout-language/ai-layout-language.js.map +1 -1
- package/src/lib/layout-language/ai-layout-links.js +5 -2
- package/src/lib/layout-language/ai-layout-links.js.map +1 -1
- package/src/lib/model/ai-build-plan.d.ts +7 -3
- package/src/lib/model/ai-build-plan.js +11 -1
- package/src/lib/model/ai-build-plan.js.map +1 -1
- package/src/lib/model/ai-credit-estimate.d.ts +39 -19
- package/src/lib/model/ai-credit-estimate.js +43 -19
- package/src/lib/model/ai-credit-estimate.js.map +1 -1
- package/src/lib/model/ai-job-activity.d.ts +30 -0
- package/src/lib/model/ai-job-activity.js +35 -0
- package/src/lib/model/ai-job-activity.js.map +1 -1
- package/src/lib/model/ai-media-credits.d.ts +5 -3
- package/src/lib/model/ai-media-credits.js +7 -5
- package/src/lib/model/ai-media-credits.js.map +1 -1
- package/src/lib/model/ai-site-job.js +6 -3
- package/src/lib/model/ai-site-job.js.map +1 -1
- package/src/lib/model/ai-site-start-seo.d.ts +11 -2
- package/src/lib/model/ai-site-start-seo.js +29 -15
- package/src/lib/model/ai-site-start-seo.js.map +1 -1
- package/src/lib/model/ai-site-store-pages.d.ts +5 -0
- package/src/lib/model/ai-site-store-pages.js +2 -0
- package/src/lib/model/ai-site-store-pages.js.map +1 -1
- package/src/lib/plugin-config.js +2 -2
- package/src/lib/plugin-config.js.map +1 -1
- package/src/lib/providers/anthropic-crm-wording-superseded.d.ts +29 -0
- package/src/lib/providers/anthropic-crm-wording-superseded.js +31 -0
- package/src/lib/providers/anthropic-crm-wording-superseded.js.map +1 -0
- package/src/lib/providers/anthropic.js +29 -7
- package/src/lib/providers/anthropic.js.map +1 -1
- package/src/lib/providers/catalog.d.ts +24 -17
- package/src/lib/providers/catalog.js +63 -30
- package/src/lib/providers/catalog.js.map +1 -1
- package/src/lib/providers/contract.d.ts +19 -1
- package/src/lib/providers/contract.js +10 -0
- package/src/lib/providers/contract.js.map +1 -1
- package/src/lib/providers/model-choice.d.ts +1 -1
- package/src/lib/providers/model-choice.js +39 -30
- package/src/lib/providers/model-choice.js.map +1 -1
- package/src/lib/providers/routing.d.ts +20 -1
- package/src/lib/providers/routing.js +71 -12
- package/src/lib/providers/routing.js.map +1 -1
- package/src/lib/runtime/ai-dev-env.d.ts +58 -1
- package/src/lib/runtime/ai-dev-env.js +86 -6
- package/src/lib/runtime/ai-dev-env.js.map +1 -1
- package/src/lib/runtime/ai-dev-replay.d.ts +4 -0
- package/src/lib/runtime/ai-dev-replay.js +4 -0
- package/src/lib/runtime/ai-dev-replay.js.map +1 -1
- package/src/lib/runtime/ai-doctrine-validators.js +13 -3
- package/src/lib/runtime/ai-doctrine-validators.js.map +1 -1
- package/src/lib/runtime/ai-doctrine.js +8 -4
- package/src/lib/runtime/ai-doctrine.js.map +1 -1
- package/src/lib/runtime/ai-eval-live.d.ts +43 -1
- package/src/lib/runtime/ai-eval-live.js +79 -9
- package/src/lib/runtime/ai-eval-live.js.map +1 -1
- package/src/lib/runtime/ai-live-batch.d.ts +20 -4
- package/src/lib/runtime/ai-live-batch.js +57 -10
- package/src/lib/runtime/ai-live-batch.js.map +1 -1
- package/src/lib/runtime/ai-palette.generated.js +4 -0
- package/src/lib/runtime/ai-palette.generated.js.map +1 -1
- package/src/lib/runtime/ai-runtime.js +21 -4
- package/src/lib/runtime/ai-runtime.js.map +1 -1
- package/src/lib/runtime/seo-fields.js +4 -3
- package/src/lib/runtime/seo-fields.js.map +1 -1
- package/src/lib/server/ai-assist.js +3 -2
- package/src/lib/server/ai-assist.js.map +1 -1
- package/src/lib/server/ai-media-image.d.ts +5 -1
- package/src/lib/server/ai-media-image.js +6 -2
- package/src/lib/server/ai-media-image.js.map +1 -1
- package/src/lib/server/ai-media-svg.js +4 -0
- package/src/lib/server/ai-media-svg.js.map +1 -1
- package/src/lib/usage/ai-allotment-alerts.js +2 -5
- package/src/lib/usage/ai-allotment-alerts.js.map +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/model/ai-site-store-pages.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * A STORE'S OWN PAGES (AGL-3676, third round).\n *\n * Zach, 2026-10-10: \"We seem to be missing the account pages for the\n * shop/store AI generation, make sure all they would have to do is setup the\n * payment info and update products to finish up their storefront.\" The\n * Ember & Oak Candle Co start had Home, Shop, Gift sets, About, Shipping &\n * care and Contact, and a product page per product; a shopper had nowhere to\n * sign in, see an order, find what they saved, or read the store's privacy\n * policy and terms.\n *\n * So a paid store start gets the pages every storefront has, written by code\n * from the platform's own elements — never asked of the model:\n *\n * - ACCOUNT at /account: the commerce plugin's Customer account (sign in,\n * create an account, profile, addresses, order history with status and\n * tracking, sign out) and Saved items (the Wishlist the product page's\n * Save fills, kept for a guest in the browser and on the account once\n * they sign in);\n * - CART at /cart: the Cart in full, with its checkout, for a shopper who\n * goes to the address rather than the header's cart drawer;\n * - SHIPPING & RETURNS at /shipping-returns, PRIVACY POLICY at /privacy and\n * TERMS OF SALE at /terms: editable drafts in the Markdown element, every\n * fact only the merchant knows left as a [bracketed placeholder] — never a\n * return window, a price or a promise the brief did not give.\n *\n * The account and the cart are a shopper's own pages, written UNLISTED\n * (noindex, out of the sitemap); the policies are indexable like every other\n * page.\n *\n * An order's own page is the commerce plugin's built-in /order-status, which\n * every order email links with its signed key; the Account page says so.\n *\n * ── Outside the plan's page count ───────────────────────────────────────\n *\n * They are STORE PAGES, not planned pages: the plan's four to eight pages are\n * the content the model designs, and these are added beside them, so they\n * never crowd one out. They still count toward the plan's pages allowance\n * (`screensPerHost`), as every page a site has does; a store is Starter and\n * up, whose allowance holds both.\n *\n * A page the plan already has stands for its store page instead of a second\n * one: a planned \"Shipping & care\" is the store's shipping page, and a page\n * the plan put at /privacy is its privacy policy. The header and footer link\n * that page.\n *\n * Pure: names, paths, words and node trees. Safe for the console to import.\n */\n\n/** A store page, by what it is. Persisted in job outputs (`proposal.storePage`); never renamed. */\nexport type AiStorePageKey = 'account' | 'cart' | 'shipping' | 'privacy' | 'terms'\n\nexport interface AiStorePageDefinition {\n key: AiStorePageKey\n /** The page's name in Pages, and its heading. */\n title: string\n slug: string\n /** What the footer's link to it says. */\n link: string\n seo: { title: string; description: string }\n /**\n * A shopper's own page, not one to find by search: written UNLISTED, the\n * page's Access setting the console offers, so the tenant serves it\n * `noindex` and leaves it out of the sitemap. Only the account and the\n * cart; the policies, like every content and landing page, stay indexable.\n */\n noindex?: true\n}\n\n/** Every store page, in the order the job writes them and the footer links them. */\nexport const AI_STORE_PAGES: readonly AiStorePageDefinition[] = [\n {\n key: 'account',\n title: 'Your account',\n slug: 'account',\n link: 'Your account',\n noindex: true,\n seo: { title: 'Your account', description: 'Sign in to see your orders, saved addresses and saved items.' },\n },\n {\n key: 'cart',\n title: 'Your cart',\n slug: 'cart',\n link: 'Cart',\n noindex: true,\n seo: { title: 'Your cart', description: 'Review your cart and check out.' },\n },\n {\n key: 'shipping',\n title: 'Shipping & returns',\n slug: 'shipping-returns',\n link: 'Shipping & returns',\n seo: { title: 'Shipping & returns', description: 'How we ship your order, and how returns and refunds work.' },\n },\n {\n key: 'privacy',\n title: 'Privacy policy',\n slug: 'privacy',\n link: 'Privacy policy',\n seo: { title: 'Privacy policy', description: 'What we collect when you shop with us, and what we do with it.' },\n },\n {\n key: 'terms',\n title: 'Terms of sale',\n slug: 'terms',\n link: 'Terms of sale',\n seo: { title: 'Terms of sale', description: 'The terms that apply when you buy from our store.' },\n },\n]\n\n/** What the job's row for the store pages reads. */\nexport const AI_SITE_STORE_PAGES_LABEL = 'Adding your account, cart and policy pages'\n\n/** The note the row carries once they are written: what the merchant fills in. */\nexport const AI_SITE_STORE_PAGES_NOTE =\n 'Your shipping, privacy and terms pages are drafts: fill in the parts in [brackets] with your store’s own details.'\n\n/** A planned page whose words say it is the store's shipping page: \"Shipping & care\", \"Delivery & returns\". */\nconst SHIPPING_WORDS = /\\b(shipping|delivery|returns?|refunds?)\\b/i\n\n/** The words of a planned page's address and title, spaced. */\nconst wordsOf = (screen: { slug: string; title: string }) => `${screen.slug.replace(/[-/_]+/g, ' ')} ${screen.title}`\n\nconst firstSegment = (slug: string) => slug.trim().replace(/^\\/+/, '').split('/')[0].toLowerCase()\n\n/** A store page as a start builds or links it. */\nexport interface AiStorePagePlan {\n key: AiStorePageKey\n title: string\n slug: string\n /** Where the header and footer link it. */\n href: string\n /** What the footer's link says. */\n link: string\n /**\n * The planned page that stands for it, by its title, where the plan has\n * one: nothing is written for this key, and its links go to that page.\n */\n planned?: string\n}\n\n/**\n * The store pages a store plan gets: each one written, or — where a planned\n * page already holds its address, or a planned page's words say it is the\n * store's shipping page — that planned page, linked in its place.\n */\nexport function aiStorePagesOfPlan(screens: ReadonlyArray<{ slug: string; title: string; record?: unknown }>): AiStorePagePlan[] {\n const pages = screens.filter((screen) => !screen.record && firstSegment(screen.slug) !== '')\n return AI_STORE_PAGES.map((page) => {\n const holds =\n pages.find((screen) => firstSegment(screen.slug) === page.slug) ??\n (page.key === 'shipping' ? pages.find((screen) => SHIPPING_WORDS.test(wordsOf(screen))) : undefined)\n if (holds) {\n const slug = firstSegment(holds.slug)\n return { key: page.key, title: page.title, slug, href: `/${slug}`, link: holds.title.trim() || page.link, planned: holds.title }\n }\n return { key: page.key, title: page.title, slug: page.slug, href: `/${page.slug}`, link: page.link }\n })\n}\n\n/** The store pages a start writes itself: those no planned page stands for. */\nexport function aiStorePagesToWrite(pages: readonly AiStorePagePlan[]): AiStorePagePlan[] {\n return pages.filter((page) => !page.planned)\n}\n\n/** The unit input a site layout is told the store's links under. */\nexport const AI_SITE_STORE_LINKS_INPUT = 'storeLinks'\n\n/** What a store's header and footer link (AGL-3676): the account beside the cart, and the store's pages under the site's. */\nexport interface AiStoreFrameLinks {\n /** The account page's path, which the header links beside the cart. */\n account: string | null\n /** The footer's store links, in order: the account, then the policies. */\n footer: Array<{ label: string; href: string }>\n}\n\n/** The header's and footer's store links for these store pages. The cart is the header's own button. */\nexport function aiStoreFrameLinks(pages: readonly AiStorePagePlan[]): AiStoreFrameLinks {\n const account = pages.find((page) => page.key === 'account')\n return {\n account: account?.href ?? null,\n footer: pages.filter((page) => page.key !== 'cart').map((page) => ({ label: page.link, href: page.href })),\n }\n}\n\nconst PATH = /^\\/[a-z0-9-]+$/\n\n/** The store links a layout unit's inputs carry; none for any other layout. */\nexport function aiStoreFrameLinksOf(inputs: Readonly<Record<string, unknown>> | null | undefined): AiStoreFrameLinks | null {\n const raw = inputs?.[AI_SITE_STORE_LINKS_INPUT]\n if (!raw || typeof raw !== 'object') return null\n const { account, footer } = raw as Record<string, unknown>\n const links = Array.isArray(footer)\n ? footer.flatMap((entry) => {\n const { label, href } = (entry ?? {}) as Record<string, unknown>\n return typeof label === 'string' && label.trim() && typeof href === 'string' && PATH.test(href)\n ? [{ label: label.trim().slice(0, 40), href }]\n : []\n })\n : []\n const accountPath = typeof account === 'string' && PATH.test(account) ? account : null\n return accountPath || links.length ? { account: accountPath, footer: links.slice(0, 6) } : null\n}\n\n// ── The pages, as node trees ──────────────────────────────────────────────\n\n/** The canvas root every stored page hangs from (`CANVAS_ROOT_ELEMENT_ID`). */\nconst ROOT = '_@_'\n\n/** The longest one Markdown element is given: the element's own text limit. */\nexport const AI_STORE_MARKDOWN_MAX = 2000\n\n/** The commerce plugin's elements a store page places, by the ids it persists (`ai-site-store-pages.spec.ts` holds them). */\nexport const AI_STORE_ELEMENTS = {\n account: 'customer-account',\n wishlist: 'wishlist',\n cart: 'cart',\n} as const\n\n/** The host token that reads the site's own name at render (`AI_SITE_NAME_TOKEN`). */\nconst NAME = '{{host.businessName}}'\n\n/** What a store page's words may link: the site's contact page and its shop, where the plan has them. */\nexport interface AiStorePageFacts {\n /** The contact page's path, or `null` where the plan has none. */\n contactPath: string | null\n /** The shop's path, `/shop` where the plan has none. */\n shopPath: string\n /** The shipping page's path, as the terms link it. */\n shippingPath: string\n}\n\ninterface StoredNode {\n $id: string\n type: 'node'\n componentId: string\n pluginId: string\n parentId: string | null\n nodes: string[]\n props?: Record<string, unknown>\n sx?: Record<string, unknown>\n}\n\n/** How a sentence asks a shopper to get in touch: the contact page, else a reply to their order email. */\nfunction contact(facts: AiStorePageFacts, words = 'contact us'): string {\n return facts.contactPath ? `[${words}](${facts.contactPath})` : `${words} by replying to your order email`\n}\n\n/** The policy's sections, as markdown, each a `##` heading and its paragraphs. */\nexport function aiStorePolicySections(key: 'shipping' | 'privacy' | 'terms', facts: AiStorePageFacts): string[] {\n if (key === 'shipping') {\n return [\n '## Shipping\\n\\nWe ship orders from [where you ship from]. Orders are packed within [number] business days, and you will get an email with tracking as soon as yours is on its way.\\n\\nShipping costs and delivery options are shown at checkout before you pay. [List the countries or regions you ship to, and any free-shipping offer you make.]',\n `## Returns\\n\\nYou can return an item within [number] days of delivery if it is [unused and in its original packaging]. [Name anything that cannot be returned, such as gift cards or personalized items.]\\n\\nTo start a return, open the link in your order email and choose Request a return, or ${contact(facts)}. [Say who pays for return shipping.]`,\n '## Refunds\\n\\nOnce we receive and check your return, we refund it to your original payment method within [number] business days. [Say whether the original shipping cost is refunded.]',\n `## Damaged or wrong items\\n\\nIf your order arrives damaged or is not what you ordered, ${contact(facts)} within [number] days of delivery with your order number and a photo, and we will put it right.`,\n ]\n }\n if (key === 'privacy') {\n return [\n `## Who we are\\n\\n${NAME} runs this online store. This policy explains what we collect when you visit, shop or create an account, and what we do with it. [Add your business’s legal name and postal address.]`,\n '## What we collect\\n\\n- **When you order:** your name, email address, shipping and billing address, your phone number if you give one, and what you bought.\\n- **When you create an account:** your name, email address, saved addresses, order history and saved items.\\n- **When you sign up for emails:** your email address and your choice to hear from us.\\n- **Payments:** card payments are processed by Stripe. We never see or store your full card number.',\n '## How we use it\\n\\nWe use your information to process and deliver your orders, to send order and shipping emails, to answer your questions, and, only if you opt in, to send you news and offers. You can unsubscribe from marketing emails at any time with the link in each one.',\n '## Who we share it with\\n\\nWe share only what is needed with the services that run the store: our website and store platform, our payment processor (Stripe), and the carriers that deliver your order. [List any other services you use, such as an email or analytics tool.] We do not sell your personal information.',\n '## Cookies\\n\\nThis site uses cookies to keep your cart and your sign-in working. [Describe any analytics or advertising cookies you use, and how visitors choose.]',\n `## Your choices\\n\\nYou can ask to see, correct or delete the information we hold about you: ${contact(facts)}. [Say how long you keep order records, and the privacy rights that apply where you sell.]\\n\\nWe post any change to this policy on this page. Last updated: [date].`,\n ]\n }\n return [\n `## About these terms\\n\\nThese terms apply to purchases from ${NAME} through this website. By placing an order you agree to them. [Add your business’s legal name and where it is registered.]`,\n '## Orders\\n\\nYour order is an offer to buy. We accept it when we send your order confirmation email. If an item turns out to be unavailable, we will tell you and refund what you paid for it.',\n '## Prices and payment\\n\\nPrices are shown in [currency] and [include or exclude] [sales tax or VAT]. Shipping and any taxes are shown at checkout before you pay. Payment is taken securely through Stripe when you place your order.',\n `## Shipping, returns and refunds\\n\\nHow we ship, and how returns and refunds work, is set out on our [Shipping & returns](${facts.shippingPath}) page.`,\n '## Products\\n\\nWe describe and photograph our products as accurately as we can. [Note anything that naturally varies, such as handmade pieces, colors or sizes.]',\n `## Liability\\n\\n[State any limit on your liability, as the law where you sell allows.] Nothing in these terms limits your rights under consumer law.\\n\\n## Contact\\n\\nQuestions about an order? ${contact(facts, 'Contact us')}. Last updated: [date].`,\n ]\n}\n\n/** Sections joined into as few Markdown elements as fit the element's limit, in order. */\nexport function aiStoreMarkdownChunks(sections: readonly string[], max = AI_STORE_MARKDOWN_MAX): string[] {\n const chunks: string[] = []\n for (const section of sections) {\n const last = chunks[chunks.length - 1]\n if (last !== undefined && last.length + 2 + section.length <= max) chunks[chunks.length - 1] = `${last}\\n\\n${section}`\n else chunks.push(section.slice(0, max))\n }\n return chunks\n}\n\n/**\n * A store page's node tree, root first, as a page's first version stores it:\n * the page's heading over the platform's elements, in one section the\n * site's layout renders inside.\n */\nexport function aiStorePageNodes(key: AiStorePageKey, facts: AiStorePageFacts): Record<string, StoredNode> {\n const page = AI_STORE_PAGES.find((one) => one.key === key) as AiStorePageDefinition\n const nodes: Record<string, StoredNode> = {}\n const id = (role: string) => `store-${key}-${role}`\n const container = id('container')\n const add = (role: string, componentId: string, pluginId: string, props: Record<string, unknown>, sx?: Record<string, unknown>): string => {\n const nodeId = id(role)\n nodes[nodeId] = { $id: nodeId, type: 'node', componentId, pluginId, parentId: container, nodes: [], props, ...(sx ? { sx } : {}) }\n return nodeId\n }\n const children: string[] = [add('title', 'muiTypography', 'mui', { children: page.title, variant: 'h1', component: 'h1' }, { mb: 4 })]\n if (key === 'account') {\n children.push(\n add('account', AI_STORE_ELEMENTS.account, 'commerce', { signedOutHeading: 'Sign in or create an account' }),\n add(\n 'guest',\n 'muiTypography',\n 'mui',\n { children: 'Checked out as a guest? The link in your order email opens your order’s status and tracking.', variant: 'body2', component: 'p' },\n { color: 'text.secondary', mt: 3 },\n ),\n add(\n 'saved',\n AI_STORE_ELEMENTS.wishlist,\n 'commerce',\n { heading: 'Saved items', emptyText: 'Nothing saved yet. Tap Save on any product to keep it here.' },\n { mt: 8 },\n ),\n )\n } else if (key === 'cart') {\n children.push(\n add('cart', AI_STORE_ELEMENTS.cart, 'commerce', { variant: 'inline', showCoupon: true }),\n add('shop', 'muiButton', 'mui', { children: 'Continue shopping', variant: 'outlined', href: facts.shopPath }, { mt: 4 }),\n )\n } else {\n aiStoreMarkdownChunks(aiStorePolicySections(key, facts)).forEach((content, index) => {\n children.push(add(`text${index + 1}`, 'markdown', 'mui', { content }))\n })\n }\n const section = id('section')\n nodes[ROOT] = { $id: ROOT, type: 'node', componentId: 'div', pluginId: 'mui', parentId: null, nodes: [section] }\n nodes[section] = {\n $id: section,\n type: 'node',\n componentId: 'section',\n pluginId: 'mui',\n parentId: ROOT,\n nodes: [container],\n props: { element: 'section', ariaLabel: page.title },\n }\n nodes[container] = {\n $id: container,\n type: 'node',\n componentId: 'muiContainer',\n pluginId: 'mui',\n parentId: section,\n nodes: children,\n props: { maxWidth: key === 'account' || key === 'cart' ? 'lg' : 'md' },\n sx: { py: { xs: 6, md: 10 } },\n }\n return nodes\n}\n\n// ── Finishing the store ───────────────────────────────────────────────────\n\n/** One thing left before an AI-built store sells, as its done page lists it. */\nexport interface AiStoreFinishStep {\n id: 'payments' | 'products' | 'shipping' | 'policies' | 'links'\n title: string\n text: string\n /**\n * The record route kind whose list the step opens (`plugin-record-routes`),\n * `pages` for the site's Pages, `layouts` for its Layouts, or `layout` for\n * the layout version a build drafted its store's links into (AGL-3676).\n */\n opens: 'store-settings' | 'product' | 'pages' | 'layouts' | 'layout'\n action: string\n}\n\n/**\n * What is left once an AI store is built (Zach, 2026-10-10): connect\n * payments, review the products and their prices, set shipping and tax, and\n * fill in the policies' brackets. Everything else — the storefront, the\n * account, cart and policy pages, the header's cart and account — is done.\n */\nexport const AI_STORE_FINISH_STEPS: readonly AiStoreFinishStep[] = [\n {\n id: 'payments',\n title: 'Connect payments',\n text: 'Connect Stripe so your store can take payments and pay you out.',\n opens: 'store-settings',\n action: 'Set up payments',\n },\n {\n id: 'products',\n title: 'Review your products and prices',\n text: 'Your first products are listed at suggested prices. Review your prices, photos and stock.',\n opens: 'product',\n action: 'Open products',\n },\n {\n id: 'shipping',\n title: 'Set shipping and tax',\n text: 'Choose your shipping rates and how tax is charged at checkout.',\n opens: 'store-settings',\n action: 'Open store settings',\n },\n {\n id: 'policies',\n title: 'Fill in your policies',\n text: 'Your Shipping & returns, Privacy policy and Terms of sale pages are drafts: replace the parts in [brackets].',\n opens: 'pages',\n action: 'Open pages',\n },\n]\n"],"names":["AI_STORE_PAGES","key","title","slug","link","noindex","seo","description","AI_SITE_STORE_PAGES_LABEL","AI_SITE_STORE_PAGES_NOTE","SHIPPING_WORDS","wordsOf","screen","replace","firstSegment","trim","split","toLowerCase","aiStorePagesOfPlan","screens","pages","filter","record","map","page","holds","find","test","undefined","href","planned","aiStorePagesToWrite","AI_SITE_STORE_LINKS_INPUT","aiStoreFrameLinks","account","footer","label","PATH","aiStoreFrameLinksOf","inputs","raw","links","Array","isArray","flatMap","entry","slice","accountPath","length","ROOT","AI_STORE_MARKDOWN_MAX","AI_STORE_ELEMENTS","wishlist","cart","NAME","contact","facts","words","contactPath","aiStorePolicySections","shippingPath","aiStoreMarkdownChunks","sections","max","chunks","section","last","push","aiStorePageNodes","one","nodes","id","role","container","add","componentId","pluginId","props","sx","nodeId","$id","type","parentId","children","variant","component","mb","signedOutHeading","color","mt","heading","emptyText","showCoupon","shopPath","forEach","content","index","element","ariaLabel","maxWidth","py","xs","md","AI_STORE_FINISH_STEPS","text","opens","action"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/model/ai-site-store-pages.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * A STORE'S OWN PAGES (AGL-3676, third round).\n *\n * Zach, 2026-10-10: \"We seem to be missing the account pages for the\n * shop/store AI generation, make sure all they would have to do is setup the\n * payment info and update products to finish up their storefront.\" The\n * Ember & Oak Candle Co start had Home, Shop, Gift sets, About, Shipping &\n * care and Contact, and a product page per product; a shopper had nowhere to\n * sign in, see an order, find what they saved, or read the store's privacy\n * policy and terms.\n *\n * So a paid store start gets the pages every storefront has, written by code\n * from the platform's own elements — never asked of the model:\n *\n * - ACCOUNT at /account: the commerce plugin's Customer account (sign in,\n * create an account, profile, addresses, order history with status and\n * tracking, sign out) and Saved items (the Wishlist the product page's\n * Save fills, kept for a guest in the browser and on the account once\n * they sign in);\n * - CART at /cart: the Cart in full, with its checkout, for a shopper who\n * goes to the address rather than the header's cart drawer;\n * - SHIPPING & RETURNS at /shipping-returns, PRIVACY POLICY at /privacy and\n * TERMS OF SALE at /terms: editable drafts in the Markdown element, every\n * fact only the merchant knows left as a [bracketed placeholder] — never a\n * return window, a price or a promise the brief did not give.\n *\n * The account and the cart are a shopper's own pages, written UNLISTED\n * (noindex, out of the sitemap); the policies are indexable like every other\n * page.\n *\n * An order's own page is the commerce plugin's built-in /order-status, which\n * every order email links with its signed key; the Account page says so.\n *\n * ── Outside the plan's page count ───────────────────────────────────────\n *\n * They are STORE PAGES, not planned pages: the plan's four to eight pages are\n * the content the model designs, and these are added beside them, so they\n * never crowd one out. They still count toward the plan's pages allowance\n * (`screensPerHost`), as every page a site has does; a store is Starter and\n * up, whose allowance holds both.\n *\n * A page the plan already has stands for its store page instead of a second\n * one: a planned \"Shipping & care\" is the store's shipping page, and a page\n * the plan put at /privacy is its privacy policy. The header and footer link\n * that page.\n *\n * Pure: names, paths, words and node trees. Safe for the console to import.\n */\n\n/** A store page, by what it is. Persisted in job outputs (`proposal.storePage`); never renamed. */\nexport type AiStorePageKey = 'account' | 'cart' | 'shipping' | 'privacy' | 'terms'\n\nexport interface AiStorePageDefinition {\n key: AiStorePageKey\n /** The page's name in Pages, and its heading. */\n title: string\n slug: string\n /** What the footer's link to it says. */\n link: string\n seo: { title: string; description: string }\n /**\n * A shopper's own page, not one to find by search: written UNLISTED, the\n * page's Access setting the console offers, so the tenant serves it\n * `noindex` and leaves it out of the sitemap. Only the account and the\n * cart; the policies, like every content and landing page, stay indexable.\n */\n noindex?: true\n}\n\n/** Every store page, in the order the job writes them and the footer links them. */\nexport const AI_STORE_PAGES: readonly AiStorePageDefinition[] = [\n {\n key: 'account',\n title: 'Your account',\n slug: 'account',\n link: 'Your account',\n noindex: true,\n seo: { title: 'Your account', description: 'Sign in to see your orders, saved addresses and saved items.' },\n },\n {\n key: 'cart',\n title: 'Your cart',\n slug: 'cart',\n link: 'Cart',\n noindex: true,\n seo: { title: 'Your cart', description: 'Review your cart and check out.' },\n },\n {\n key: 'shipping',\n title: 'Shipping & returns',\n slug: 'shipping-returns',\n link: 'Shipping & returns',\n seo: { title: 'Shipping & returns', description: 'How we ship your order, and how returns and refunds work.' },\n },\n {\n key: 'privacy',\n title: 'Privacy policy',\n slug: 'privacy',\n link: 'Privacy policy',\n seo: { title: 'Privacy policy', description: 'What we collect when you shop with us, and what we do with it.' },\n },\n {\n key: 'terms',\n title: 'Terms of sale',\n slug: 'terms',\n link: 'Terms of sale',\n seo: { title: 'Terms of sale', description: 'The terms that apply when you buy from our store.' },\n },\n]\n\n/** What the job's row for the store pages reads. */\nexport const AI_SITE_STORE_PAGES_LABEL = 'Adding your account, cart and policy pages'\n\n/** The note the row carries once they are written: what the merchant fills in. */\nexport const AI_SITE_STORE_PAGES_NOTE =\n 'Your shipping, privacy and terms pages are drafts: fill in the parts in [brackets] with your store’s own details.'\n\n/** A planned page whose words say it is the store's shipping page: \"Shipping & care\", \"Delivery & returns\". */\nconst SHIPPING_WORDS = /\\b(shipping|delivery|returns?|refunds?)\\b/i\n\n/** The words of a planned page's address and title, spaced. */\nconst wordsOf = (screen: { slug: string; title: string }) => `${screen.slug.replace(/[-/_]+/g, ' ')} ${screen.title}`\n\nconst firstSegment = (slug: string) => slug.trim().replace(/^\\/+/, '').split('/')[0].toLowerCase()\n\n/** A store page as a start builds or links it. */\nexport interface AiStorePagePlan {\n key: AiStorePageKey\n title: string\n slug: string\n /** Where the header and footer link it. */\n href: string\n /** What the footer's link says. */\n link: string\n /**\n * The planned page that stands for it, by its title, where the plan has\n * one: nothing is written for this key, and its links go to that page.\n */\n planned?: string\n}\n\n/**\n * The store pages a store plan gets: each one written, or — where a planned\n * page already holds its address, or a planned page's words say it is the\n * store's shipping page — that planned page, linked in its place.\n */\nexport function aiStorePagesOfPlan(screens: ReadonlyArray<{ slug: string; title: string; record?: unknown }>): AiStorePagePlan[] {\n const pages = screens.filter((screen) => !screen.record && firstSegment(screen.slug) !== '')\n return AI_STORE_PAGES.map((page) => {\n const holds =\n pages.find((screen) => firstSegment(screen.slug) === page.slug) ??\n (page.key === 'shipping' ? pages.find((screen) => SHIPPING_WORDS.test(wordsOf(screen))) : undefined)\n if (holds) {\n const slug = firstSegment(holds.slug)\n return { key: page.key, title: page.title, slug, href: `/${slug}`, link: holds.title.trim() || page.link, planned: holds.title }\n }\n return { key: page.key, title: page.title, slug: page.slug, href: `/${page.slug}`, link: page.link }\n })\n}\n\n/** The store pages a start writes itself: those no planned page stands for. */\nexport function aiStorePagesToWrite(pages: readonly AiStorePagePlan[]): AiStorePagePlan[] {\n return pages.filter((page) => !page.planned)\n}\n\n/** The unit input a site layout is told the store's links under. */\nexport const AI_SITE_STORE_LINKS_INPUT = 'storeLinks'\n\n/** What a store's header and footer link (AGL-3676): the account beside the cart, and the store's pages under the site's. */\nexport interface AiStoreFrameLinks {\n /** The account page's path, which the header links beside the cart. */\n account: string | null\n /** The footer's store links, in order: the account, then the policies. */\n footer: Array<{ label: string; href: string }>\n}\n\n/** The header's and footer's store links for these store pages. The cart is the header's own button. */\nexport function aiStoreFrameLinks(pages: readonly AiStorePagePlan[]): AiStoreFrameLinks {\n const account = pages.find((page) => page.key === 'account')\n return {\n account: account?.href ?? null,\n footer: pages.filter((page) => page.key !== 'cart').map((page) => ({ label: page.link, href: page.href })),\n }\n}\n\nconst PATH = /^\\/[a-z0-9-]+$/\n\n/** The store links a layout unit's inputs carry; none for any other layout. */\nexport function aiStoreFrameLinksOf(inputs: Readonly<Record<string, unknown>> | null | undefined): AiStoreFrameLinks | null {\n const raw = inputs?.[AI_SITE_STORE_LINKS_INPUT]\n if (!raw || typeof raw !== 'object') return null\n const { account, footer } = raw as Record<string, unknown>\n const links = Array.isArray(footer)\n ? footer.flatMap((entry) => {\n const { label, href } = (entry ?? {}) as Record<string, unknown>\n return typeof label === 'string' && label.trim() && typeof href === 'string' && PATH.test(href)\n ? [{ label: label.trim().slice(0, 40), href }]\n : []\n })\n : []\n const accountPath = typeof account === 'string' && PATH.test(account) ? account : null\n return accountPath || links.length ? { account: accountPath, footer: links.slice(0, 6) } : null\n}\n\n// ── The pages, as node trees ──────────────────────────────────────────────\n\n/** The canvas root every stored page hangs from (`CANVAS_ROOT_ELEMENT_ID`). */\nconst ROOT = '_@_'\n\n/** The longest one Markdown element is given: the element's own text limit. */\nexport const AI_STORE_MARKDOWN_MAX = 2000\n\n/** The commerce plugin's elements a store page places, by the ids it persists (`ai-site-store-pages.spec.ts` holds them). */\nexport const AI_STORE_ELEMENTS = {\n account: 'customer-account',\n wishlist: 'wishlist',\n cart: 'cart',\n} as const\n\n/** The host token that reads the site's own name at render (`AI_SITE_NAME_TOKEN`). */\nconst NAME = '{{host.businessName}}'\n\n/** What a store page's words may link: the site's contact page and its shop, where the plan has them. */\nexport interface AiStorePageFacts {\n /** The contact page's path, or `null` where the plan has none. */\n contactPath: string | null\n /** The shop's path, `/shop` where the plan has none. */\n shopPath: string\n /** The shipping page's path, as the terms link it. */\n shippingPath: string\n}\n\ninterface StoredNode {\n $id: string\n type: 'node'\n componentId: string\n pluginId: string\n parentId: string | null\n nodes: string[]\n props?: Record<string, unknown>\n sx?: Record<string, unknown>\n}\n\n/** How a sentence asks a shopper to get in touch: the contact page, else a reply to their order email. */\nfunction contact(facts: AiStorePageFacts, words = 'contact us'): string {\n return facts.contactPath ? `[${words}](${facts.contactPath})` : `${words} by replying to your order email`\n}\n\n/** The policy's sections, as markdown, each a `##` heading and its paragraphs. */\nexport function aiStorePolicySections(key: 'shipping' | 'privacy' | 'terms', facts: AiStorePageFacts): string[] {\n if (key === 'shipping') {\n return [\n '## Shipping\\n\\nWe ship orders from [where you ship from]. Orders are packed within [number] business days, and you will get an email with tracking as soon as yours is on its way.\\n\\nShipping costs and delivery options are shown at checkout before you pay. [List the countries or regions you ship to, and any free-shipping offer you make.]',\n `## Returns\\n\\nYou can return an item within [number] days of delivery if it is [unused and in its original packaging]. [Name anything that cannot be returned, such as gift cards or personalized items.]\\n\\nTo start a return, open the link in your order email and choose Request a return, or ${contact(facts)}. [Say who pays for return shipping.]`,\n '## Refunds\\n\\nOnce we receive and check your return, we refund it to your original payment method within [number] business days. [Say whether the original shipping cost is refunded.]',\n `## Damaged or wrong items\\n\\nIf your order arrives damaged or is not what you ordered, ${contact(facts)} within [number] days of delivery with your order number and a photo, and we will put it right.`,\n ]\n }\n if (key === 'privacy') {\n return [\n `## Who we are\\n\\n${NAME} runs this online store. This policy explains what we collect when you visit, shop or create an account, and what we do with it. [Add your business’s legal name and postal address.]`,\n '## What we collect\\n\\n- **When you order:** your name, email address, shipping and billing address, your phone number if you give one, and what you bought.\\n- **When you create an account:** your name, email address, saved addresses, order history and saved items.\\n- **When you sign up for emails:** your email address and your choice to hear from us.\\n- **Payments:** card payments are processed by Stripe. We never see or store your full card number.',\n '## How we use it\\n\\nWe use your information to process and deliver your orders, to send order and shipping emails, to answer your questions, and, only if you opt in, to send you news and offers. You can unsubscribe from marketing emails at any time with the link in each one.',\n '## Who we share it with\\n\\nWe share only what is needed with the services that run the store: our website and store platform, our payment processor (Stripe), and the carriers that deliver your order. [List any other services you use, such as an email or analytics tool.] We do not sell your personal information.',\n '## Cookies\\n\\nThis site uses cookies to keep your cart and your sign-in working. [Describe any analytics or advertising cookies you use, and how visitors choose.]',\n `## Your choices\\n\\nYou can ask to see, correct or delete the information we hold about you: ${contact(facts)}. [Say how long you keep order records, and the privacy rights that apply where you sell.]\\n\\nWe post any change to this policy on this page. Last updated: [date].`,\n ]\n }\n return [\n `## About these terms\\n\\nThese terms apply to purchases from ${NAME} through this website. By placing an order you agree to them. [Add your business’s legal name and where it is registered.]`,\n '## Orders\\n\\nYour order is an offer to buy. We accept it when we send your order confirmation email. If an item turns out to be unavailable, we will tell you and refund what you paid for it.',\n '## Prices and payment\\n\\nPrices are shown in [currency] and [include or exclude] [sales tax or VAT]. Shipping and any taxes are shown at checkout before you pay. Payment is taken securely through Stripe when you place your order.',\n `## Shipping, returns and refunds\\n\\nHow we ship, and how returns and refunds work, is set out on our [Shipping & returns](${facts.shippingPath}) page.`,\n '## Products\\n\\nWe describe and photograph our products as accurately as we can. [Note anything that naturally varies, such as handmade pieces, colors or sizes.]',\n `## Liability\\n\\n[State any limit on your liability, as the law where you sell allows.] Nothing in these terms limits your rights under consumer law.\\n\\n## Contact\\n\\nQuestions about an order? ${contact(facts, 'Contact us')}. Last updated: [date].`,\n ]\n}\n\n/** Sections joined into as few Markdown elements as fit the element's limit, in order. */\nexport function aiStoreMarkdownChunks(sections: readonly string[], max = AI_STORE_MARKDOWN_MAX): string[] {\n const chunks: string[] = []\n for (const section of sections) {\n const last = chunks[chunks.length - 1]\n if (last !== undefined && last.length + 2 + section.length <= max) chunks[chunks.length - 1] = `${last}\\n\\n${section}`\n else chunks.push(section.slice(0, max))\n }\n return chunks\n}\n\n/**\n * A store page's node tree, root first, as a page's first version stores it:\n * the page's heading over the platform's elements, in one section the\n * site's layout renders inside.\n */\nexport function aiStorePageNodes(key: AiStorePageKey, facts: AiStorePageFacts): Record<string, StoredNode> {\n const page = AI_STORE_PAGES.find((one) => one.key === key) as AiStorePageDefinition\n const nodes: Record<string, StoredNode> = {}\n const id = (role: string) => `store-${key}-${role}`\n const container = id('container')\n const add = (role: string, componentId: string, pluginId: string, props: Record<string, unknown>, sx?: Record<string, unknown>): string => {\n const nodeId = id(role)\n nodes[nodeId] = { $id: nodeId, type: 'node', componentId, pluginId, parentId: container, nodes: [], props, ...(sx ? { sx } : {}) }\n return nodeId\n }\n const children: string[] = [add('title', 'muiTypography', 'mui', { children: page.title, variant: 'h1', component: 'h1' }, { mb: 4 })]\n if (key === 'account') {\n children.push(\n add('account', AI_STORE_ELEMENTS.account, 'commerce', { signedOutHeading: 'Sign in or create an account' }),\n add(\n 'guest',\n 'muiTypography',\n 'mui',\n { children: 'Checked out as a guest? The link in your order email opens your order’s status and tracking.', variant: 'body2', component: 'p' },\n { color: 'text.secondary', mt: 3 },\n ),\n add(\n 'saved',\n AI_STORE_ELEMENTS.wishlist,\n 'commerce',\n { heading: 'Saved items', emptyText: 'Nothing saved yet. Tap Save on any product to keep it here.' },\n { mt: 8 },\n ),\n )\n } else if (key === 'cart') {\n children.push(\n add('cart', AI_STORE_ELEMENTS.cart, 'commerce', { variant: 'inline', showCoupon: true }),\n add('shop', 'muiButton', 'mui', { children: 'Continue shopping', variant: 'outlined', href: facts.shopPath }, { mt: 4 }),\n )\n } else {\n aiStoreMarkdownChunks(aiStorePolicySections(key, facts)).forEach((content, index) => {\n children.push(add(`text${index + 1}`, 'markdown', 'mui', { content }))\n })\n }\n const section = id('section')\n nodes[ROOT] = { $id: ROOT, type: 'node', componentId: 'div', pluginId: 'mui', parentId: null, nodes: [section] }\n nodes[section] = {\n $id: section,\n type: 'node',\n componentId: 'section',\n pluginId: 'mui',\n parentId: ROOT,\n nodes: [container],\n props: { element: 'section', ariaLabel: page.title },\n }\n nodes[container] = {\n $id: container,\n type: 'node',\n componentId: 'muiContainer',\n pluginId: 'mui',\n parentId: section,\n nodes: children,\n props: { maxWidth: key === 'account' || key === 'cart' ? 'lg' : 'md' },\n sx: { py: { xs: 6, md: 10 } },\n }\n return nodes\n}\n\n// ── Finishing the store ───────────────────────────────────────────────────\n\n/** One thing left before an AI-built store sells, as its done page lists it. */\nexport interface AiStoreFinishStep {\n id: 'payments' | 'products' | 'shipping' | 'policies' | 'links'\n title: string\n text: string\n /**\n * The record route kind whose list the step opens (`plugin-record-routes`),\n * `pages` for the site's Pages, `layouts` for its Layouts, or `layout` for\n * the layout version a build drafted its store's links into (AGL-3676).\n */\n opens: 'store-settings' | 'product' | 'pages' | 'layouts' | 'layout'\n /**\n * The record of `opens` to land on rather than its list: the store's\n * settings are a page each (AGL-3713), and a step opens the one it names.\n */\n record?: string\n action: string\n}\n\n/**\n * What is left once an AI store is built (Zach, 2026-10-10): connect\n * payments, review the products and their prices, set shipping and tax, and\n * fill in the policies' brackets. Everything else — the storefront, the\n * account, cart and policy pages, the header's cart and account — is done.\n */\nexport const AI_STORE_FINISH_STEPS: readonly AiStoreFinishStep[] = [\n {\n id: 'payments',\n title: 'Connect payments',\n text: 'Connect Stripe so your store can take payments and pay you out.',\n opens: 'store-settings',\n record: 'payments',\n action: 'Set up payments',\n },\n {\n id: 'products',\n title: 'Review your products and prices',\n text: 'Your first products are listed at suggested prices. Review your prices, photos and stock.',\n opens: 'product',\n action: 'Open products',\n },\n {\n id: 'shipping',\n title: 'Set shipping and tax',\n text: 'Choose your shipping rates and how tax is charged at checkout.',\n opens: 'store-settings',\n record: 'shipping',\n action: 'Open store settings',\n },\n {\n id: 'policies',\n title: 'Fill in your policies',\n text: 'Your Shipping & returns, Privacy policy and Terms of sale pages are drafts: replace the parts in [brackets].',\n opens: 'pages',\n action: 'Open pages',\n },\n]\n"],"names":["AI_STORE_PAGES","key","title","slug","link","noindex","seo","description","AI_SITE_STORE_PAGES_LABEL","AI_SITE_STORE_PAGES_NOTE","SHIPPING_WORDS","wordsOf","screen","replace","firstSegment","trim","split","toLowerCase","aiStorePagesOfPlan","screens","pages","filter","record","map","page","holds","find","test","undefined","href","planned","aiStorePagesToWrite","AI_SITE_STORE_LINKS_INPUT","aiStoreFrameLinks","account","footer","label","PATH","aiStoreFrameLinksOf","inputs","raw","links","Array","isArray","flatMap","entry","slice","accountPath","length","ROOT","AI_STORE_MARKDOWN_MAX","AI_STORE_ELEMENTS","wishlist","cart","NAME","contact","facts","words","contactPath","aiStorePolicySections","shippingPath","aiStoreMarkdownChunks","sections","max","chunks","section","last","push","aiStorePageNodes","one","nodes","id","role","container","add","componentId","pluginId","props","sx","nodeId","$id","type","parentId","children","variant","component","mb","signedOutHeading","color","mt","heading","emptyText","showCoupon","shopPath","forEach","content","index","element","ariaLabel","maxWidth","py","xs","md","AI_STORE_FINISH_STEPS","text","opens","action"],"mappings":"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"}
|
package/src/lib/plugin-config.js
CHANGED
|
@@ -51,12 +51,12 @@ import { AI_CATALOG_PROVIDERS, AI_MODEL_CATALOG } from "./providers/catalog.js";
|
|
|
51
51
|
'job.campaign': 'jobCampaignModel',
|
|
52
52
|
'job.workflow': 'jobWorkflowModel'
|
|
53
53
|
};
|
|
54
|
-
const MODEL_OPTIONS = [
|
|
54
|
+
/** Every current catalog model: a retired one is served by its successor, so it is not offered. */ const MODEL_OPTIONS = [
|
|
55
55
|
{
|
|
56
56
|
value: AI_SETTING_PLATFORM,
|
|
57
57
|
label: 'Platform default'
|
|
58
58
|
},
|
|
59
|
-
...AI_MODEL_CATALOG.map((entry)=>({
|
|
59
|
+
...AI_MODEL_CATALOG.filter((entry)=>!entry.successor).map((entry)=>({
|
|
60
60
|
value: entry.id,
|
|
61
61
|
label: `${entry.label} (${entry.provider})`
|
|
62
62
|
}))
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../libs/plugins/ai/src/lib/plugin-config.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 { PluginConfigSchema } from '@aglyn/aglyn'\nimport { AI_PLUGIN_SETTINGS_ID } from './constants'\nimport { AI_CATALOG_PROVIDERS, AI_MODEL_CATALOG, type AiStepKind } from './providers/catalog'\n\n/**\n * The org's AI settings (AGL-2939), stored in `pluginSettings/ai` and\n * inherited per site the way every plugin setting is (AGL-428): which\n * provider serves the workspace, and which catalog model each kind of step\n * runs on. `platform` means \"whatever the deployment's environment says\",\n * which is what every workspace runs with until it chooses.\n *\n * PURE DATA (type-only aglyn import): the client barrel registers it via\n * '@aglyn/aglyn' and the /server entry via '@aglyn/aglyn/server'.\n */\n\n/** The value that defers to the deployment's environment. */\nexport const AI_SETTING_PLATFORM = 'platform'\n\n/** The setting key each step kind's model override is stored under. */\nexport const AI_STEP_MODEL_SETTING: Record<AiStepKind, string> = {\n 'assist.chat': 'chatModel',\n 'copy.element': 'copyElementModel',\n 'copy.section': 'copySectionModel',\n 'copy.blog': 'copyBlogModel',\n 'generate.section': 'generateModel',\n 'job.component': 'jobComponentModel',\n 'job.crm': 'jobCrmModel',\n 'job.experiment': 'jobExperimentModel',\n 'job.form': 'jobFormModel',\n 'job.insight': 'jobInsightModel',\n 'job.layout': 'jobLayoutModel',\n 'job.logic': 'jobLogicModel',\n 'job.edit': 'jobEditModel',\n 'job.template': 'jobTemplateModel',\n 'job.page': 'jobPageModel',\n 'job.products': 'jobProductsModel',\n 'job.seo': 'jobSeoModel',\n 'job.text': 'jobTextModel',\n 'job.theme': 'jobThemeModel',\n 'job.plan': 'jobPlanModel',\n 'job.email': 'jobEmailModel',\n 'job.campaign': 'jobCampaignModel',\n 'job.workflow': 'jobWorkflowModel',\n}\n\nconst MODEL_OPTIONS = [\n { value: AI_SETTING_PLATFORM, label: 'Platform default' },\n ...AI_MODEL_CATALOG.map((entry) => ({\n value: entry.id,\n label: `${entry.label} (${entry.provider})`,\n })),\n]\n\nconst modelField = (kind: AiStepKind, label: string, description: string) => ({\n key: AI_STEP_MODEL_SETTING[kind],\n label,\n type: 'select' as const,\n options: MODEL_OPTIONS,\n description,\n})\n\nexport const AI_CONFIG_SCHEMA: PluginConfigSchema = {\n pluginId: AI_PLUGIN_SETTINGS_ID,\n fields: [\n {\n key: 'provider',\n label: 'AI provider',\n type: 'select',\n options: [\n { value: AI_SETTING_PLATFORM, label: 'Platform default' },\n ...AI_CATALOG_PROVIDERS.map((provider) => ({ value: provider.id, label: provider.label })),\n ],\n description:\n 'Which provider answers this workspace. A model chosen below must ' +\n 'be one the provider serves; otherwise the provider’s default for ' +\n 'that kind of step is used.',\n },\n modelField('assist.chat', 'Assistant model', 'The in-console assistant’s answers.'),\n modelField('copy.element', 'Copy assistant (element) model', 'Rewriting one element’s text.'),\n modelField('copy.section', 'Copy assistant (section) model', 'Writing a section’s copy.'),\n modelField('copy.blog', 'Copy assistant (blog) model', 'Drafting a blog post.'),\n modelField('generate.section', 'Section generation model', 'Generating a section’s structure.'),\n modelField('job.component', 'Generation job (component) model', 'Generating a reusable component and its properties.'),\n modelField('job.crm', 'Generation job (CRM) model', 'CRM record summaries and next steps, email drafts and import column matches.'),\n modelField(\n 'job.experiment',\n 'Generation job (A/B test) model',\n 'Writing variants for an A/B test, and explaining what a test’s result means.',\n ),\n modelField('job.form', 'Generation job (form) model', 'Generating a form from a confirmed plan.'),\n modelField('job.insight', 'Insights model', 'Answering a question about the site’s figures, and the weekly insights.'),\n modelField('job.layout', 'Generation job (layout) model', 'Generating a shared layout from a confirmed plan.'),\n modelField('job.logic', 'Generation job (logic) model', 'Proposing a site function or variable, and explaining a function.'),\n modelField('job.edit', 'Generation job (edit) model', 'Changing a page or layout the site already has, into a version visitors do not see.'),\n modelField('job.template', 'Generation job (template) model', 'Generating a page template from a confirmed plan.'),\n modelField('job.page', 'Generation job (page) model', 'Generating a page, one section at a time, from a confirmed plan.'),\n modelField('job.products', 'Generation job (products) model', 'Writing product copy, and proposing products, categories and discounts for a store.'),\n modelField('job.seo', 'Generation job (SEO) model', 'Search listings, image descriptions and a site audit’s fixes.'),\n modelField('job.text', 'Generation job (text) model', 'The text step of a generation job.'),\n modelField('job.theme', 'Generation job (theme) model', 'Proposing a change to a site’s theme.'),\n modelField('job.plan', 'Generation job (plan) model', 'The plan step of a generation job.'),\n modelField('job.email', 'Generation job (email) model', 'Generating an email design from a confirmed plan.'),\n modelField('job.campaign', 'Generation job (campaign) model', 'Drafting a campaign and its email from a brief.'),\n modelField('job.workflow', 'Generation job (automation) model', 'Drafting an automation from a description, and explaining one.'),\n ],\n defaults: {\n provider: AI_SETTING_PLATFORM,\n ...Object.fromEntries(\n Object.values(AI_STEP_MODEL_SETTING).map((key) => [key, AI_SETTING_PLATFORM]),\n ),\n },\n}\n"],"names":["AI_PLUGIN_SETTINGS_ID","AI_CATALOG_PROVIDERS","AI_MODEL_CATALOG","AI_SETTING_PLATFORM","AI_STEP_MODEL_SETTING","MODEL_OPTIONS","value","label","
|
|
1
|
+
{"version":3,"sources":["../../../../../../libs/plugins/ai/src/lib/plugin-config.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 { PluginConfigSchema } from '@aglyn/aglyn'\nimport { AI_PLUGIN_SETTINGS_ID } from './constants'\nimport { AI_CATALOG_PROVIDERS, AI_MODEL_CATALOG, type AiStepKind } from './providers/catalog'\n\n/**\n * The org's AI settings (AGL-2939), stored in `pluginSettings/ai` and\n * inherited per site the way every plugin setting is (AGL-428): which\n * provider serves the workspace, and which catalog model each kind of step\n * runs on. `platform` means \"whatever the deployment's environment says\",\n * which is what every workspace runs with until it chooses.\n *\n * PURE DATA (type-only aglyn import): the client barrel registers it via\n * '@aglyn/aglyn' and the /server entry via '@aglyn/aglyn/server'.\n */\n\n/** The value that defers to the deployment's environment. */\nexport const AI_SETTING_PLATFORM = 'platform'\n\n/** The setting key each step kind's model override is stored under. */\nexport const AI_STEP_MODEL_SETTING: Record<AiStepKind, string> = {\n 'assist.chat': 'chatModel',\n 'copy.element': 'copyElementModel',\n 'copy.section': 'copySectionModel',\n 'copy.blog': 'copyBlogModel',\n 'generate.section': 'generateModel',\n 'job.component': 'jobComponentModel',\n 'job.crm': 'jobCrmModel',\n 'job.experiment': 'jobExperimentModel',\n 'job.form': 'jobFormModel',\n 'job.insight': 'jobInsightModel',\n 'job.layout': 'jobLayoutModel',\n 'job.logic': 'jobLogicModel',\n 'job.edit': 'jobEditModel',\n 'job.template': 'jobTemplateModel',\n 'job.page': 'jobPageModel',\n 'job.products': 'jobProductsModel',\n 'job.seo': 'jobSeoModel',\n 'job.text': 'jobTextModel',\n 'job.theme': 'jobThemeModel',\n 'job.plan': 'jobPlanModel',\n 'job.email': 'jobEmailModel',\n 'job.campaign': 'jobCampaignModel',\n 'job.workflow': 'jobWorkflowModel',\n}\n\n/** Every current catalog model: a retired one is served by its successor, so it is not offered. */\nconst MODEL_OPTIONS = [\n { value: AI_SETTING_PLATFORM, label: 'Platform default' },\n ...AI_MODEL_CATALOG.filter((entry) => !entry.successor).map((entry) => ({\n value: entry.id,\n label: `${entry.label} (${entry.provider})`,\n })),\n]\n\nconst modelField = (kind: AiStepKind, label: string, description: string) => ({\n key: AI_STEP_MODEL_SETTING[kind],\n label,\n type: 'select' as const,\n options: MODEL_OPTIONS,\n description,\n})\n\nexport const AI_CONFIG_SCHEMA: PluginConfigSchema = {\n pluginId: AI_PLUGIN_SETTINGS_ID,\n fields: [\n {\n key: 'provider',\n label: 'AI provider',\n type: 'select',\n options: [\n { value: AI_SETTING_PLATFORM, label: 'Platform default' },\n ...AI_CATALOG_PROVIDERS.map((provider) => ({ value: provider.id, label: provider.label })),\n ],\n description:\n 'Which provider answers this workspace. A model chosen below must ' +\n 'be one the provider serves; otherwise the provider’s default for ' +\n 'that kind of step is used.',\n },\n modelField('assist.chat', 'Assistant model', 'The in-console assistant’s answers.'),\n modelField('copy.element', 'Copy assistant (element) model', 'Rewriting one element’s text.'),\n modelField('copy.section', 'Copy assistant (section) model', 'Writing a section’s copy.'),\n modelField('copy.blog', 'Copy assistant (blog) model', 'Drafting a blog post.'),\n modelField('generate.section', 'Section generation model', 'Generating a section’s structure.'),\n modelField('job.component', 'Generation job (component) model', 'Generating a reusable component and its properties.'),\n modelField('job.crm', 'Generation job (CRM) model', 'CRM record summaries and next steps, email drafts and import column matches.'),\n modelField(\n 'job.experiment',\n 'Generation job (A/B test) model',\n 'Writing variants for an A/B test, and explaining what a test’s result means.',\n ),\n modelField('job.form', 'Generation job (form) model', 'Generating a form from a confirmed plan.'),\n modelField('job.insight', 'Insights model', 'Answering a question about the site’s figures, and the weekly insights.'),\n modelField('job.layout', 'Generation job (layout) model', 'Generating a shared layout from a confirmed plan.'),\n modelField('job.logic', 'Generation job (logic) model', 'Proposing a site function or variable, and explaining a function.'),\n modelField('job.edit', 'Generation job (edit) model', 'Changing a page or layout the site already has, into a version visitors do not see.'),\n modelField('job.template', 'Generation job (template) model', 'Generating a page template from a confirmed plan.'),\n modelField('job.page', 'Generation job (page) model', 'Generating a page, one section at a time, from a confirmed plan.'),\n modelField('job.products', 'Generation job (products) model', 'Writing product copy, and proposing products, categories and discounts for a store.'),\n modelField('job.seo', 'Generation job (SEO) model', 'Search listings, image descriptions and a site audit’s fixes.'),\n modelField('job.text', 'Generation job (text) model', 'The text step of a generation job.'),\n modelField('job.theme', 'Generation job (theme) model', 'Proposing a change to a site’s theme.'),\n modelField('job.plan', 'Generation job (plan) model', 'The plan step of a generation job.'),\n modelField('job.email', 'Generation job (email) model', 'Generating an email design from a confirmed plan.'),\n modelField('job.campaign', 'Generation job (campaign) model', 'Drafting a campaign and its email from a brief.'),\n modelField('job.workflow', 'Generation job (automation) model', 'Drafting an automation from a description, and explaining one.'),\n ],\n defaults: {\n provider: AI_SETTING_PLATFORM,\n ...Object.fromEntries(\n Object.values(AI_STEP_MODEL_SETTING).map((key) => [key, AI_SETTING_PLATFORM]),\n ),\n },\n}\n"],"names":["AI_PLUGIN_SETTINGS_ID","AI_CATALOG_PROVIDERS","AI_MODEL_CATALOG","AI_SETTING_PLATFORM","AI_STEP_MODEL_SETTING","MODEL_OPTIONS","value","label","filter","entry","successor","map","id","provider","modelField","kind","description","key","type","options","AI_CONFIG_SCHEMA","pluginId","fields","defaults","Object","fromEntries","values"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC;AAGD,SAASA,qBAAqB,QAAQ,iBAAa;AACnD,SAASC,oBAAoB,EAAEC,gBAAgB,QAAyB,yBAAqB;AAE7F;;;;;;;;;CASC,GAED,2DAA2D,GAC3D,OAAO,MAAMC,sBAAsB,WAAU;AAE7C,qEAAqE,GACrE,OAAO,MAAMC,wBAAoD;IAC/D,eAAe;IACf,gBAAgB;IAChB,gBAAgB;IAChB,aAAa;IACb,oBAAoB;IACpB,iBAAiB;IACjB,WAAW;IACX,kBAAkB;IAClB,YAAY;IACZ,eAAe;IACf,cAAc;IACd,aAAa;IACb,YAAY;IACZ,gBAAgB;IAChB,YAAY;IACZ,gBAAgB;IAChB,WAAW;IACX,YAAY;IACZ,aAAa;IACb,YAAY;IACZ,aAAa;IACb,gBAAgB;IAChB,gBAAgB;AAClB,EAAC;AAED,iGAAiG,GACjG,MAAMC,gBAAgB;IACpB;QAAEC,OAAOH;QAAqBI,OAAO;IAAmB;OACrDL,iBAAiBM,MAAM,CAAC,CAACC,QAAU,CAACA,MAAMC,SAAS,EAAEC,GAAG,CAAC,CAACF,QAAW,CAAA;YACtEH,OAAOG,MAAMG,EAAE;YACfL,OAAO,GAAGE,MAAMF,KAAK,CAAC,EAAE,EAAEE,MAAMI,QAAQ,CAAC,CAAC,CAAC;QAC7C,CAAA;CACD;AAED,MAAMC,aAAa,CAACC,MAAkBR,OAAeS,cAAyB,CAAA;QAC5EC,KAAKb,qBAAqB,CAACW,KAAK;QAChCR;QACAW,MAAM;QACNC,SAASd;QACTW;IACF,CAAA;AAEA,OAAO,MAAMI,mBAAuC;IAClDC,UAAUrB;IACVsB,QAAQ;QACN;YACEL,KAAK;YACLV,OAAO;YACPW,MAAM;YACNC,SAAS;gBACP;oBAAEb,OAAOH;oBAAqBI,OAAO;gBAAmB;mBACrDN,qBAAqBU,GAAG,CAAC,CAACE,WAAc,CAAA;wBAAEP,OAAOO,SAASD,EAAE;wBAAEL,OAAOM,SAASN,KAAK;oBAAC,CAAA;aACxF;YACDS,aACE,sEACA,sEACA;QACJ;QACAF,WAAW,eAAe,mBAAmB;QAC7CA,WAAW,gBAAgB,kCAAkC;QAC7DA,WAAW,gBAAgB,kCAAkC;QAC7DA,WAAW,aAAa,+BAA+B;QACvDA,WAAW,oBAAoB,4BAA4B;QAC3DA,WAAW,iBAAiB,oCAAoC;QAChEA,WAAW,WAAW,8BAA8B;QACpDA,WACE,kBACA,mCACA;QAEFA,WAAW,YAAY,+BAA+B;QACtDA,WAAW,eAAe,kBAAkB;QAC5CA,WAAW,cAAc,iCAAiC;QAC1DA,WAAW,aAAa,gCAAgC;QACxDA,WAAW,YAAY,+BAA+B;QACtDA,WAAW,gBAAgB,mCAAmC;QAC9DA,WAAW,YAAY,+BAA+B;QACtDA,WAAW,gBAAgB,mCAAmC;QAC9DA,WAAW,WAAW,8BAA8B;QACpDA,WAAW,YAAY,+BAA+B;QACtDA,WAAW,aAAa,gCAAgC;QACxDA,WAAW,YAAY,+BAA+B;QACtDA,WAAW,aAAa,gCAAgC;QACxDA,WAAW,gBAAgB,mCAAmC;QAC9DA,WAAW,gBAAgB,qCAAqC;KACjE;IACDS,UAAU;QACRV,UAAUV;OACPqB,OAAOC,WAAW,CACnBD,OAAOE,MAAM,CAACtB,uBAAuBO,GAAG,CAAC,CAACM,MAAQ;YAACA;YAAKd;SAAoB;AAGlF,EAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
import type { AnthropicCrmAssistanceWording } from './catalog';
|
|
18
|
+
/**
|
|
19
|
+
* CRM assistance as `/legal/subprocessors` published it until October 5,
|
|
20
|
+
* 2026: the disclosed fields of a record, with addresses and numbers in its
|
|
21
|
+
* text replaced. It is still what production sends while
|
|
22
|
+
* `release_crm_assist_whole_record` is off, which the published wording
|
|
23
|
+
* covers: the row describes what the CRM can send, not who has it on.
|
|
24
|
+
*
|
|
25
|
+
* Kept beside the catalog rather than in it: nothing the console runs reads
|
|
26
|
+
* it, and the client barrel exports the whole catalog, so a record of what was
|
|
27
|
+
* published would load on every console page (AGL-3781).
|
|
28
|
+
*/
|
|
29
|
+
export declare const ANTHROPIC_CRM_ASSISTANCE_DISCLOSED: AnthropicCrmAssistanceWording;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/ /**
|
|
17
|
+
* CRM assistance as `/legal/subprocessors` published it until October 5,
|
|
18
|
+
* 2026: the disclosed fields of a record, with addresses and numbers in its
|
|
19
|
+
* text replaced. It is still what production sends while
|
|
20
|
+
* `release_crm_assist_whole_record` is off, which the published wording
|
|
21
|
+
* covers: the row describes what the CRM can send, not who has it on.
|
|
22
|
+
*
|
|
23
|
+
* Kept beside the catalog rather than in it: nothing the console runs reads
|
|
24
|
+
* it, and the client barrel exports the whole catalog, so a record of what was
|
|
25
|
+
* published would load on every console page (AGL-3781).
|
|
26
|
+
*/ export const ANTHROPIC_CRM_ASSISTANCE_DISCLOSED = {
|
|
27
|
+
record: "For CRM assistance, the opened contact, company, deal or lead as the CRM shows it: its name and, by kind, job title, company, lifecycle stage, tags, capture history and counts, domain, industry, headcount, pipeline stages, status, amount, dates, lost reason, parties and lead status, with its notes, newest timeline entries and open tasks and deals. Email addresses and phone numbers in that text are replaced, and no email, phone or postal field, marketing consent, custom field value, team member or record id is sent.",
|
|
28
|
+
never: 'No account identifiers, email addresses or authentication tokens.'
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
//# sourceMappingURL=anthropic-crm-wording-superseded.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/providers/anthropic-crm-wording-superseded.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 { AnthropicCrmAssistanceWording } from './catalog'\n\n/**\n * CRM assistance as `/legal/subprocessors` published it until October 5,\n * 2026: the disclosed fields of a record, with addresses and numbers in its\n * text replaced. It is still what production sends while\n * `release_crm_assist_whole_record` is off, which the published wording\n * covers: the row describes what the CRM can send, not who has it on.\n *\n * Kept beside the catalog rather than in it: nothing the console runs reads\n * it, and the client barrel exports the whole catalog, so a record of what was\n * published would load on every console page (AGL-3781).\n */\nexport const ANTHROPIC_CRM_ASSISTANCE_DISCLOSED: AnthropicCrmAssistanceWording = {\n record:\n \"For CRM assistance, the opened contact, company, deal or lead as the CRM shows it: its name and, by kind, job title, company, lifecycle stage, tags, capture history and counts, domain, industry, headcount, pipeline stages, status, amount, dates, lost reason, parties and lead status, with its notes, newest timeline entries and open tasks and deals. Email addresses and phone numbers in that text are replaced, and no email, phone or postal field, marketing consent, custom field value, team member or record id is sent.\",\n never: 'No account identifiers, email addresses or authentication tokens.',\n}\n"],"names":["ANTHROPIC_CRM_ASSISTANCE_DISCLOSED","record","never"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAID;;;;;;;;;;CAUC,GACD,OAAO,MAAMA,qCAAoE;IAC/EC,QACE;IACFC,OAAO;AACT,EAAC"}
|
|
@@ -18,7 +18,7 @@ import { _ as _wrap_async_generator } from "@swc/helpers/_/_wrap_async_generator
|
|
|
18
18
|
* See the License for the specific language governing permissions and
|
|
19
19
|
* limitations under the License.
|
|
20
20
|
*/ import { aiModelIdsForProvider, estimateAiBilledUsd, aiCatalogEntry } from "./catalog.js";
|
|
21
|
-
import { AiUpstreamError, aiRawOutputOf, aiStoppedAtCeiling, aiTokenCount, aiToolInputOf } from "./contract.js";
|
|
21
|
+
import { AiBatchUnfinishedError, AiUpstreamError, aiRawOutputOf, aiStoppedAtCeiling, aiTokenCount, aiToolInputOf } from "./contract.js";
|
|
22
22
|
/**
|
|
23
23
|
* The Anthropic adapter (AGL-2903, behind the contract since AGL-2939):
|
|
24
24
|
* the Messages API over raw `fetch`. No provider SDK is installed, and the
|
|
@@ -482,19 +482,32 @@ function batchHeaders(apiKey) {
|
|
|
482
482
|
});
|
|
483
483
|
return new AiUpstreamError(response.status, anthropicFailureIsRetryable(response.status, payload == null ? void 0 : (_payload_error = payload.error) == null ? void 0 : _payload_error.type), requestId, anthropicAccountProblem(response.status, payload == null ? void 0 : payload.error));
|
|
484
484
|
}
|
|
485
|
+
/** Results a batch can end a request with that answer nothing yet: asked again, not failed (AGL-3781). */ const ANTHROPIC_BATCH_UNFINISHED = new Set([
|
|
486
|
+
'canceled',
|
|
487
|
+
'expired'
|
|
488
|
+
]);
|
|
485
489
|
/**
|
|
486
490
|
* Many requests through the Message Batches API (AGL-3660): created as one
|
|
487
491
|
* batch, polled until it has ended, its results read by `custom_id` — they
|
|
488
492
|
* come back in any order — and each turned into the result `complete` would
|
|
489
493
|
* have returned, at half the price. Development only: the live evals' batch
|
|
490
494
|
* mode is the one caller, and no door waits minutes for an answer.
|
|
495
|
+
*
|
|
496
|
+
* A batch still processing when its wait runs out is canceled, and read once
|
|
497
|
+
* the cancel has ended it (AGL-3781): a cancel keeps every answer the batch
|
|
498
|
+
* already has, so those come back as results, and only the requests it never
|
|
499
|
+
* reached come back as `AiBatchUnfinishedError`, for the caller to ask on
|
|
500
|
+
* their own. Throwing away a round's paid-for answers because one batch was
|
|
501
|
+
* slow is how a whole golden run lost its grades.
|
|
491
502
|
*/ async function completeBatch(requests, options = {}) {
|
|
492
|
-
var _options_pollMs, _options_timeoutMs;
|
|
503
|
+
var _options_pollMs, _options_timeoutMs, _options_cancelGraceMs;
|
|
493
504
|
if (!requests.length) return [];
|
|
494
505
|
const apiKey = requests[0].apiKey;
|
|
495
506
|
const model = requests[0].model;
|
|
496
507
|
const pollMs = (_options_pollMs = options.pollMs) != null ? _options_pollMs : 10000;
|
|
497
508
|
const timeoutMs = (_options_timeoutMs = options.timeoutMs) != null ? _options_timeoutMs : 60 * 60000;
|
|
509
|
+
const cancelGraceMs = (_options_cancelGraceMs = options.cancelGraceMs) != null ? _options_cancelGraceMs : 10 * 60000;
|
|
510
|
+
const unfinished = (id, reason)=>requests.map(()=>new AiBatchUnfinishedError(id, reason));
|
|
498
511
|
const created = await fetch(ANTHROPIC_BATCHES_URL, {
|
|
499
512
|
method: 'POST',
|
|
500
513
|
headers: batchHeaders(apiKey),
|
|
@@ -516,14 +529,18 @@ function batchHeaders(apiKey) {
|
|
|
516
529
|
if (!created.ok) throw await batchFailure(created, model);
|
|
517
530
|
let batch = await created.json();
|
|
518
531
|
const deadline = Date.now() + timeoutMs;
|
|
532
|
+
let cancelDeadline = null;
|
|
519
533
|
while(batch.processing_status !== 'ended'){
|
|
520
|
-
if (Date.now()
|
|
534
|
+
if (cancelDeadline === null && Date.now() >= deadline) {
|
|
535
|
+
console.warn(`[ai] batch ${batch.id} has not ended after ${timeoutMs} ms; canceling it to read what it answered`);
|
|
521
536
|
await fetch(`${ANTHROPIC_BATCHES_URL}/${batch.id}/cancel`, {
|
|
522
537
|
method: 'POST',
|
|
523
538
|
headers: batchHeaders(apiKey)
|
|
524
539
|
}).catch(()=>undefined);
|
|
525
|
-
|
|
540
|
+
cancelDeadline = Date.now() + cancelGraceMs;
|
|
526
541
|
}
|
|
542
|
+
// A cancel that never ends leaves no results to read; every request goes back unanswered.
|
|
543
|
+
if (cancelDeadline !== null && Date.now() >= cancelDeadline) return unfinished(batch.id, 'cancel did not end');
|
|
527
544
|
await new Promise((resolve)=>setTimeout(resolve, pollMs));
|
|
528
545
|
const polled = await fetch(`${ANTHROPIC_BATCHES_URL}/${batch.id}`, {
|
|
529
546
|
headers: batchHeaders(apiKey)
|
|
@@ -531,7 +548,10 @@ function batchHeaders(apiKey) {
|
|
|
531
548
|
if (!polled.ok) throw await batchFailure(polled, model);
|
|
532
549
|
batch = await polled.json();
|
|
533
550
|
}
|
|
534
|
-
if (!batch.results_url)
|
|
551
|
+
if (!batch.results_url) {
|
|
552
|
+
if (cancelDeadline !== null) return unfinished(batch.id, 'canceled with no results');
|
|
553
|
+
throw new Error(`batch ${batch.id} ended with no results`);
|
|
554
|
+
}
|
|
535
555
|
const results = await fetch(batch.results_url, {
|
|
536
556
|
headers: batchHeaders(apiKey)
|
|
537
557
|
});
|
|
@@ -549,14 +569,16 @@ function batchHeaders(apiKey) {
|
|
|
549
569
|
if ((result == null ? void 0 : result.type) === 'succeeded') {
|
|
550
570
|
return anthropicResultFrom(result.message, request.model, ANTHROPIC_BATCH_PRICE_FACTOR);
|
|
551
571
|
}
|
|
572
|
+
const type = (_ref = result == null ? void 0 : result.type) != null ? _ref : 'missing';
|
|
573
|
+
if (ANTHROPIC_BATCH_UNFINISHED.has(type) || type === 'missing') return new AiBatchUnfinishedError(batch.id, type);
|
|
552
574
|
console.error('ai batch request not answered', {
|
|
553
575
|
provider: ANTHROPIC_PROVIDER_ID,
|
|
554
576
|
batchId: batch.id,
|
|
555
577
|
customId: `r${index}`,
|
|
556
|
-
result:
|
|
578
|
+
result: type,
|
|
557
579
|
error: (_ref1 = result == null ? void 0 : result.error) != null ? _ref1 : null
|
|
558
580
|
});
|
|
559
|
-
return new AiUpstreamError(null,
|
|
581
|
+
return new AiUpstreamError(null, type === 'errored', batch.id, null);
|
|
560
582
|
});
|
|
561
583
|
}
|
|
562
584
|
export const anthropicProvider = {
|
|
@@ -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 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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"}
|
|
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 AiBatchUnfinishedError,\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/** The batch as its create and poll calls describe it. */\ninterface AnthropicBatch {\n id: string\n processing_status?: string\n results_url?: string | null\n}\n\n/** Results a batch can end a request with that answer nothing yet: asked again, not failed (AGL-3781). */\nconst ANTHROPIC_BATCH_UNFINISHED = new Set(['canceled', 'expired'])\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 *\n * A batch still processing when its wait runs out is canceled, and read once\n * the cancel has ended it (AGL-3781): a cancel keeps every answer the batch\n * already has, so those come back as results, and only the requests it never\n * reached come back as `AiBatchUnfinishedError`, for the caller to ask on\n * their own. Throwing away a round's paid-for answers because one batch was\n * slow is how a whole golden run lost its grades.\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 cancelGraceMs = options.cancelGraceMs ?? 10 * 60_000\n const unfinished = (id: string, reason: string) => requests.map(() => new AiBatchUnfinishedError(id, reason))\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 AnthropicBatch\n const deadline = Date.now() + timeoutMs\n let cancelDeadline: number | null = null\n while (batch.processing_status !== 'ended') {\n if (cancelDeadline === null && Date.now() >= deadline) {\n console.warn(`[ai] batch ${batch.id} has not ended after ${timeoutMs} ms; canceling it to read what it answered`)\n await fetch(`${ANTHROPIC_BATCHES_URL}/${batch.id}/cancel`, { method: 'POST', headers: batchHeaders(apiKey) }).catch(\n () => undefined,\n )\n cancelDeadline = Date.now() + cancelGraceMs\n }\n // A cancel that never ends leaves no results to read; every request goes back unanswered.\n if (cancelDeadline !== null && Date.now() >= cancelDeadline) return unfinished(batch.id, 'cancel did not end')\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 AnthropicBatch\n }\n if (!batch.results_url) {\n if (cancelDeadline !== null) return unfinished(batch.id, 'canceled with no results')\n throw new Error(`batch ${batch.id} ended with no results`)\n }\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 const type = result?.type ?? 'missing'\n if (ANTHROPIC_BATCH_UNFINISHED.has(type) || type === 'missing') return new AiBatchUnfinishedError(batch.id, type)\n console.error('ai batch request not answered', {\n provider: ANTHROPIC_PROVIDER_ID,\n batchId: batch.id,\n customId: `r${index}`,\n result: type,\n error: result?.error ?? null,\n })\n return new AiUpstreamError(null, 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","AiBatchUnfinishedError","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","ANTHROPIC_BATCH_UNFINISHED","Set","completeBatch","requests","options","pollMs","timeoutMs","cancelGraceMs","unfinished","id","created","request","_key","_signal","rest","custom_id","params","batch","deadline","Date","now","cancelDeadline","processing_status","warn","Promise","resolve","setTimeout","polled","results_url","results","byId","entry","trim","result","has","batchId","customId","anthropicProvider","label","apiKeyEnv","readApiKey","process","env","ANTHROPIC_API_KEY","endpointHost","toolSchemaLimits","models","Boolean"],"mappings":"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"}
|