blume 1.7.3 → 2.0.0
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/AGENTS.md +19 -0
- package/CHANGELOG.md +217 -0
- package/README.md +34 -21
- package/dist/cli/chunk-11j0384y.js +148 -0
- package/dist/cli/chunk-11j0384y.js.map +10 -0
- package/dist/cli/{chunk-rqy0s5wh.js → chunk-1w8dp3qb.js} +17 -16
- package/dist/cli/{chunk-rqy0s5wh.js.map → chunk-1w8dp3qb.js.map} +3 -3
- package/dist/cli/chunk-2q1dwty4.js +75 -0
- package/dist/cli/chunk-2q1dwty4.js.map +11 -0
- package/dist/cli/chunk-41za066z.js +122 -0
- package/dist/cli/chunk-41za066z.js.map +11 -0
- package/dist/cli/chunk-5a2z0198.js +133 -0
- package/dist/cli/chunk-5a2z0198.js.map +10 -0
- package/dist/cli/{chunk-5g0w1e2c.js → chunk-6k8vp3ta.js} +25 -13
- package/dist/cli/{chunk-5g0w1e2c.js.map → chunk-6k8vp3ta.js.map} +4 -4
- package/dist/cli/{chunk-5qk08vmp.js → chunk-79njf86q.js} +133 -54
- package/dist/cli/chunk-79njf86q.js.map +11 -0
- package/dist/cli/{chunk-e7f42gdj.js → chunk-7ez8ny0t.js} +2 -2
- package/dist/cli/{chunk-nn13znc2.js → chunk-88cpgt6h.js} +1 -1
- package/dist/cli/chunk-a9kptbw5.js +361 -0
- package/dist/cli/chunk-a9kptbw5.js.map +14 -0
- package/dist/cli/chunk-abh8yjkn.js +31 -0
- package/dist/cli/chunk-abh8yjkn.js.map +10 -0
- package/dist/cli/chunk-b5aj94ah.js +91 -0
- package/dist/cli/chunk-b5aj94ah.js.map +10 -0
- package/dist/cli/{chunk-b27xqwn9.js → chunk-bctazmbk.js} +9 -5
- package/dist/cli/chunk-bctazmbk.js.map +10 -0
- package/dist/cli/chunk-beat36xx.js +279 -0
- package/dist/cli/chunk-beat36xx.js.map +10 -0
- package/dist/cli/chunk-bnbmcwfb.js +145 -0
- package/dist/cli/chunk-bnbmcwfb.js.map +11 -0
- package/dist/cli/{chunk-0xjyb285.js → chunk-bw22s759.js} +15 -5
- package/dist/cli/{chunk-0xjyb285.js.map → chunk-bw22s759.js.map} +4 -4
- package/dist/cli/chunk-by2290sx.js +39 -0
- package/dist/cli/chunk-by2290sx.js.map +10 -0
- package/dist/cli/chunk-d1tadaw7.js +79 -0
- package/dist/cli/chunk-d1tadaw7.js.map +10 -0
- package/dist/cli/{chunk-ahnw3kxw.js → chunk-d80hr03s.js} +24 -19
- package/dist/cli/chunk-d80hr03s.js.map +15 -0
- package/dist/cli/chunk-ernrthtr.js +97 -0
- package/dist/cli/chunk-ernrthtr.js.map +10 -0
- package/dist/cli/chunk-f2972sbt.js +374 -0
- package/dist/cli/chunk-f2972sbt.js.map +10 -0
- package/dist/cli/{chunk-vacwm2hv.js → chunk-f7t03s3g.js} +2 -2
- package/dist/cli/{chunk-2z47ypj8.js → chunk-fa25z98p.js} +16 -3
- package/dist/cli/chunk-fa25z98p.js.map +11 -0
- package/dist/cli/{chunk-cjtn640a.js → chunk-fh5hj5jt.js} +43 -20
- package/dist/cli/chunk-fh5hj5jt.js.map +10 -0
- package/dist/cli/{chunk-yg63d42r.js → chunk-j8mw0za6.js} +86 -57
- package/dist/cli/chunk-j8mw0za6.js.map +35 -0
- package/dist/cli/{chunk-ct47dqpx.js → chunk-jts8mvcz.js} +67 -7
- package/dist/cli/{chunk-2mzebbbz.js.map → chunk-jts8mvcz.js.map} +6 -4
- package/dist/cli/{chunk-ps4m1xh4.js → chunk-mnqj32sj.js} +505 -542
- package/dist/cli/chunk-mnqj32sj.js.map +12 -0
- package/dist/cli/{chunk-8cjtbafj.js → chunk-mwt1k8n7.js} +100 -374
- package/dist/cli/chunk-mwt1k8n7.js.map +10 -0
- package/dist/cli/chunk-nk3ts2xk.js +51 -0
- package/dist/cli/chunk-nk3ts2xk.js.map +10 -0
- package/dist/cli/{chunk-3r45185y.js → chunk-pat2zzwc.js} +9 -11
- package/dist/cli/{chunk-3r45185y.js.map → chunk-pat2zzwc.js.map} +2 -2
- package/dist/cli/chunk-pnnvybbk.js +176 -0
- package/dist/cli/chunk-pnnvybbk.js.map +11 -0
- package/dist/cli/{chunk-4x36ddpw.js → chunk-sqn5t4q0.js} +81 -87
- package/dist/cli/chunk-sqn5t4q0.js.map +10 -0
- package/dist/cli/{chunk-bvwwhd84.js → chunk-tzne8qfq.js} +15 -15
- package/dist/cli/{chunk-bvwwhd84.js.map → chunk-tzne8qfq.js.map} +1 -1
- package/dist/cli/chunk-xaz13gwg.js +12449 -0
- package/dist/cli/chunk-xaz13gwg.js.map +182 -0
- package/dist/cli/chunk-y3e45rc8.js +102 -0
- package/dist/cli/chunk-y3e45rc8.js.map +10 -0
- package/dist/cli/chunk-z01ze5c1.js +261 -0
- package/dist/cli/chunk-z01ze5c1.js.map +10 -0
- package/dist/cli/{chunk-k79xp7av.js → chunk-z1f5arsg.js} +219 -689
- package/dist/cli/chunk-z1f5arsg.js.map +36 -0
- package/dist/cli/{chunk-1jefwnfs.js → chunk-zg2gtj10.js} +1076 -2592
- package/dist/cli/chunk-zg2gtj10.js.map +35 -0
- package/dist/cli/{chunk-dwgcp5sm.js → chunk-zxccj738.js} +1 -1
- package/dist/cli/index.js +214 -57
- package/dist/cli/index.js.map +8 -7
- package/dist/types/ai/agent-readability.d.ts +52 -0
- package/dist/types/ai/ai-catalog.d.ts +42 -0
- package/dist/types/ai/api/paths.d.ts +17 -0
- package/dist/types/ai/api-catalog.d.ts +18 -0
- package/dist/types/ai/ask.d.ts +368 -0
- package/dist/types/ai/changelog-markdown.d.ts +2 -0
- package/dist/types/ai/component-markdown.d.ts +2 -2
- package/dist/types/ai/index.d.ts +24 -0
- package/dist/types/ai/link-headers.d.ts +24 -0
- package/dist/types/ai/llms.d.ts +25 -0
- package/dist/types/ai/markdown.d.ts +45 -0
- package/dist/types/ai/mcp/discovery.d.ts +68 -0
- package/dist/types/ai/mcp/tools.d.ts +16 -0
- package/dist/types/ai/openapi-components.d.ts +43 -0
- package/dist/types/ai/relative-links.d.ts +26 -0
- package/dist/types/ai/serializers.d.ts +15 -0
- package/dist/types/ai/skills.d.ts +42 -0
- package/dist/types/ai/tar.d.ts +25 -0
- package/dist/types/ai/visibility.d.ts +17 -0
- package/dist/types/ai/web-bot-auth.d.ts +16 -0
- package/dist/types/analytics/adobe.d.ts +35 -0
- package/dist/types/analytics/amplitude.d.ts +50 -0
- package/dist/types/analytics/clarity.d.ts +31 -0
- package/dist/types/analytics/clearbit.d.ts +29 -0
- package/dist/types/analytics/cloudflare.d.ts +41 -0
- package/dist/types/analytics/fathom.d.ts +41 -0
- package/dist/types/analytics/google-analytics.d.ts +44 -0
- package/dist/types/analytics/google-tag-manager.d.ts +40 -0
- package/dist/types/analytics/head.d.ts +30 -0
- package/dist/types/analytics/heap.d.ts +40 -0
- package/dist/types/analytics/hightouch.d.ts +44 -0
- package/dist/types/analytics/hotjar.d.ts +33 -0
- package/dist/types/analytics/index.d.ts +61 -0
- package/dist/types/analytics/inline.d.ts +17 -0
- package/dist/types/analytics/logrocket.d.ts +44 -0
- package/dist/types/analytics/mixpanel.d.ts +67 -0
- package/dist/types/analytics/pirsch.d.ts +42 -0
- package/dist/types/analytics/plausible.d.ts +56 -0
- package/dist/types/analytics/posthog.d.ts +45 -0
- package/dist/types/analytics/schema.d.ts +320 -0
- package/dist/types/analytics/script.d.ts +46 -0
- package/dist/types/analytics/segment.d.ts +50 -0
- package/dist/types/analytics/vercel.d.ts +48 -0
- package/dist/types/astro/integration.d.ts +76 -0
- package/dist/types/astro/markdown-negotiation.d.ts +23 -0
- package/dist/types/astro/module-types.d.ts +14 -0
- package/dist/types/astro/pages.d.ts +44 -0
- package/dist/types/cli/env.d.ts +12 -0
- package/dist/types/cli/init/scaffold.d.ts +154 -0
- package/dist/types/components/layout/nav-utils.d.ts +11 -0
- package/dist/types/core/adapter.d.ts +47 -0
- package/dist/types/core/api-name.d.ts +7 -0
- package/dist/types/core/changelog-index.d.ts +13 -0
- package/dist/types/core/config-input.d.ts +186 -515
- package/dist/types/core/config.d.ts +60 -34
- package/dist/types/core/content-assets.d.ts +76 -0
- package/dist/types/core/custom-pages.d.ts +33 -0
- package/dist/types/core/data.d.ts +27 -12
- package/dist/types/core/define-components.d.ts +12 -9
- package/dist/types/core/deployment-env.d.ts +6 -11
- package/dist/types/core/frontmatter.d.ts +10 -0
- package/dist/types/core/graph.d.ts +18 -0
- package/dist/types/core/heading-markers.d.ts +54 -0
- package/dist/types/core/i18n-ui.d.ts +6 -2
- package/dist/types/core/i18n.d.ts +87 -0
- package/dist/types/core/includes.d.ts +138 -0
- package/dist/types/core/last-modified.d.ts +47 -0
- package/dist/types/core/links.d.ts +95 -0
- package/dist/types/core/locale-links.d.ts +60 -0
- package/dist/types/core/manifest.d.ts +17 -0
- package/dist/types/core/meta.d.ts +38 -0
- package/dist/types/core/nav-diagnostics.d.ts +26 -0
- package/dist/types/core/navigation.d.ts +6 -0
- package/dist/types/core/node-require.d.ts +19 -0
- package/dist/types/core/package-json.d.ts +13 -0
- package/dist/types/core/probe.d.ts +42 -0
- package/dist/types/core/project-graph.d.ts +51 -0
- package/dist/types/core/project.d.ts +2 -0
- package/dist/types/core/safe-href.d.ts +2 -0
- package/dist/types/core/safe-links.d.ts +26 -0
- package/dist/types/core/schema.d.ts +2282 -452
- package/dist/types/core/site-url.d.ts +16 -0
- package/dist/types/core/sources/assets.d.ts +36 -0
- package/dist/types/core/sources/cache.d.ts +37 -0
- package/dist/types/core/sources/collection.d.ts +28 -0
- package/dist/types/core/sources/contentful-rich-text.d.ts +31 -0
- package/dist/types/core/sources/contentful.d.ts +40 -0
- package/dist/types/core/sources/filesystem.d.ts +24 -0
- package/dist/types/core/sources/github-releases.d.ts +31 -0
- package/dist/types/core/sources/json.d.ts +30 -0
- package/dist/types/core/sources/lexical.d.ts +19 -0
- package/dist/types/core/sources/lower.d.ts +75 -0
- package/dist/types/core/sources/mdx-remote.d.ts +28 -0
- package/dist/types/core/sources/normalize.d.ts +147 -0
- package/dist/types/core/sources/notion.d.ts +131 -0
- package/dist/types/core/sources/obsidian.d.ts +46 -0
- package/dist/types/core/sources/payload.d.ts +39 -0
- package/dist/types/core/sources/portable-text.d.ts +42 -0
- package/dist/types/core/sources/read.d.ts +23 -0
- package/dist/types/core/sources/remote.d.ts +74 -0
- package/dist/types/core/sources/resolve.d.ts +19 -0
- package/dist/types/core/sources/sanity.d.ts +43 -0
- package/dist/types/core/sources/strapi-blocks.d.ts +12 -0
- package/dist/types/core/sources/strapi.d.ts +33 -0
- package/dist/types/core/sources/types.d.ts +7 -0
- package/dist/types/core/sources/watch.d.ts +45 -0
- package/dist/types/core/text-width.d.ts +11 -0
- package/dist/types/core/types.d.ts +15 -1
- package/dist/types/core/unrecognized-keys.d.ts +7 -0
- package/dist/types/core/versions.d.ts +72 -0
- package/dist/types/core/yaml.d.ts +9 -0
- package/dist/types/deploy/adapter-output.d.ts +45 -0
- package/dist/types/deploy/adapters/cloudflare.d.ts +40 -0
- package/dist/types/deploy/adapters/index.d.ts +29 -0
- package/dist/types/deploy/adapters/netlify.d.ts +37 -0
- package/dist/types/deploy/adapters/node.d.ts +37 -0
- package/dist/types/deploy/adapters/registry.d.ts +133 -0
- package/dist/types/deploy/adapters/types.d.ts +71 -0
- package/dist/types/deploy/adapters/vercel.d.ts +38 -0
- package/dist/types/deploy/artifacts.d.ts +65 -0
- package/dist/types/deploy/cloudflare-negotiation.d.ts +196 -0
- package/dist/types/deploy/function-bundle.d.ts +80 -0
- package/dist/types/deploy/headers.d.ts +50 -0
- package/dist/types/deploy/node-headers.d.ts +42 -0
- package/dist/types/deploy/platforms/cloudflare.d.ts +40 -0
- package/dist/types/deploy/platforms/index.d.ts +18 -0
- package/dist/types/deploy/platforms/netlify.d.ts +13 -0
- package/dist/types/deploy/platforms/node.d.ts +11 -0
- package/dist/types/deploy/platforms/paths.d.ts +27 -0
- package/dist/types/deploy/platforms/static.d.ts +10 -0
- package/dist/types/deploy/platforms/types.d.ts +104 -0
- package/dist/types/deploy/platforms/vercel.d.ts +32 -0
- package/dist/types/deploy/redirects.d.ts +53 -0
- package/dist/types/deploy/robots.d.ts +8 -0
- package/dist/types/deploy/rss.d.ts +31 -0
- package/dist/types/deploy/sitemap.d.ts +21 -0
- package/dist/types/deploy/vercel-negotiation.d.ts +109 -0
- package/dist/types/markdown/code-title.d.ts +32 -0
- package/dist/types/markdown/fence-meta.d.ts +23 -0
- package/dist/types/markdown/themes.d.ts +3 -3
- package/dist/types/openapi/asyncapi.d.ts +129 -0
- package/dist/types/openapi/graphql-build.d.ts +8 -0
- package/dist/types/openapi/graphql.d.ts +122 -0
- package/dist/types/openapi/model.d.ts +158 -0
- package/dist/types/openapi/parse.d.ts +57 -0
- package/dist/types/openapi/references.d.ts +37 -25
- package/dist/types/openapi/render-mdx.d.ts +33 -0
- package/dist/types/openapi/sentence.d.ts +7 -0
- package/dist/types/openapi/signature.d.ts +10 -0
- package/dist/types/openapi/source.d.ts +22 -0
- package/dist/types/openapi/spec-dependency-error.d.ts +10 -0
- package/dist/types/reference/asyncapi.d.ts +166 -0
- package/dist/types/reference/graphql.d.ts +181 -0
- package/dist/types/reference/index.d.ts +32 -0
- package/dist/types/reference/openapi.d.ts +165 -0
- package/dist/types/reference/options.d.ts +157 -0
- package/dist/types/reference/scalar.d.ts +136 -0
- package/dist/types/reference/schema.d.ts +630 -0
- package/dist/types/search/adapters/algolia.d.ts +32 -0
- package/dist/types/search/adapters/flexsearch.d.ts +12 -0
- package/dist/types/search/adapters/index.d.ts +31 -0
- package/dist/types/search/adapters/mixedbread.d.ts +22 -0
- package/dist/types/search/adapters/orama-cloud.d.ts +33 -0
- package/dist/types/search/adapters/orama.d.ts +13 -0
- package/dist/types/search/adapters/pagefind.d.ts +12 -0
- package/dist/types/search/adapters/registry.d.ts +228 -0
- package/dist/types/search/adapters/types.d.ts +34 -0
- package/dist/types/search/adapters/typesense.d.ts +42 -0
- package/dist/types/search/build.d.ts +23 -0
- package/dist/types/search/documents.d.ts +90 -0
- package/dist/types/search/facets.d.ts +3 -0
- package/dist/types/search/sync/algolia.d.ts +14 -0
- package/dist/types/search/sync/index.d.ts +14 -0
- package/dist/types/search/sync/orama-cloud.d.ts +10 -0
- package/dist/types/search/sync/typesense.d.ts +14 -0
- package/dist/types/sources/contentful.d.ts +68 -0
- package/dist/types/sources/custom.d.ts +20 -0
- package/dist/types/sources/filesystem.d.ts +42 -0
- package/dist/types/sources/github-releases.d.ts +46 -0
- package/dist/types/sources/index.d.ts +48 -0
- package/dist/types/sources/mdx-remote.d.ts +63 -0
- package/dist/types/sources/notion.d.ts +65 -0
- package/dist/types/sources/obsidian.d.ts +34 -0
- package/dist/types/sources/payload.d.ts +68 -0
- package/dist/types/sources/registry.d.ts +1414 -0
- package/dist/types/sources/sanity.d.ts +69 -0
- package/dist/types/sources/shared.d.ts +46 -0
- package/dist/types/sources/strapi.d.ts +66 -0
- package/dist/types/theme/icon-kind.d.ts +11 -0
- package/dist/types/theme/icons.d.ts +20 -0
- package/docs/01-quickstart.mdx +18 -18
- package/docs/02-deployment.mdx +50 -26
- package/docs/03-upgrading.mdx +351 -0
- package/docs/04-migrating.mdx +58 -0
- package/docs/08-faq.mdx +3 -3
- package/docs/advanced/blog.mdx +13 -6
- package/docs/advanced/changelog.mdx +23 -35
- package/docs/advanced/custom-pages.mdx +20 -8
- package/docs/advanced/meta.ts +1 -8
- package/docs/advanced/skills.mdx +8 -0
- package/docs/cli/audit.mdx +646 -0
- package/docs/cli/doctor.mdx +29 -0
- package/docs/{reference/eval.mdx → cli/evals.mdx} +9 -8
- package/docs/cli/index.mdx +105 -0
- package/docs/cli/meta.ts +7 -0
- package/docs/{reference → cli}/translate.mdx +1 -1
- package/docs/cli/validate.mdx +41 -0
- package/docs/cli/version.mdx +40 -0
- package/docs/configuration/analytics.mdx +350 -59
- package/docs/configuration/ask-ai.mdx +162 -61
- package/docs/configuration/customization.mdx +15 -9
- package/docs/configuration/index.mdx +50 -31
- package/docs/configuration/search.mdx +75 -54
- package/docs/configuration/theming.mdx +24 -15
- package/docs/content/components.mdx +21 -5
- package/docs/{reference → content}/frontmatter.mdx +35 -1
- package/docs/content/i18n.mdx +8 -6
- package/docs/content/includes.mdx +2 -4
- package/docs/content/index.mdx +1 -1
- package/docs/content/islands.mdx +10 -5
- package/docs/content/meta.mdx +1 -1
- package/docs/content/meta.ts +1 -0
- package/docs/content/navigation.mdx +9 -7
- package/docs/content/sources.mdx +145 -50
- package/docs/content/syntax.mdx +16 -12
- package/docs/content/versioning.mdx +3 -3
- package/docs/discoverability/agent-discovery.mdx +11 -11
- package/docs/discoverability/index.mdx +4 -4
- package/docs/discoverability/json-api.mdx +4 -4
- package/docs/discoverability/llms-txt.mdx +6 -6
- package/docs/discoverability/markdown.mdx +4 -4
- package/docs/discoverability/mcp.mdx +11 -11
- package/docs/discoverability/sitemap-and-robots.mdx +3 -3
- package/docs/index.mdx +2 -2
- package/docs/references/asyncapi.mdx +59 -0
- package/docs/{advanced → references}/graphql.mdx +45 -32
- package/docs/{reference → references}/meta.ts +2 -2
- package/docs/references/openapi.mdx +171 -0
- package/docs/references/scalar.mdx +64 -0
- package/package.json +42 -8
- package/skills/blume/SKILL.md +21 -8
- package/skills/blume-migrate/SKILL.md +22 -21
- package/skills/blume-migrate/assets/oxfmt@0.67.0.patch +49 -0
- package/skills/blume-migrate/references/docusaurus.md +5 -4
- package/skills/blume-migrate/references/fumadocs.md +4 -4
- package/skills/blume-migrate/references/mintlify.md +23 -8
- package/skills/blume-migrate/references/monorepo.md +6 -6
- package/skills/blume-migrate/references/starlight.md +4 -4
- package/src/ai/agent-readability.ts +21 -22
- package/src/ai/ai-catalog.ts +50 -32
- package/src/ai/api/handlers.ts +46 -11
- package/src/ai/api-catalog.ts +8 -8
- package/src/ai/ask-data.ts +1 -1
- package/src/ai/ask.ts +624 -100
- package/src/ai/changelog-markdown.ts +91 -0
- package/src/ai/component-markdown.ts +328 -12
- package/src/ai/index.ts +45 -0
- package/src/ai/link-headers.ts +7 -6
- package/src/ai/llms.ts +20 -15
- package/src/ai/markdown.ts +35 -5
- package/src/ai/mcp/data.ts +9 -5
- package/src/ai/openapi-components.ts +4 -1
- package/src/ai/relative-links.ts +170 -0
- package/src/ai/serializers.ts +2 -2
- package/src/ai/skills.ts +1 -1
- package/src/ai/web-bot-auth.ts +2 -2
- package/src/analytics/adobe.ts +46 -0
- package/src/analytics/amplitude.ts +79 -0
- package/src/analytics/clarity.ts +46 -0
- package/src/analytics/clearbit.ts +47 -0
- package/src/analytics/cloudflare.ts +67 -0
- package/src/analytics/fathom.ts +64 -0
- package/src/analytics/google-analytics.ts +84 -0
- package/src/analytics/google-tag-manager.ts +61 -0
- package/src/analytics/head.ts +130 -0
- package/src/analytics/heap.ts +65 -0
- package/src/analytics/hightouch.ts +77 -0
- package/src/analytics/hotjar.ts +47 -0
- package/src/analytics/index.ts +71 -0
- package/src/analytics/inline.ts +21 -0
- package/src/analytics/logrocket.ts +71 -0
- package/src/analytics/mixpanel.ts +92 -0
- package/src/analytics/pirsch.ts +66 -0
- package/src/analytics/plausible.ts +83 -0
- package/src/analytics/posthog.ts +78 -0
- package/src/analytics/schema.ts +60 -0
- package/src/analytics/script.ts +60 -0
- package/src/analytics/segment.ts +85 -0
- package/src/analytics/vercel.ts +50 -0
- package/src/astro/adapter-root.ts +7 -9
- package/src/astro/component-slots.ts +131 -91
- package/src/astro/generate.ts +112 -345
- package/src/astro/integration.ts +2 -6
- package/src/astro/pages.ts +13 -101
- package/src/astro/render-deps.ts +379 -0
- package/src/astro/runtime-deps.ts +201 -0
- package/src/astro/templates.ts +554 -541
- package/src/audit/agent.ts +24 -0
- package/src/audit/catalog.ts +2 -2
- package/src/audit/checks/assets.ts +2 -2
- package/src/audit/checks/dns-aid.ts +1 -1
- package/src/audit/checks/duplicates.ts +3 -1
- package/src/audit/checks/i18n.ts +1 -1
- package/src/audit/checks/indexability.ts +7 -7
- package/src/audit/checks/links.ts +2 -2
- package/src/audit/checks/llms.ts +6 -6
- package/src/audit/checks/network.ts +3 -3
- package/src/audit/checks/og-image.ts +2 -2
- package/src/audit/checks/robots.ts +1 -1
- package/src/audit/checks/sitemap.ts +2 -2
- package/src/audit/checks/social.ts +1 -1
- package/src/audit/run.ts +4 -3
- package/src/audit/terms.ts +31 -0
- package/src/audit/url.ts +13 -13
- package/src/cli/command-meta.ts +10 -0
- package/src/cli/commands/audit.ts +39 -20
- package/src/cli/commands/build.ts +71 -316
- package/src/cli/commands/check.ts +1 -0
- package/src/cli/commands/dev.ts +40 -1
- package/src/cli/commands/doctor.ts +90 -14
- package/src/cli/commands/eject.ts +44 -7
- package/src/cli/commands/eval.ts +2 -2
- package/src/cli/commands/init.ts +161 -41
- package/src/cli/commands/migrate.ts +121 -0
- package/src/cli/commands/preview.ts +7 -1
- package/src/cli/commands/translate.ts +2 -2
- package/src/cli/commands/upgrade.ts +141 -0
- package/src/cli/commands/version.ts +57 -44
- package/src/cli/eject-scripts.ts +121 -6
- package/src/cli/index.ts +11 -1
- package/src/cli/init/install.ts +70 -0
- package/src/cli/init/questions.ts +7 -0
- package/src/cli/init/scaffold.ts +459 -75
- package/src/cli/lazy-command.ts +37 -1
- package/src/cli/prepare.ts +40 -6
- package/src/cli/required-secrets.ts +38 -11
- package/src/cli/unknown-flags.ts +266 -0
- package/src/cli/yarn-pnp.ts +52 -0
- package/src/components/content/AccordionItem.astro +7 -1
- package/src/components/content/Card.astro +4 -3
- package/src/components/content/ColorItem.astro +22 -4
- package/src/components/content/GithubInfo.astro +2 -2
- package/src/components/content/Prompt.astro +25 -25
- package/src/components/content/Tabs.astro +3 -1
- package/src/components/content/Tile.astro +2 -3
- package/src/components/content/Tooltip.astro +57 -9
- package/src/components/content/content-strings.ts +34 -0
- package/src/components/content/diff.ts +1 -1
- package/src/components/content/mermaid-element.ts +13 -2
- package/src/components/content/prompt-markdown.ts +292 -0
- package/src/components/content/tooltip-id.ts +41 -0
- package/src/components/islands/hooks.ts +25 -2
- package/src/components/layout/Analytics.astro +21 -79
- package/src/components/layout/Banner.astro +3 -1
- package/src/components/layout/DiscoveryLinks.astro +69 -0
- package/src/components/layout/Header.astro +83 -20
- package/src/components/layout/LanguageSwitcher.astro +4 -1
- package/src/components/layout/Logo.astro +23 -2
- package/src/components/layout/NavSelector.astro +13 -2
- package/src/components/layout/NavTree.astro +12 -3
- package/src/components/layout/NavTreeScript.astro +17 -3
- package/src/components/layout/PageActions.astro +3 -3
- package/src/components/layout/PageFeedback.astro +11 -1
- package/src/components/layout/PageLayout.astro +52 -5
- package/src/components/layout/ReferenceLayout.astro +21 -12
- package/src/components/layout/RootLayout.astro +69 -66
- package/src/components/layout/Search.astro +30 -6
- package/src/components/layout/WebMcp.astro +1 -1
- package/src/components/layout/analytics-client.ts +72 -15
- package/src/components/layout/drawer-inert.ts +113 -15
- package/src/components/layout/dropdown-clamp.ts +105 -0
- package/src/components/layout/head-scripts.ts +15 -6
- package/src/components/layout/nav-utils.ts +17 -0
- package/src/components/layout/search/algolia.ts +8 -8
- package/src/components/layout/search/orama-cloud.ts +9 -7
- package/src/components/layout/search/typesense.ts +11 -17
- package/src/components/openapi/MessageComposer.astro +2 -2
- package/src/components/openapi/Playground.astro +2 -2
- package/src/components/openapi/playground-client.ts +79 -10
- package/src/core/changelog-index.ts +24 -0
- package/src/core/component-overrides.ts +399 -154
- package/src/core/config-input.ts +188 -553
- package/src/core/config.ts +130 -41
- package/src/core/custom-pages.ts +105 -0
- package/src/core/data.ts +31 -12
- package/src/core/define-components.ts +12 -9
- package/src/core/deployment-env.ts +18 -74
- package/src/core/diagnostics.ts +14 -7
- package/src/core/graph.ts +69 -25
- package/src/core/i18n-ui.ts +6 -2
- package/src/core/i18n.ts +17 -0
- package/src/core/includes.ts +156 -38
- package/src/core/last-modified.ts +6 -11
- package/src/core/links.ts +166 -2
- package/src/core/manifest.ts +10 -3
- package/src/core/navigation.ts +115 -16
- package/src/core/new-tab.ts +35 -0
- package/src/core/node-require.ts +21 -0
- package/src/core/project-graph.ts +42 -26
- package/src/core/project.ts +9 -4
- package/src/core/request-body.ts +61 -0
- package/src/core/safe-href.ts +28 -0
- package/src/core/safe-links.ts +68 -0
- package/src/core/schema.ts +517 -739
- package/src/core/server-features.ts +8 -9
- package/src/core/sources/assets.ts +47 -11
- package/src/core/sources/collection.ts +67 -0
- package/src/core/sources/contentful-rich-text.ts +285 -0
- package/src/core/sources/contentful.ts +173 -0
- package/src/core/sources/github-releases.ts +51 -1
- package/src/core/sources/json.ts +71 -0
- package/src/core/sources/lexical.ts +195 -0
- package/src/core/sources/lower.ts +226 -0
- package/src/core/sources/normalize.ts +52 -2
- package/src/core/sources/notion.ts +39 -28
- package/src/core/sources/payload.ts +135 -0
- package/src/core/sources/portable-text.ts +11 -16
- package/src/core/sources/remote.ts +226 -0
- package/src/core/sources/resolve.ts +104 -166
- package/src/core/sources/sanity.ts +16 -49
- package/src/core/sources/strapi-blocks.ts +124 -0
- package/src/core/sources/strapi.ts +191 -0
- package/src/core/sources/types.ts +12 -1
- package/src/core/types.ts +15 -1
- package/src/core/ui-packs/ar.ts +6 -2
- package/src/core/ui-packs/bg.ts +6 -2
- package/src/core/ui-packs/bn.ts +6 -2
- package/src/core/ui-packs/ca.ts +3 -1
- package/src/core/ui-packs/cs.ts +6 -2
- package/src/core/ui-packs/da.ts +6 -2
- package/src/core/ui-packs/de.ts +6 -2
- package/src/core/ui-packs/el.ts +3 -1
- package/src/core/ui-packs/es.ts +3 -1
- package/src/core/ui-packs/fa.ts +6 -2
- package/src/core/ui-packs/fi.ts +6 -2
- package/src/core/ui-packs/fr.ts +3 -1
- package/src/core/ui-packs/he.ts +6 -2
- package/src/core/ui-packs/hi.ts +6 -2
- package/src/core/ui-packs/hr.ts +6 -2
- package/src/core/ui-packs/hu.ts +6 -2
- package/src/core/ui-packs/id.ts +6 -2
- package/src/core/ui-packs/it.ts +3 -1
- package/src/core/ui-packs/ja.ts +3 -1
- package/src/core/ui-packs/ko.ts +3 -1
- package/src/core/ui-packs/nl.ts +6 -2
- package/src/core/ui-packs/no.ts +6 -2
- package/src/core/ui-packs/pl.ts +6 -2
- package/src/core/ui-packs/pt-br.ts +3 -1
- package/src/core/ui-packs/pt.ts +3 -1
- package/src/core/ui-packs/ro.ts +6 -2
- package/src/core/ui-packs/ru.ts +6 -2
- package/src/core/ui-packs/sk.ts +6 -2
- package/src/core/ui-packs/sr.ts +6 -2
- package/src/core/ui-packs/sv.ts +6 -2
- package/src/core/ui-packs/th.ts +3 -1
- package/src/core/ui-packs/tr.ts +6 -2
- package/src/core/ui-packs/uk.ts +6 -2
- package/src/core/ui-packs/vi.ts +3 -1
- package/src/core/ui-packs/zh-tw.ts +3 -1
- package/src/core/ui-packs/zh.ts +3 -1
- package/src/core/unrecognized-keys.ts +10 -0
- package/src/core/version-cut.ts +116 -8
- package/src/deploy/adapter-output.ts +57 -97
- package/src/deploy/adapters/cloudflare.ts +39 -0
- package/src/deploy/adapters/index.ts +41 -0
- package/src/deploy/adapters/netlify.ts +34 -0
- package/src/deploy/adapters/node.ts +34 -0
- package/src/deploy/adapters/registry.ts +127 -0
- package/src/deploy/adapters/types.ts +92 -0
- package/src/deploy/adapters/vercel.ts +35 -0
- package/src/deploy/artifacts.ts +55 -27
- package/src/deploy/cloudflare-negotiation.ts +179 -100
- package/src/deploy/function-bundle.ts +18 -3
- package/src/deploy/headers.ts +124 -23
- package/src/deploy/node-headers.ts +198 -0
- package/src/deploy/platforms/cloudflare.ts +312 -0
- package/src/deploy/platforms/index.ts +67 -0
- package/src/deploy/platforms/netlify.ts +52 -0
- package/src/deploy/platforms/node.ts +40 -0
- package/src/deploy/platforms/paths.ts +42 -0
- package/src/deploy/platforms/static.ts +29 -0
- package/src/deploy/platforms/types.ts +112 -0
- package/src/deploy/platforms/vercel.ts +193 -0
- package/src/deploy/redirects.ts +30 -18
- package/src/deploy/robots.ts +3 -3
- package/src/deploy/rss.ts +2 -2
- package/src/deploy/sitemap.ts +2 -2
- package/src/deploy/vercel-negotiation.ts +2 -2
- package/src/eval/agents.ts +32 -1
- package/src/eval/findings.ts +19 -11
- package/src/eval/report.ts +10 -2
- package/src/markdown/external-links.ts +65 -0
- package/src/markdown/include.ts +45 -27
- package/src/markdown/index.ts +34 -9
- package/src/markdown/inline-code.ts +12 -6
- package/src/markdown/relative-links.ts +324 -0
- package/src/markdown/themes.ts +3 -3
- package/src/migrate/migrate.ts +149 -0
- package/src/openapi/parse.ts +64 -16
- package/src/openapi/proxy.ts +62 -10
- package/src/openapi/references.ts +147 -147
- package/src/openapi/render-mdx.ts +32 -10
- package/src/openapi/scalar.ts +15 -13
- package/src/openapi/sentence.ts +14 -0
- package/src/openapi/source.ts +37 -21
- package/src/openapi/spec-dependency-error.ts +15 -0
- package/src/reference/asyncapi.ts +83 -0
- package/src/reference/graphql.ts +89 -0
- package/src/reference/index.ts +40 -0
- package/src/reference/openapi.ts +83 -0
- package/src/reference/options.ts +201 -0
- package/src/reference/scalar.ts +136 -0
- package/src/reference/schema.ts +88 -0
- package/src/registry/eject.ts +97 -42
- package/src/search/adapters/algolia.ts +46 -0
- package/src/search/adapters/flexsearch.ts +29 -0
- package/src/search/adapters/index.ts +39 -0
- package/src/search/adapters/mixedbread.ts +39 -0
- package/src/search/adapters/orama-cloud.ts +51 -0
- package/src/search/adapters/orama.ts +24 -0
- package/src/search/adapters/pagefind.ts +27 -0
- package/src/search/adapters/registry.ts +131 -0
- package/src/search/adapters/types.ts +46 -0
- package/src/search/adapters/typesense.ts +57 -0
- package/src/search/build.ts +8 -4
- package/src/search/documents.ts +6 -0
- package/src/search/sync/algolia.ts +12 -11
- package/src/search/sync/index.ts +35 -20
- package/src/search/sync/orama-cloud.ts +12 -9
- package/src/search/sync/typesense.ts +15 -13
- package/src/sources/contentful.ts +63 -0
- package/src/sources/custom.ts +38 -0
- package/src/sources/filesystem.ts +51 -0
- package/src/sources/github-releases.ts +52 -0
- package/src/sources/index.ts +60 -0
- package/src/sources/mdx-remote.ts +76 -0
- package/src/sources/notion.ts +63 -0
- package/src/sources/obsidian.ts +38 -0
- package/src/sources/payload.ts +60 -0
- package/src/sources/registry.ts +182 -0
- package/src/sources/sanity.ts +66 -0
- package/src/sources/shared.ts +52 -0
- package/src/sources/strapi.ts +58 -0
- package/src/theme/entry.ts +24 -2
- package/src/translate/report.ts +40 -7
- package/src/upgrade/upgrade.ts +499 -0
- package/dist/cli/chunk-0qymqwzz.js +0 -164
- package/dist/cli/chunk-0qymqwzz.js.map +0 -15
- package/dist/cli/chunk-1jefwnfs.js.map +0 -48
- package/dist/cli/chunk-2mzebbbz.js +0 -69
- package/dist/cli/chunk-2z47ypj8.js.map +0 -11
- package/dist/cli/chunk-4x36ddpw.js.map +0 -11
- package/dist/cli/chunk-5093q3n7.js +0 -68
- package/dist/cli/chunk-5093q3n7.js.map +0 -10
- package/dist/cli/chunk-5qk08vmp.js.map +0 -11
- package/dist/cli/chunk-7s8hm3b6.js +0 -5347
- package/dist/cli/chunk-7s8hm3b6.js.map +0 -58
- package/dist/cli/chunk-8cjtbafj.js.map +0 -13
- package/dist/cli/chunk-97r59kpr.js +0 -381
- package/dist/cli/chunk-97r59kpr.js.map +0 -12
- package/dist/cli/chunk-ahnw3kxw.js.map +0 -15
- package/dist/cli/chunk-b27xqwn9.js.map +0 -10
- package/dist/cli/chunk-bf6bt1xt.js +0 -185
- package/dist/cli/chunk-bf6bt1xt.js.map +0 -11
- package/dist/cli/chunk-cjtn640a.js.map +0 -10
- package/dist/cli/chunk-ct47dqpx.js.map +0 -11
- package/dist/cli/chunk-esphfr8p.js +0 -107
- package/dist/cli/chunk-esphfr8p.js.map +0 -11
- package/dist/cli/chunk-ex56aa81.js +0 -1016
- package/dist/cli/chunk-ex56aa81.js.map +0 -13
- package/dist/cli/chunk-garjf5z9.js +0 -30
- package/dist/cli/chunk-garjf5z9.js.map +0 -10
- package/dist/cli/chunk-js7saxwm.js +0 -1045
- package/dist/cli/chunk-js7saxwm.js.map +0 -22
- package/dist/cli/chunk-k79xp7av.js.map +0 -39
- package/dist/cli/chunk-ps4m1xh4.js.map +0 -15
- package/dist/cli/chunk-q4rae3bg.js +0 -60
- package/dist/cli/chunk-q4rae3bg.js.map +0 -10
- package/dist/cli/chunk-rz9jmfhz.js +0 -108
- package/dist/cli/chunk-rz9jmfhz.js.map +0 -10
- package/dist/cli/chunk-vh9w1sgp.js +0 -73
- package/dist/cli/chunk-vh9w1sgp.js.map +0 -10
- package/dist/cli/chunk-vrfp10qk.js +0 -81
- package/dist/cli/chunk-vrfp10qk.js.map +0 -10
- package/dist/cli/chunk-yg63d42r.js.map +0 -34
- package/docs/advanced/api-reference.mdx +0 -240
- package/docs/reference/cli.mdx +0 -197
- package/skills/blume-migrate/assets/oxfmt@0.55.0.patch +0 -20
- package/src/components/content/changelog-element.ts +0 -69
- package/src/search/providers.ts +0 -91
- /package/dist/cli/{chunk-e7f42gdj.js.map → chunk-7ez8ny0t.js.map} +0 -0
- /package/dist/cli/{chunk-nn13znc2.js.map → chunk-88cpgt6h.js.map} +0 -0
- /package/dist/cli/{chunk-vacwm2hv.js.map → chunk-f7t03s3g.js.map} +0 -0
- /package/dist/cli/{chunk-dwgcp5sm.js.map → chunk-zxccj738.js.map} +0 -0
package/src/ai/ask.ts
CHANGED
|
@@ -1,134 +1,658 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
import type { AdapterDescriptor, JsonValue } from "../core/adapter.ts";
|
|
4
|
+
import { adapterDescriptorSchema } from "../core/adapter.ts";
|
|
5
|
+
import { unrecognizedKeysMessage } from "../core/unrecognized-keys.ts";
|
|
2
6
|
|
|
3
7
|
/**
|
|
4
|
-
* The
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* AI SDK's OpenAI-compatible provider.
|
|
8
|
+
* The `reasoning` levels the adapters accept: the AI SDK's top-level
|
|
9
|
+
* `reasoning` values minus `provider-default`, which is what omitting the
|
|
10
|
+
* option means.
|
|
8
11
|
*/
|
|
9
|
-
export
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
headers?: AskHeaders;
|
|
21
|
-
kind: "openai-compatible";
|
|
22
|
-
model: string;
|
|
23
|
-
name: string;
|
|
24
|
-
};
|
|
12
|
+
export const askReasoningLevels = [
|
|
13
|
+
"none",
|
|
14
|
+
"minimal",
|
|
15
|
+
"low",
|
|
16
|
+
"medium",
|
|
17
|
+
"high",
|
|
18
|
+
"xhigh",
|
|
19
|
+
] as const;
|
|
20
|
+
|
|
21
|
+
/** How much the model reasons before answering (an adapter's `reasoning`). */
|
|
22
|
+
export type AskReasoning = (typeof askReasoningLevels)[number];
|
|
25
23
|
|
|
26
24
|
/**
|
|
27
|
-
*
|
|
28
|
-
* provider
|
|
29
|
-
*
|
|
30
|
-
* provider applies them after the `Authorization` header it derives from the
|
|
31
|
-
* API key, so a custom header can't displace auth.
|
|
25
|
+
* The AI SDK's `providerOptions` shape, forwarded to `streamText` verbatim:
|
|
26
|
+
* `{ [provider]: { [option]: value } }`. The escape hatch for model controls
|
|
27
|
+
* Blume doesn't name, so a new provider knob never needs a Blume field.
|
|
32
28
|
*/
|
|
33
|
-
export type
|
|
29
|
+
export type AskProviderOptions = Record<string, Record<string, JsonValue>>;
|
|
34
30
|
|
|
35
|
-
|
|
36
|
-
|
|
31
|
+
/** The AI SDK provider package the OpenAI-compatible adapters install. */
|
|
32
|
+
const OPENAI_COMPATIBLE_DEP = "@ai-sdk/openai-compatible";
|
|
33
|
+
|
|
34
|
+
// ---------------------------------------------------------------------------
|
|
35
|
+
// Shared options
|
|
36
|
+
// ---------------------------------------------------------------------------
|
|
37
|
+
|
|
38
|
+
/** The options every Ask AI adapter accepts. */
|
|
39
|
+
export interface AskAdapterOptions {
|
|
40
|
+
/**
|
|
41
|
+
* Name of the env var holding the provider's API key. Each adapter has its
|
|
42
|
+
* own default; set this only to point at a different variable.
|
|
43
|
+
*/
|
|
44
|
+
apiKeyEnv?: string;
|
|
45
|
+
/**
|
|
46
|
+
* Static request headers sent to the provider on every call — a
|
|
47
|
+
* caller-identifying header for a shared backend, for example. Values are
|
|
48
|
+
* written into the generated route as literals, so keep secrets in
|
|
49
|
+
* `apiKeyEnv` rather than here.
|
|
50
|
+
*/
|
|
51
|
+
headers?: Record<string, string>;
|
|
52
|
+
/**
|
|
53
|
+
* Options passed to `streamText` as its `providerOptions`, untouched, in the
|
|
54
|
+
* AI SDK's own shape (`{ openai: { textVerbosity: "low" } }`, say).
|
|
55
|
+
*/
|
|
56
|
+
providerOptions?: AskProviderOptions;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* `providerOptions`, forwarded to `streamText` verbatim. JSON-only, because
|
|
61
|
+
* the generated and ejected routes inline it as a literal.
|
|
62
|
+
*/
|
|
63
|
+
const providerOptionsSchema = z.record(
|
|
64
|
+
z.string(),
|
|
65
|
+
z.record(z.string(), z.json())
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
/** The shared option schema, with the adapter's own key env var default. */
|
|
69
|
+
const sharedOptions = (apiKeyEnv: string) => ({
|
|
70
|
+
apiKeyEnv: z.string().min(1).default(apiKeyEnv),
|
|
71
|
+
headers: z.record(z.string(), z.string()).optional(),
|
|
72
|
+
providerOptions: providerOptionsSchema.optional(),
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
const reasoningOption = z.enum(askReasoningLevels).optional();
|
|
76
|
+
|
|
77
|
+
// ---------------------------------------------------------------------------
|
|
78
|
+
// gateway()
|
|
79
|
+
// ---------------------------------------------------------------------------
|
|
80
|
+
|
|
81
|
+
const GATEWAY_API_KEY_ENV = "AI_GATEWAY_API_KEY";
|
|
82
|
+
/** The model the gateway adapter uses when none is configured. */
|
|
83
|
+
const DEFAULT_GATEWAY_MODEL = "openai/gpt-5.5";
|
|
84
|
+
|
|
85
|
+
/** Options for {@link gateway}. */
|
|
86
|
+
export interface AskGatewayOptions extends AskAdapterOptions {
|
|
87
|
+
/** A `provider/model` id routed by the gateway. Defaults to `openai/gpt-5.5`. */
|
|
88
|
+
model?: string;
|
|
89
|
+
/**
|
|
90
|
+
* How much the model reasons before answering. Sent as the AI SDK's
|
|
91
|
+
* top-level `reasoning` option, which the gateway maps to the model's own
|
|
92
|
+
* control (OpenAI's `reasoning_effort`, for example); the model has to
|
|
93
|
+
* offer the level you pick. Omitted keeps the model's default.
|
|
94
|
+
*/
|
|
95
|
+
reasoning?: AskReasoning;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const gatewayOptionsSchema = z.strictObject({
|
|
99
|
+
...sharedOptions(GATEWAY_API_KEY_ENV),
|
|
100
|
+
model: z.string().min(1).default(DEFAULT_GATEWAY_MODEL),
|
|
101
|
+
reasoning: reasoningOption,
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
export type AskGatewayAdapter = AdapterDescriptor<"gateway", AskGatewayOptions>;
|
|
105
|
+
|
|
106
|
+
export const gatewayAdapterSchema = adapterDescriptorSchema(
|
|
107
|
+
"gateway",
|
|
108
|
+
gatewayOptionsSchema
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Route Ask AI through the Vercel AI Gateway (the default). `model` is a
|
|
113
|
+
* `provider/model` string; the key is `AI_GATEWAY_API_KEY`, or Vercel's OIDC
|
|
114
|
+
* token when deployed there. Needs no provider SDK beyond the `ai` package
|
|
115
|
+
* Blume ships.
|
|
116
|
+
*/
|
|
117
|
+
export const gateway = (
|
|
118
|
+
options: AskGatewayOptions = {}
|
|
119
|
+
): AskGatewayAdapter => ({
|
|
120
|
+
kind: "gateway",
|
|
121
|
+
options,
|
|
122
|
+
requiredSecrets: [options.apiKeyEnv ?? GATEWAY_API_KEY_ENV],
|
|
123
|
+
runtimeDeps: [],
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
// ---------------------------------------------------------------------------
|
|
127
|
+
// openrouter()
|
|
128
|
+
// ---------------------------------------------------------------------------
|
|
129
|
+
|
|
130
|
+
const OPENROUTER_API_KEY_ENV = "OPENROUTER_API_KEY";
|
|
131
|
+
|
|
132
|
+
/** Options for {@link openrouter}. */
|
|
133
|
+
export interface AskOpenRouterOptions extends AskAdapterOptions {
|
|
134
|
+
/** The OpenRouter model id (`anthropic/claude-sonnet-4-5`). */
|
|
135
|
+
model: string;
|
|
136
|
+
/**
|
|
137
|
+
* How much the model reasons before answering. Set on the model as
|
|
138
|
+
* OpenRouter's `reasoning.effort`, because its provider ignores the AI
|
|
139
|
+
* SDK's call-level option. Omitted keeps the model's default.
|
|
140
|
+
*/
|
|
141
|
+
reasoning?: AskReasoning;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const openrouterOptionsSchema = z.strictObject({
|
|
145
|
+
...sharedOptions(OPENROUTER_API_KEY_ENV),
|
|
146
|
+
model: z.string().min(1),
|
|
147
|
+
reasoning: reasoningOption,
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
export type AskOpenRouterAdapter = AdapterDescriptor<
|
|
151
|
+
"openrouter",
|
|
152
|
+
AskOpenRouterOptions
|
|
153
|
+
>;
|
|
154
|
+
|
|
155
|
+
export const openrouterAdapterSchema = adapterDescriptorSchema(
|
|
156
|
+
"openrouter",
|
|
157
|
+
openrouterOptionsSchema
|
|
158
|
+
);
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Route Ask AI through OpenRouter. Reads `OPENROUTER_API_KEY` and needs
|
|
162
|
+
* `@openrouter/ai-sdk-provider` installed in the project.
|
|
163
|
+
*/
|
|
164
|
+
export const openrouter = (
|
|
165
|
+
options: AskOpenRouterOptions
|
|
166
|
+
): AskOpenRouterAdapter => ({
|
|
167
|
+
kind: "openrouter",
|
|
168
|
+
options,
|
|
169
|
+
requiredSecrets: [options.apiKeyEnv ?? OPENROUTER_API_KEY_ENV],
|
|
170
|
+
runtimeDeps: ["@openrouter/ai-sdk-provider"],
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
// ---------------------------------------------------------------------------
|
|
174
|
+
// llmgateway()
|
|
175
|
+
// ---------------------------------------------------------------------------
|
|
176
|
+
|
|
177
|
+
const LLMGATEWAY_API_KEY_ENV = "LLMGATEWAY_API_KEY";
|
|
178
|
+
|
|
179
|
+
/** Options for {@link llmgateway}. */
|
|
180
|
+
export interface AskLlmGatewayOptions extends AskAdapterOptions {
|
|
181
|
+
/** Overrides the preset endpoint (`https://api.llmgateway.io/v1`). */
|
|
37
182
|
baseUrl?: string;
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
183
|
+
/** The model id LLMGateway serves. */
|
|
184
|
+
model: string;
|
|
185
|
+
/**
|
|
186
|
+
* How much the model reasons before answering, sent in the request as
|
|
187
|
+
* `reasoning_effort`. Omitted keeps the model's default.
|
|
188
|
+
*/
|
|
189
|
+
reasoning?: AskReasoning;
|
|
41
190
|
}
|
|
42
191
|
|
|
192
|
+
const llmgatewayOptionsSchema = z.strictObject({
|
|
193
|
+
...sharedOptions(LLMGATEWAY_API_KEY_ENV),
|
|
194
|
+
baseUrl: z.url().default("https://api.llmgateway.io/v1"),
|
|
195
|
+
model: z.string().min(1),
|
|
196
|
+
reasoning: reasoningOption,
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
export type AskLlmGatewayAdapter = AdapterDescriptor<
|
|
200
|
+
"llmgateway",
|
|
201
|
+
AskLlmGatewayOptions
|
|
202
|
+
>;
|
|
203
|
+
|
|
204
|
+
export const llmgatewayAdapterSchema = adapterDescriptorSchema(
|
|
205
|
+
"llmgateway",
|
|
206
|
+
llmgatewayOptionsSchema
|
|
207
|
+
);
|
|
208
|
+
|
|
43
209
|
/**
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
* endpoints with no dedicated provider, so they reuse `@ai-sdk/openai-compatible`.
|
|
210
|
+
* Route Ask AI through LLMGateway's OpenAI-compatible endpoint. Reads
|
|
211
|
+
* `LLMGATEWAY_API_KEY` and needs `@ai-sdk/openai-compatible` installed.
|
|
47
212
|
*/
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
213
|
+
export const llmgateway = (
|
|
214
|
+
options: AskLlmGatewayOptions
|
|
215
|
+
): AskLlmGatewayAdapter => ({
|
|
216
|
+
kind: "llmgateway",
|
|
217
|
+
options,
|
|
218
|
+
requiredSecrets: [options.apiKeyEnv ?? LLMGATEWAY_API_KEY_ENV],
|
|
219
|
+
runtimeDeps: [OPENAI_COMPATIBLE_DEP],
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
// ---------------------------------------------------------------------------
|
|
223
|
+
// inkeep()
|
|
224
|
+
// ---------------------------------------------------------------------------
|
|
225
|
+
|
|
226
|
+
const INKEEP_API_KEY_ENV = "INKEEP_API_KEY";
|
|
52
227
|
|
|
53
228
|
/**
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
* (the generic `openai-compatible`).
|
|
229
|
+
* Options for {@link inkeep}. No `reasoning`: Inkeep runs its own QA pipeline
|
|
230
|
+
* behind an OpenAI-compatible endpoint with no reasoning control.
|
|
57
231
|
*/
|
|
58
|
-
interface
|
|
59
|
-
|
|
232
|
+
export interface AskInkeepOptions extends AskAdapterOptions {
|
|
233
|
+
/** Overrides the preset endpoint (`https://api.inkeep.com/v1`). */
|
|
234
|
+
baseUrl?: string;
|
|
235
|
+
/** The Inkeep QA model id. */
|
|
236
|
+
model: string;
|
|
60
237
|
}
|
|
61
238
|
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
239
|
+
const inkeepOptionsSchema = z.strictObject({
|
|
240
|
+
...sharedOptions(INKEEP_API_KEY_ENV),
|
|
241
|
+
baseUrl: z.url().default("https://api.inkeep.com/v1"),
|
|
242
|
+
model: z.string().min(1),
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
export type AskInkeepAdapter = AdapterDescriptor<"inkeep", AskInkeepOptions>;
|
|
246
|
+
|
|
247
|
+
export const inkeepAdapterSchema = adapterDescriptorSchema(
|
|
248
|
+
"inkeep",
|
|
249
|
+
inkeepOptionsSchema
|
|
250
|
+
);
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Answer with Inkeep, which retrieves from the content indexed in its own
|
|
254
|
+
* dashboard, so Blume leaves it ungrounded and it takes no `reasoning`.
|
|
255
|
+
* Reads `INKEEP_API_KEY` and needs `@ai-sdk/openai-compatible` installed.
|
|
256
|
+
*/
|
|
257
|
+
export const inkeep = (options: AskInkeepOptions): AskInkeepAdapter => ({
|
|
258
|
+
kind: "inkeep",
|
|
259
|
+
options,
|
|
260
|
+
requiredSecrets: [options.apiKeyEnv ?? INKEEP_API_KEY_ENV],
|
|
261
|
+
runtimeDeps: [OPENAI_COMPATIBLE_DEP],
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
// ---------------------------------------------------------------------------
|
|
265
|
+
// openaiCompatible()
|
|
266
|
+
// ---------------------------------------------------------------------------
|
|
267
|
+
|
|
268
|
+
/** Options for {@link openaiCompatible}. */
|
|
269
|
+
export interface AskOpenAICompatibleOptions extends AskAdapterOptions {
|
|
270
|
+
/** Name of the env var holding the endpoint's API key. */
|
|
271
|
+
apiKeyEnv: string;
|
|
272
|
+
/** The endpoint's base URL (`https://my-gateway.example.com/v1`). */
|
|
273
|
+
baseUrl: string;
|
|
274
|
+
/** The model id the endpoint serves. */
|
|
275
|
+
model: string;
|
|
276
|
+
/** The provider name the AI SDK reports. Defaults to `openai-compatible`. */
|
|
277
|
+
name?: string;
|
|
278
|
+
/**
|
|
279
|
+
* How much the model reasons before answering, sent in the request as
|
|
280
|
+
* `reasoning_effort`, so the endpoint has to accept that parameter.
|
|
281
|
+
* Omitted keeps the model's default.
|
|
282
|
+
*/
|
|
283
|
+
reasoning?: AskReasoning;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
const openaiCompatibleOptionsSchema = z.strictObject({
|
|
287
|
+
...sharedOptions("API_KEY"),
|
|
288
|
+
// A generic endpoint has no preset, so the caller names the key env var.
|
|
289
|
+
apiKeyEnv: z.string().min(1),
|
|
290
|
+
baseUrl: z.url(),
|
|
291
|
+
model: z.string().min(1),
|
|
292
|
+
name: z.string().min(1).default("openai-compatible"),
|
|
293
|
+
reasoning: reasoningOption,
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
export type AskOpenAICompatibleAdapter = AdapterDescriptor<
|
|
297
|
+
"openai-compatible",
|
|
298
|
+
AskOpenAICompatibleOptions
|
|
299
|
+
>;
|
|
300
|
+
|
|
301
|
+
export const openaiCompatibleAdapterSchema = adapterDescriptorSchema(
|
|
302
|
+
"openai-compatible",
|
|
303
|
+
openaiCompatibleOptionsSchema
|
|
304
|
+
);
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Route Ask AI through any OpenAI-compatible endpoint: supply its `baseUrl`,
|
|
308
|
+
* the `model` it serves, and the env var holding its key. Needs
|
|
309
|
+
* `@ai-sdk/openai-compatible` installed.
|
|
310
|
+
*/
|
|
311
|
+
export const openaiCompatible = (
|
|
312
|
+
options: AskOpenAICompatibleOptions
|
|
313
|
+
): AskOpenAICompatibleAdapter => ({
|
|
314
|
+
kind: "openai-compatible",
|
|
315
|
+
options,
|
|
316
|
+
requiredSecrets: [options.apiKeyEnv],
|
|
317
|
+
runtimeDeps: [OPENAI_COMPATIBLE_DEP],
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
// ---------------------------------------------------------------------------
|
|
321
|
+
// The `ai.ask.provider` schema
|
|
322
|
+
// ---------------------------------------------------------------------------
|
|
323
|
+
|
|
324
|
+
/** Which backend answers Ask AI: the value of `gateway()`, `openrouter()`, … */
|
|
325
|
+
export type AskAdapter =
|
|
326
|
+
| AskGatewayAdapter
|
|
327
|
+
| AskOpenRouterAdapter
|
|
328
|
+
| AskLlmGatewayAdapter
|
|
329
|
+
| AskInkeepAdapter
|
|
330
|
+
| AskOpenAICompatibleAdapter;
|
|
331
|
+
|
|
332
|
+
// ---------------------------------------------------------------------------
|
|
333
|
+
// Blume 1 hints
|
|
334
|
+
// ---------------------------------------------------------------------------
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* The 1.x `ai.ask.provider` names — also the adapters' `kind`s — each with the
|
|
338
|
+
* `blume/ai` factory that replaced it.
|
|
339
|
+
*/
|
|
340
|
+
const FACTORY_BY_PROVIDER = new Map([
|
|
341
|
+
["gateway", "gateway"],
|
|
342
|
+
["inkeep", "inkeep"],
|
|
343
|
+
["llmgateway", "llmgateway"],
|
|
344
|
+
["openai-compatible", "openaiCompatible"],
|
|
345
|
+
["openrouter", "openrouter"],
|
|
346
|
+
]);
|
|
347
|
+
|
|
348
|
+
/** The 1.x flat `ai.ask` fields: each is now an option of the provider adapter. */
|
|
349
|
+
const MOVED_TO_PROVIDER: ReadonlySet<string> = new Set([
|
|
350
|
+
"apiKeyEnv",
|
|
351
|
+
"baseUrl",
|
|
352
|
+
"headers",
|
|
353
|
+
"model",
|
|
354
|
+
"reasoning",
|
|
355
|
+
]);
|
|
356
|
+
|
|
357
|
+
/** The provider an `ai.ask` object names: a 1.x string or a descriptor's `kind`. */
|
|
358
|
+
const askProviderNameProbe = z.looseObject({
|
|
359
|
+
provider: z.union([
|
|
360
|
+
z.string(),
|
|
361
|
+
z.looseObject({ kind: z.string() }).transform(({ kind }) => kind),
|
|
362
|
+
]),
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
/** The factory a failing `ai.ask` object's provider names, or the gateway. */
|
|
366
|
+
const providerFactory = (issue: z.core.$ZodRawIssue): string => {
|
|
367
|
+
const probe = askProviderNameProbe.safeParse(issue.input);
|
|
368
|
+
return (
|
|
369
|
+
(probe.success && FACTORY_BY_PROVIDER.get(probe.data.provider)) || "gateway"
|
|
370
|
+
);
|
|
371
|
+
};
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* Error params for `ai.ask`: a 1.x flat provider field (`model`, `apiKeyEnv`,
|
|
375
|
+
* `baseUrl`, `headers`, `reasoning`) names the adapter call it moves into —
|
|
376
|
+
* the one the object's `provider` picks, 1.x string or descriptor — instead
|
|
377
|
+
* of Zod's bare "Unrecognized key"; any other unknown key keeps its wording.
|
|
378
|
+
*/
|
|
379
|
+
export const askMovedFieldsHint = {
|
|
380
|
+
error: (issue: z.core.$ZodRawIssue): string | undefined => {
|
|
381
|
+
if (issue.code !== "unrecognized_keys") {
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
384
|
+
const moved = issue.keys.filter((key) => MOVED_TO_PROVIDER.has(key));
|
|
385
|
+
if (moved.length === 0) {
|
|
386
|
+
return;
|
|
387
|
+
}
|
|
388
|
+
const fields = moved.map((key) => `ai.ask.${key}`).join(", ");
|
|
389
|
+
const hint = `${fields} moved into the provider adapter: \`provider: ${providerFactory(issue)}({ ${moved.join(", ")} })\`, imported from "blume/ai".`;
|
|
390
|
+
const others = issue.keys.filter((key) => !MOVED_TO_PROVIDER.has(key));
|
|
391
|
+
return others.length > 0
|
|
392
|
+
? `${hint} ${unrecognizedKeysMessage(others)}`
|
|
393
|
+
: hint;
|
|
82
394
|
},
|
|
83
395
|
};
|
|
84
396
|
|
|
85
|
-
|
|
397
|
+
/** A value that is a 1.x provider name, for the `ai.ask.provider` hint. */
|
|
398
|
+
const providerNameProbe = z.string();
|
|
86
399
|
|
|
87
400
|
/**
|
|
88
|
-
* The
|
|
89
|
-
*
|
|
90
|
-
* to send.
|
|
401
|
+
* The message for an `ai.ask.provider` that isn't a descriptor: a 1.x
|
|
402
|
+
* provider name names the factory that replaced it; anything else lists them.
|
|
91
403
|
*/
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
404
|
+
const providerNotAdapterMessage = (issue: z.core.$ZodRawIssue): string => {
|
|
405
|
+
const name = providerNameProbe.safeParse(issue.input);
|
|
406
|
+
const factory = name.success ? FACTORY_BY_PROVIDER.get(name.data) : undefined;
|
|
407
|
+
return factory
|
|
408
|
+
? `ai.ask.provider takes an adapter from "blume/ai", not a provider name: \`provider: ${factory}({ model })\`. The 1.x model, apiKeyEnv, baseUrl, headers, and reasoning fields move into the call.`
|
|
409
|
+
: 'ai.ask.provider takes an adapter from "blume/ai": gateway(), openrouter(), llmgateway(), inkeep(), or openaiCompatible().';
|
|
410
|
+
};
|
|
96
411
|
|
|
97
|
-
/**
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
412
|
+
/**
|
|
413
|
+
* `ai.ask.provider`: the descriptor an adapter factory returned, validated
|
|
414
|
+
* against that adapter's own option schema. A value that isn't a descriptor
|
|
415
|
+
* at all (a 1.x provider name) names the factory that replaced it.
|
|
416
|
+
*/
|
|
417
|
+
export const askAdapterSchema = z.discriminatedUnion(
|
|
418
|
+
"kind",
|
|
419
|
+
[
|
|
420
|
+
gatewayAdapterSchema,
|
|
421
|
+
openrouterAdapterSchema,
|
|
422
|
+
llmgatewayAdapterSchema,
|
|
423
|
+
inkeepAdapterSchema,
|
|
424
|
+
openaiCompatibleAdapterSchema,
|
|
425
|
+
],
|
|
426
|
+
{
|
|
427
|
+
// A non-object (a 1.x provider name) fails before any discriminator is
|
|
428
|
+
// read — `invalid_type` at runtime, though Zod types the union's own
|
|
429
|
+
// issues as `invalid_union` only; a bad `kind` keeps Zod's message.
|
|
430
|
+
error: (issue) =>
|
|
431
|
+
issue.code === "invalid_union"
|
|
432
|
+
? undefined
|
|
433
|
+
: providerNotAdapterMessage(issue),
|
|
104
434
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
435
|
+
);
|
|
436
|
+
|
|
437
|
+
/** A resolved (post-defaults) `ai.ask.provider` descriptor. */
|
|
438
|
+
export type AskAdapterConfig = z.output<typeof askAdapterSchema>;
|
|
439
|
+
export type AskAdapterKind = AskAdapterConfig["kind"];
|
|
440
|
+
|
|
441
|
+
/** The provider when `ai.ask.provider` is unset: the gateway with its defaults. */
|
|
442
|
+
export const DEFAULT_ASK_PROVIDER: AskAdapter = gateway();
|
|
443
|
+
|
|
444
|
+
// ---------------------------------------------------------------------------
|
|
445
|
+
// Resolved backend
|
|
446
|
+
// ---------------------------------------------------------------------------
|
|
447
|
+
|
|
448
|
+
/** The route fragments an adapter contributes to `askEndpointTemplate`. */
|
|
449
|
+
export interface AskBackendTemplate {
|
|
450
|
+
/**
|
|
451
|
+
* Extra `streamText` fields as `key: value` source lines: the adapter's
|
|
452
|
+
* reasoning mapping (when it is a call option) and `providerOptions`.
|
|
453
|
+
*/
|
|
454
|
+
fields: string[];
|
|
455
|
+
/** Import lines after the shared `astro` and `astro:env/server` ones. */
|
|
456
|
+
imports: string[];
|
|
457
|
+
/**
|
|
458
|
+
* The up-front credential guard: a statement that returns a 503, since the
|
|
459
|
+
* endpoint exists but can't answer until the deployment sets its key.
|
|
460
|
+
*/
|
|
461
|
+
keyCheck: string;
|
|
462
|
+
/** The `model:` expression passed to `streamText`. */
|
|
463
|
+
model: string;
|
|
464
|
+
/** Module-level provider setup (the provider factory call). */
|
|
465
|
+
setup: string;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
/**
|
|
469
|
+
* What the endpoint template and the diagnostics read from an adapter beyond
|
|
470
|
+
* the descriptor itself (`kind`, `requiredSecrets`, `runtimeDeps` travel on
|
|
471
|
+
* the descriptor; `generate`, `eject`, the required-secrets check, and the
|
|
472
|
+
* runtime-dependency manifest read those directly).
|
|
473
|
+
*/
|
|
474
|
+
export interface AskBackend {
|
|
475
|
+
/** Whether Blume grounds answers in the docs (Inkeep retrieves itself). */
|
|
476
|
+
grounded: boolean;
|
|
477
|
+
kind: AskAdapterKind;
|
|
478
|
+
/** Human-readable adapter name for diagnostics ("AI Gateway"). */
|
|
479
|
+
label: string;
|
|
480
|
+
/** Appended to the missing-secret warning (an alternative credential, say). */
|
|
481
|
+
secretNote?: string;
|
|
482
|
+
template: AskBackendTemplate;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
const secretExpr = (env: string): string => `getSecret(${JSON.stringify(env)})`;
|
|
486
|
+
|
|
487
|
+
/**
|
|
488
|
+
* The `headers` line of a provider factory call. Every provider Blume
|
|
489
|
+
* generates against takes the same option; the OpenAI-compatible provider
|
|
490
|
+
* applies it after the `Authorization` header it derives from the API key, so
|
|
491
|
+
* a custom header can't displace auth. An empty map is dropped so the route
|
|
492
|
+
* only carries `headers` when there is something to send.
|
|
493
|
+
*/
|
|
494
|
+
const headersLine = (headers?: Record<string, string>): string =>
|
|
495
|
+
headers && Object.keys(headers).length > 0
|
|
496
|
+
? `\n headers: ${JSON.stringify(headers)},`
|
|
497
|
+
: "";
|
|
498
|
+
|
|
499
|
+
/** Refuse a request up front when the adapter's key env var is unset. */
|
|
500
|
+
const keyCheck = (env: string): string => ` if (!${secretExpr(env)}) {
|
|
501
|
+
return new Response(
|
|
502
|
+
${JSON.stringify(`Ask AI is not configured: set ${env}.`)},
|
|
503
|
+
{ status: 503 }
|
|
504
|
+
);
|
|
505
|
+
}`;
|
|
506
|
+
|
|
507
|
+
/**
|
|
508
|
+
* The `streamText` fields shared by the adapters that take `reasoning` as the
|
|
509
|
+
* AI SDK's top-level call option, plus the verbatim `providerOptions`.
|
|
510
|
+
*/
|
|
511
|
+
const callFields = (options: {
|
|
512
|
+
providerOptions?: z.output<typeof providerOptionsSchema>;
|
|
513
|
+
reasoning?: AskReasoning;
|
|
514
|
+
}): string[] => {
|
|
515
|
+
const fields: string[] = [];
|
|
516
|
+
if (options.reasoning) {
|
|
517
|
+
fields.push(`reasoning: ${JSON.stringify(options.reasoning)}`);
|
|
518
|
+
}
|
|
519
|
+
if (options.providerOptions) {
|
|
520
|
+
fields.push(`providerOptions: ${JSON.stringify(options.providerOptions)}`);
|
|
109
521
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
522
|
+
return fields;
|
|
523
|
+
};
|
|
524
|
+
|
|
525
|
+
const gatewayBackend = (
|
|
526
|
+
options: z.output<typeof gatewayOptionsSchema>
|
|
527
|
+
): AskBackend => ({
|
|
528
|
+
grounded: true,
|
|
529
|
+
kind: "gateway",
|
|
530
|
+
label: "AI Gateway",
|
|
531
|
+
secretNote: "on Vercel the gateway can also authenticate via OIDC",
|
|
532
|
+
template: {
|
|
533
|
+
// The gateway maps the AI SDK's top-level `reasoning` to the model's own
|
|
534
|
+
// control (OpenAI's `reasoning_effort`, say).
|
|
535
|
+
fields: callFields(options),
|
|
536
|
+
// The gateway provider reads the key (or Vercel's OIDC token) from the
|
|
537
|
+
// environment itself; passing the key explicitly lets a binding-backed
|
|
538
|
+
// secret store reach it too.
|
|
539
|
+
imports: [
|
|
540
|
+
'import { createGateway, createTextStreamResponse, streamText, toTextStream } from "ai";',
|
|
541
|
+
],
|
|
542
|
+
keyCheck: ` // The AI Gateway authenticates with an API key or Vercel's OIDC token.
|
|
543
|
+
if (!(${secretExpr(options.apiKeyEnv)} || getSecret("VERCEL_OIDC_TOKEN"))) {
|
|
544
|
+
return new Response(
|
|
545
|
+
${JSON.stringify(`Ask AI is not configured: set ${options.apiKeyEnv} (or deploy on Vercel with OIDC).`)},
|
|
546
|
+
{ status: 503 }
|
|
547
|
+
);
|
|
548
|
+
}`,
|
|
549
|
+
model: `gateway(${JSON.stringify(options.model)})`,
|
|
550
|
+
setup: `\nconst gateway = createGateway({
|
|
551
|
+
apiKey: ${secretExpr(options.apiKeyEnv)},${headersLine(options.headers)}
|
|
552
|
+
});\n`,
|
|
553
|
+
},
|
|
554
|
+
});
|
|
555
|
+
|
|
556
|
+
const openrouterBackend = (
|
|
557
|
+
options: z.output<typeof openrouterOptionsSchema>
|
|
558
|
+
): AskBackend => {
|
|
559
|
+
// The OpenRouter provider ignores the AI SDK's top-level `reasoning` call
|
|
560
|
+
// option and only reads its own model-level setting, so the level rides on
|
|
561
|
+
// the model as `reasoning.effort` and nowhere else.
|
|
562
|
+
const settings = options.reasoning
|
|
563
|
+
? `, { reasoning: { effort: ${JSON.stringify(options.reasoning)} } }`
|
|
564
|
+
: "";
|
|
113
565
|
return {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
566
|
+
grounded: true,
|
|
567
|
+
kind: "openrouter",
|
|
568
|
+
label: "OpenRouter",
|
|
569
|
+
template: {
|
|
570
|
+
fields: callFields({ providerOptions: options.providerOptions }),
|
|
571
|
+
imports: [
|
|
572
|
+
'import { createTextStreamResponse, streamText, toTextStream } from "ai";',
|
|
573
|
+
'import { createOpenRouter } from "@openrouter/ai-sdk-provider";',
|
|
574
|
+
],
|
|
575
|
+
keyCheck: keyCheck(options.apiKeyEnv),
|
|
576
|
+
model: `openrouter(${JSON.stringify(options.model)}${settings})`,
|
|
577
|
+
setup: `\nconst openrouter = createOpenRouter({
|
|
578
|
+
apiKey: ${secretExpr(options.apiKeyEnv)},${headersLine(options.headers)}
|
|
579
|
+
});\n`,
|
|
580
|
+
},
|
|
120
581
|
};
|
|
121
582
|
};
|
|
122
583
|
|
|
123
584
|
/**
|
|
124
|
-
* The
|
|
125
|
-
*
|
|
126
|
-
*
|
|
585
|
+
* The backend shared by the adapters that stream through the AI SDK's
|
|
586
|
+
* OpenAI-compatible provider, which sends the top-level `reasoning` call
|
|
587
|
+
* option as `reasoning_effort`.
|
|
127
588
|
*/
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
589
|
+
const openaiCompatibleBackend = (
|
|
590
|
+
kind: AskAdapterKind,
|
|
591
|
+
label: string,
|
|
592
|
+
grounded: boolean,
|
|
593
|
+
options: {
|
|
594
|
+
apiKeyEnv: string;
|
|
595
|
+
baseUrl: string;
|
|
596
|
+
headers?: Record<string, string>;
|
|
597
|
+
model: string;
|
|
598
|
+
name: string;
|
|
599
|
+
providerOptions?: z.output<typeof providerOptionsSchema>;
|
|
600
|
+
reasoning?: AskReasoning;
|
|
601
|
+
}
|
|
602
|
+
): AskBackend => ({
|
|
603
|
+
grounded,
|
|
604
|
+
kind,
|
|
605
|
+
label,
|
|
606
|
+
template: {
|
|
607
|
+
fields: callFields(options),
|
|
608
|
+
imports: [
|
|
609
|
+
'import { createTextStreamResponse, streamText, toTextStream } from "ai";',
|
|
610
|
+
'import { createOpenAICompatible } from "@ai-sdk/openai-compatible";',
|
|
611
|
+
],
|
|
612
|
+
keyCheck: keyCheck(options.apiKeyEnv),
|
|
613
|
+
model: `provider(${JSON.stringify(options.model)})`,
|
|
614
|
+
// `headers` sits between the key and the name so the API key's
|
|
615
|
+
// `Authorization` header is applied first.
|
|
616
|
+
setup: `\nconst provider = createOpenAICompatible({
|
|
617
|
+
apiKey: ${secretExpr(options.apiKeyEnv)},
|
|
618
|
+
baseURL: ${JSON.stringify(options.baseUrl)},${headersLine(options.headers)}
|
|
619
|
+
name: ${JSON.stringify(options.name)},
|
|
620
|
+
});\n`,
|
|
621
|
+
},
|
|
622
|
+
});
|
|
623
|
+
|
|
624
|
+
/** Resolve a parsed `ai.ask.provider` descriptor into its backend. */
|
|
625
|
+
export const resolveAskBackend = (
|
|
626
|
+
provider: AskAdapterConfig = askAdapterSchema.parse(DEFAULT_ASK_PROVIDER)
|
|
627
|
+
): AskBackend => {
|
|
628
|
+
switch (provider.kind) {
|
|
629
|
+
case "gateway": {
|
|
630
|
+
return gatewayBackend(provider.options);
|
|
631
|
+
}
|
|
632
|
+
case "openrouter": {
|
|
633
|
+
return openrouterBackend(provider.options);
|
|
634
|
+
}
|
|
635
|
+
case "llmgateway": {
|
|
636
|
+
return openaiCompatibleBackend("llmgateway", "LLMGateway", true, {
|
|
637
|
+
...provider.options,
|
|
638
|
+
name: "llmgateway",
|
|
639
|
+
});
|
|
640
|
+
}
|
|
641
|
+
case "inkeep": {
|
|
642
|
+
// Inkeep answers from the content indexed in its dashboard, so injected
|
|
643
|
+
// excerpts would conflict with its own retrieval.
|
|
644
|
+
return openaiCompatibleBackend("inkeep", "Inkeep", false, {
|
|
645
|
+
...provider.options,
|
|
646
|
+
name: "inkeep",
|
|
647
|
+
});
|
|
648
|
+
}
|
|
649
|
+
default: {
|
|
650
|
+
return openaiCompatibleBackend(
|
|
651
|
+
"openai-compatible",
|
|
652
|
+
"OpenAI-compatible",
|
|
653
|
+
true,
|
|
654
|
+
provider.options
|
|
655
|
+
);
|
|
656
|
+
}
|
|
132
657
|
}
|
|
133
|
-
return ASK_PRESETS[provider]?.runtimeDep ?? OPENAI_COMPATIBLE_DEP;
|
|
134
658
|
};
|