blume 2.0.0 → 2.0.2
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 +1 -1
- package/CHANGELOG.md +110 -0
- package/README.md +2 -2
- package/dist/cli/{chunk-f2972sbt.js → chunk-00gs3wqs.js} +1 -1
- package/dist/cli/{chunk-fa25z98p.js → chunk-273ygyr4.js} +4 -3
- package/dist/cli/chunk-273ygyr4.js.map +11 -0
- package/dist/cli/{chunk-pat2zzwc.js → chunk-3yce002v.js} +21 -8
- package/dist/cli/{chunk-pat2zzwc.js.map → chunk-3yce002v.js.map} +4 -4
- package/dist/cli/{chunk-d1tadaw7.js → chunk-4e9b9ra6.js} +17 -7
- package/dist/cli/chunk-4e9b9ra6.js.map +10 -0
- package/dist/cli/{chunk-zg2gtj10.js → chunk-5r8g91qn.js} +352 -676
- package/dist/cli/chunk-5r8g91qn.js.map +34 -0
- package/dist/cli/{chunk-11j0384y.js → chunk-6dtt0zfn.js} +14 -14
- package/dist/cli/{chunk-11j0384y.js.map → chunk-6dtt0zfn.js.map} +3 -3
- package/dist/cli/{chunk-bw22s759.js → chunk-6k4ftwze.js} +38 -19
- package/dist/cli/{chunk-bw22s759.js.map → chunk-6k4ftwze.js.map} +4 -4
- package/dist/cli/{chunk-sqn5t4q0.js → chunk-7mbqtmgb.js} +16 -7
- package/dist/cli/chunk-7mbqtmgb.js.map +10 -0
- package/dist/cli/{chunk-79njf86q.js → chunk-7vtckvaw.js} +21 -19
- package/dist/cli/chunk-7vtckvaw.js.map +11 -0
- package/dist/cli/{chunk-fh5hj5jt.js → chunk-8g8ytmgx.js} +17 -18
- package/dist/cli/{chunk-fh5hj5jt.js.map → chunk-8g8ytmgx.js.map} +2 -2
- package/dist/cli/{chunk-1w8dp3qb.js → chunk-91ws1n6j.js} +18 -15
- package/dist/cli/chunk-91ws1n6j.js.map +10 -0
- package/dist/cli/{chunk-7ez8ny0t.js → chunk-bbnwccaz.js} +2 -2
- package/dist/cli/{chunk-5a2z0198.js → chunk-bfwp9vp6.js} +18 -10
- package/dist/cli/chunk-bfwp9vp6.js.map +10 -0
- package/dist/cli/{chunk-ernrthtr.js → chunk-d1v5rhy0.js} +14 -15
- package/dist/cli/{chunk-ernrthtr.js.map → chunk-d1v5rhy0.js.map} +2 -2
- package/dist/cli/{chunk-a9kptbw5.js → chunk-ddndchfr.js} +21 -6
- package/dist/cli/chunk-ddndchfr.js.map +14 -0
- package/dist/cli/{chunk-zxccj738.js → chunk-esh98wmb.js} +1 -1
- package/dist/cli/{chunk-88cpgt6h.js → chunk-fsmrqk8a.js} +1 -1
- package/dist/cli/{chunk-b5aj94ah.js → chunk-g698a744.js} +5 -5
- package/dist/cli/{chunk-jts8mvcz.js → chunk-gs7r695n.js} +9 -3
- package/dist/cli/{chunk-jts8mvcz.js.map → chunk-gs7r695n.js.map} +3 -3
- package/dist/cli/{chunk-41za066z.js → chunk-h2ez8dzb.js} +4 -4
- package/dist/cli/{chunk-by2290sx.js → chunk-h7k3nq3v.js} +2 -2
- package/dist/cli/{chunk-j8mw0za6.js → chunk-hqp2ajnh.js} +252 -123
- package/dist/cli/chunk-hqp2ajnh.js.map +35 -0
- package/dist/cli/{chunk-mnqj32sj.js → chunk-hr8ne106.js} +119 -50
- package/dist/cli/chunk-hr8ne106.js.map +13 -0
- package/dist/cli/{chunk-mwt1k8n7.js → chunk-j85scx15.js} +74 -30
- package/dist/cli/chunk-j85scx15.js.map +10 -0
- package/dist/cli/{chunk-z01ze5c1.js → chunk-k7pj68a8.js} +63 -22
- package/dist/cli/chunk-k7pj68a8.js.map +11 -0
- package/dist/cli/{chunk-2q1dwty4.js → chunk-mqc662a6.js} +8 -8
- package/dist/cli/{chunk-2q1dwty4.js.map → chunk-mqc662a6.js.map} +4 -4
- package/dist/cli/{chunk-y3e45rc8.js → chunk-n1yg3tj3.js} +4 -4
- package/dist/cli/{chunk-bctazmbk.js → chunk-nfcyttvj.js} +17 -6
- package/dist/cli/chunk-nfcyttvj.js.map +10 -0
- package/dist/cli/{chunk-6k8vp3ta.js → chunk-pbg5a4s3.js} +60 -28
- package/dist/cli/chunk-pbg5a4s3.js.map +19 -0
- package/dist/cli/{chunk-d80hr03s.js → chunk-ppzjqwx2.js} +24 -17
- package/dist/cli/{chunk-d80hr03s.js.map → chunk-ppzjqwx2.js.map} +4 -4
- package/dist/cli/{chunk-beat36xx.js → chunk-qkb5a8sa.js} +25 -10
- package/dist/cli/chunk-qkb5a8sa.js.map +10 -0
- package/dist/cli/{chunk-bnbmcwfb.js → chunk-sqw4ekg1.js} +5 -5
- package/dist/cli/{chunk-bnbmcwfb.js.map → chunk-sqw4ekg1.js.map} +3 -3
- package/dist/cli/{chunk-xaz13gwg.js → chunk-v6ya5kcb.js} +3268 -1150
- package/dist/cli/chunk-v6ya5kcb.js.map +189 -0
- package/dist/cli/{chunk-tzne8qfq.js → chunk-w4bxdvsa.js} +18 -15
- package/dist/cli/chunk-w4bxdvsa.js.map +10 -0
- package/dist/cli/{chunk-f7t03s3g.js → chunk-wdrt2k2v.js} +2 -2
- package/dist/cli/{chunk-z1f5arsg.js → chunk-xh43dwgw.js} +170 -55
- package/dist/cli/chunk-xh43dwgw.js.map +36 -0
- package/dist/cli/{chunk-pnnvybbk.js → chunk-zp79m0ts.js} +5 -5
- package/dist/cli/{chunk-pnnvybbk.js.map → chunk-zp79m0ts.js.map} +2 -2
- package/dist/cli/index.js +160 -35
- package/dist/cli/index.js.map +4 -4
- package/dist/types/ai/agent-readability.d.ts +1 -1
- package/dist/types/ai/agent-surface.d.ts +32 -0
- package/dist/types/ai/api/paths.d.ts +1 -1
- package/dist/types/ai/api-catalog.d.ts +7 -1
- package/dist/types/ai/ask-context.d.ts +14 -7
- package/dist/types/ai/ask.d.ts +43 -43
- package/dist/types/ai/component-markdown.d.ts +4 -4
- package/dist/types/ai/index.d.ts +3 -3
- package/dist/types/ai/openapi-components.d.ts +1 -1
- package/dist/types/ai/relative-links.d.ts +9 -4
- package/dist/types/ai/serializers.d.ts +1 -1
- package/dist/types/ai/static-expression.d.ts +28 -0
- package/dist/types/ai/visibility.d.ts +1 -1
- package/dist/types/analytics/databuddy.d.ts +43 -0
- package/dist/types/analytics/index.d.ts +2 -0
- package/dist/types/analytics/schema.d.ts +14 -0
- package/dist/types/cli/env.d.ts +5 -0
- package/dist/types/cli/init/scaffold.d.ts +19 -3
- package/dist/types/cli/init/starter-spec.d.ts +11 -0
- package/dist/types/core/base-path.d.ts +9 -0
- package/dist/types/core/config-input.d.ts +21 -21
- package/dist/types/core/config.d.ts +5 -5
- package/dist/types/core/data.d.ts +3 -3
- package/dist/types/core/graph.d.ts +2 -0
- package/dist/types/core/i18n-ui.d.ts +37 -8
- package/dist/types/core/i18n.d.ts +7 -1
- package/dist/types/core/links.d.ts +3 -1
- package/dist/types/core/load-module.d.ts +10 -0
- package/dist/types/core/locale-links.d.ts +12 -2
- package/dist/types/core/meta.d.ts +5 -1
- package/dist/types/core/nav-diagnostics.d.ts +10 -0
- package/dist/types/core/navigation.d.ts +38 -0
- package/dist/types/core/ordering-prefix.d.ts +4 -0
- package/dist/types/core/safe-links.d.ts +3 -1
- package/dist/types/core/schema.d.ts +57 -18
- package/dist/types/core/sources/github-releases.d.ts +5 -0
- package/dist/types/core/sources/lower.d.ts +14 -2
- package/dist/types/core/sources/normalize.d.ts +10 -1
- package/dist/types/core/sources/remote.d.ts +11 -1
- package/dist/types/core/sources/resolve.d.ts +12 -0
- package/dist/types/core/sources/types.d.ts +31 -0
- package/dist/types/core/types.d.ts +9 -0
- package/dist/types/core/unrecognized-keys.d.ts +1 -1
- package/dist/types/deploy/adapters/node.d.ts +5 -2
- package/dist/types/deploy/adapters/types.d.ts +7 -0
- package/dist/types/deploy/cloudflare-negotiation.d.ts +3 -2
- package/dist/types/deploy/headers.d.ts +31 -7
- package/dist/types/deploy/node-headers.d.ts +43 -8
- package/dist/types/deploy/platforms/netlify.d.ts +27 -2
- package/dist/types/deploy/platforms/node.d.ts +6 -5
- package/dist/types/deploy/platforms/types.d.ts +7 -0
- package/dist/types/deploy/platforms/vercel.d.ts +3 -2
- package/dist/types/deploy/redirects.d.ts +7 -2
- package/dist/types/deploy/vercel-negotiation.d.ts +3 -2
- package/dist/types/openapi/model.d.ts +20 -6
- package/dist/types/search/documents.d.ts +1 -1
- package/dist/types/search/orama-index.d.ts +1 -1
- package/dist/types/search/sync/algolia.d.ts +3 -1
- package/docs/01-quickstart.mdx +3 -2
- package/docs/02-deployment.mdx +21 -12
- package/docs/03-upgrading.mdx +22 -9
- package/docs/04-migrating.mdx +4 -4
- package/docs/08-faq.mdx +12 -5
- package/docs/advanced/changelog.mdx +1 -1
- package/docs/advanced/custom-pages.mdx +5 -3
- package/docs/advanced/skills.mdx +1 -1
- package/docs/cli/audit.mdx +5 -5
- package/docs/cli/doctor.mdx +4 -4
- package/docs/cli/evals.mdx +9 -9
- package/docs/cli/index.mdx +6 -3
- package/docs/cli/translate.mdx +8 -8
- package/docs/configuration/analytics.mdx +23 -2
- package/docs/configuration/{ask-ai.mdx → assistant.mdx} +20 -20
- package/docs/configuration/customization.mdx +5 -4
- package/docs/configuration/index.mdx +7 -5
- package/docs/configuration/meta.ts +1 -1
- package/docs/configuration/search.mdx +2 -2
- package/docs/content/components.mdx +1 -1
- package/docs/content/frontmatter.mdx +5 -1
- package/docs/content/i18n.mdx +3 -3
- package/docs/content/index.mdx +4 -2
- package/docs/content/islands.mdx +1 -1
- package/docs/content/meta.mdx +5 -3
- package/docs/content/navigation.mdx +29 -4
- package/docs/content/sources.mdx +18 -12
- package/docs/content/versioning.mdx +1 -0
- package/docs/discoverability/agent-discovery.mdx +22 -8
- package/docs/discoverability/index.mdx +3 -3
- package/docs/discoverability/llms-txt.mdx +2 -5
- package/docs/discoverability/markdown.mdx +5 -3
- package/docs/discoverability/mcp.mdx +4 -0
- package/docs/discoverability/metadata.mdx +3 -2
- package/docs/discoverability/open-graph.mdx +6 -4
- package/docs/discoverability/rss.mdx +3 -1
- package/docs/index.mdx +2 -2
- package/docs/references/asyncapi.mdx +1 -1
- package/docs/references/graphql.mdx +2 -2
- package/docs/references/openapi.mdx +3 -3
- package/package.json +1 -1
- package/skills/blume/SKILL.md +5 -5
- package/skills/blume-migrate/SKILL.md +6 -6
- package/skills/blume-migrate/references/docusaurus.md +6 -6
- package/skills/blume-migrate/references/mintlify.md +3 -3
- package/skills/blume-migrate/references/monorepo.md +1 -1
- package/skills/blume-migrate/references/nextra.md +1 -1
- package/skills/blume-migrate/references/starlight.md +5 -5
- package/skills/blume-migrate/scripts/mintlify-codemod.mjs +2 -2
- package/skills/blume-update-docs/references/audit-checklist.md +1 -1
- package/src/ai/agent-readability.ts +4 -4
- package/src/ai/agent-surface.ts +56 -0
- package/src/ai/api/paths.ts +1 -1
- package/src/ai/api/spec.ts +15 -2
- package/src/ai/api-catalog.ts +7 -1
- package/src/ai/ask-context.ts +21 -9
- package/src/ai/ask-data.ts +28 -14
- package/src/ai/ask.ts +84 -71
- package/src/ai/component-markdown.ts +43 -37
- package/src/ai/cors.ts +3 -3
- package/src/ai/index.ts +16 -16
- package/src/ai/link-headers.ts +8 -3
- package/src/ai/llms.ts +4 -3
- package/src/ai/markdown.ts +23 -11
- package/src/ai/mcp/server.ts +78 -7
- package/src/ai/openapi-components.ts +1 -1
- package/src/ai/relative-links.ts +78 -10
- package/src/ai/serializers.ts +1 -1
- package/src/ai/static-expression.ts +416 -0
- package/src/ai/visibility.ts +46 -15
- package/src/analytics/databuddy.ts +67 -0
- package/src/analytics/head.ts +4 -0
- package/src/analytics/index.ts +2 -0
- package/src/analytics/posthog.ts +21 -3
- package/src/analytics/schema.ts +2 -0
- package/src/astro/generate.ts +90 -45
- package/src/astro/module-types.ts +1 -1
- package/src/astro/runtime-deps.ts +6 -6
- package/src/astro/templates.ts +87 -49
- package/src/audit/catalog.ts +2 -2
- package/src/audit/checks/assets.ts +25 -5
- package/src/audit/checks/content.ts +20 -2
- package/src/audit/checks/i18n.ts +46 -8
- package/src/audit/checks/indexability.ts +39 -19
- package/src/audit/checks/links.ts +14 -0
- package/src/audit/checks/llms.ts +6 -3
- package/src/audit/checks/network.ts +3 -1
- package/src/audit/checks/og-image.ts +10 -0
- package/src/audit/checks/robots.ts +6 -1
- package/src/audit/checks/sitemap.ts +56 -31
- package/src/audit/checks/social.ts +21 -2
- package/src/audit/crawl.ts +88 -15
- package/src/audit/report.ts +54 -17
- package/src/audit/run.ts +1 -0
- package/src/audit/types.ts +18 -0
- package/src/audit/url.ts +37 -6
- package/src/blume-modules.d.ts +2 -2
- package/src/cli/build-failure.ts +50 -0
- package/src/cli/commands/audit.ts +8 -1
- package/src/cli/commands/build.ts +19 -5
- package/src/cli/commands/check.ts +2 -0
- package/src/cli/commands/doctor.ts +7 -5
- package/src/cli/commands/eval.ts +4 -10
- package/src/cli/commands/init.ts +15 -5
- package/src/cli/commands/migrate.ts +2 -2
- package/src/cli/commands/preview.ts +15 -0
- package/src/cli/commands/sync.ts +2 -0
- package/src/cli/commands/translate.ts +12 -9
- package/src/cli/commands/upgrade.ts +13 -2
- package/src/cli/eject-scripts.ts +32 -7
- package/src/cli/env.ts +12 -1
- package/src/cli/init/scaffold.ts +117 -11
- package/src/cli/init/starter-spec.ts +235 -0
- package/src/cli/required-secrets.ts +3 -3
- package/src/components/content/AccordionItem.astro +26 -22
- package/src/components/content/Badge.astro +2 -9
- package/src/components/content/Card.astro +2 -2
- package/src/components/content/Component.astro +9 -3
- package/src/components/content/Expandable.astro +5 -1
- package/src/components/content/Frame.astro +2 -7
- package/src/components/content/GithubInfo.astro +12 -2
- package/src/components/content/Prompt.astro +2 -7
- package/src/components/content/Tabs.astro +54 -5
- package/src/components/content/Tile.astro +1 -1
- package/src/components/content/Tooltip.astro +69 -7
- package/src/components/content/Tree.astro +7 -2
- package/src/components/content/TypeTable.astro +10 -5
- package/src/components/content/Update.astro +8 -2
- package/src/components/content/auto-type-table.ts +4 -1
- package/src/components/content/badge-color.ts +17 -0
- package/src/components/content/base-href.ts +18 -3
- package/src/components/content/inline-markdown.ts +27 -7
- package/src/components/copy-feedback.ts +36 -9
- package/src/components/islands/{AskAI.astro → Assistant.astro} +10 -10
- package/src/components/islands/{ask-ai.tsx → assistant.tsx} +39 -25
- package/src/components/islands/hooks.ts +21 -14
- package/src/components/islands/webmcp.ts +12 -8
- package/src/components/layout/Banner.astro +23 -4
- package/src/components/layout/Header.astro +32 -19
- package/src/components/layout/Logo.astro +5 -0
- package/src/components/layout/NavSelector.astro +6 -1
- package/src/components/layout/NavTabMenu.astro +133 -0
- package/src/components/layout/NavTree.astro +15 -6
- package/src/components/layout/NavTreeCache.astro +5 -2
- package/src/components/layout/NavTreeScript.astro +45 -5
- package/src/components/layout/PageLayout.astro +28 -14
- package/src/components/layout/Pagination.astro +7 -7
- package/src/components/layout/ReferenceLayout.astro +5 -2
- package/src/components/layout/RootLayout.astro +27 -14
- package/src/components/layout/Search.astro +18 -14
- package/src/components/layout/analytics-client.ts +3 -1
- package/src/components/layout/drawer-inert.ts +1 -1
- package/src/components/openapi/GraphqlType.astro +11 -3
- package/src/components/openapi/MessageComposer.astro +1 -1
- package/src/components/openapi/Operation.astro +21 -5
- package/src/components/openapi/PanelTabs.astro +4 -1
- package/src/components/openapi/Playground.astro +8 -2
- package/src/components/openapi/RequestPanel.astro +9 -5
- package/src/components/openapi/SchemaProperty.astro +11 -33
- package/src/components/openapi/SchemaTable.astro +27 -52
- package/src/components/openapi/description.ts +2 -2
- package/src/components/openapi/helpers.ts +90 -12
- package/src/components/openapi/message-composer.ts +8 -0
- package/src/components/openapi/message-model.ts +12 -2
- package/src/components/openapi/message.ts +4 -1
- package/src/components/openapi/operation-model.ts +40 -8
- package/src/components/openapi/panel.ts +29 -5
- package/src/components/openapi/playground-client.ts +37 -7
- package/src/components/openapi/playground-schema.ts +25 -6
- package/src/components/openapi/request.ts +2 -0
- package/src/components/openapi/schema-tree.ts +203 -0
- package/src/components/openapi/snippets.ts +30 -15
- package/src/components/openapi/validate-json.ts +1 -1
- package/src/core/base-path.ts +15 -0
- package/src/core/code-fences.ts +1 -1
- package/src/core/config-input.ts +23 -23
- package/src/core/config.ts +21 -7
- package/src/core/data.ts +3 -3
- package/src/core/diagnostics.ts +217 -30
- package/src/core/graph.ts +120 -11
- package/src/core/i18n-ui.ts +74 -11
- package/src/core/i18n.ts +13 -2
- package/src/core/links.ts +7 -4
- package/src/core/load-module.ts +20 -0
- package/src/core/locale-links.ts +17 -17
- package/src/core/manifest.ts +3 -2
- package/src/core/meta.ts +69 -6
- package/src/core/nav-diagnostics.ts +56 -1
- package/src/core/navigation.ts +245 -76
- package/src/core/ordering-prefix.ts +27 -0
- package/src/core/project-graph.ts +23 -1
- package/src/core/request-body.ts +1 -1
- package/src/core/safe-href.ts +53 -1
- package/src/core/safe-links.ts +11 -2
- package/src/core/schema.ts +95 -34
- package/src/core/server-features.ts +2 -2
- package/src/core/sources/assets.ts +83 -41
- package/src/core/sources/contentful-rich-text.ts +3 -2
- package/src/core/sources/contentful.ts +25 -12
- package/src/core/sources/filesystem.ts +5 -1
- package/src/core/sources/github-releases.ts +106 -5
- package/src/core/sources/lexical.ts +9 -4
- package/src/core/sources/lower.ts +79 -26
- package/src/core/sources/mdx-remote.ts +1 -0
- package/src/core/sources/normalize.ts +132 -30
- package/src/core/sources/notion.ts +26 -10
- package/src/core/sources/obsidian.ts +17 -3
- package/src/core/sources/payload.ts +1 -0
- package/src/core/sources/portable-text.ts +63 -44
- package/src/core/sources/remote.ts +18 -2
- package/src/core/sources/resolve.ts +52 -33
- package/src/core/sources/sanity.ts +1 -0
- package/src/core/sources/strapi-blocks.ts +9 -4
- package/src/core/sources/strapi.ts +1 -0
- package/src/core/sources/types.ts +31 -0
- package/src/core/types.ts +9 -0
- package/src/core/ui-packs/ar.ts +17 -5
- package/src/core/ui-packs/bg.ts +17 -5
- package/src/core/ui-packs/bn.ts +17 -5
- package/src/core/ui-packs/ca.ts +17 -5
- package/src/core/ui-packs/cs.ts +17 -5
- package/src/core/ui-packs/da.ts +17 -5
- package/src/core/ui-packs/de.ts +17 -5
- package/src/core/ui-packs/el.ts +17 -5
- package/src/core/ui-packs/es.ts +17 -5
- package/src/core/ui-packs/fa.ts +17 -5
- package/src/core/ui-packs/fi.ts +17 -5
- package/src/core/ui-packs/fr.ts +17 -5
- package/src/core/ui-packs/he.ts +17 -5
- package/src/core/ui-packs/hi.ts +17 -5
- package/src/core/ui-packs/hr.ts +17 -5
- package/src/core/ui-packs/hu.ts +17 -5
- package/src/core/ui-packs/id.ts +17 -5
- package/src/core/ui-packs/it.ts +17 -5
- package/src/core/ui-packs/ja.ts +17 -5
- package/src/core/ui-packs/ko.ts +17 -5
- package/src/core/ui-packs/nl.ts +17 -5
- package/src/core/ui-packs/no.ts +17 -5
- package/src/core/ui-packs/pl.ts +17 -5
- package/src/core/ui-packs/pt-br.ts +17 -5
- package/src/core/ui-packs/pt.ts +17 -5
- package/src/core/ui-packs/ro.ts +17 -5
- package/src/core/ui-packs/ru.ts +17 -5
- package/src/core/ui-packs/sk.ts +17 -5
- package/src/core/ui-packs/sr.ts +17 -5
- package/src/core/ui-packs/sv.ts +17 -5
- package/src/core/ui-packs/th.ts +17 -5
- package/src/core/ui-packs/tr.ts +17 -5
- package/src/core/ui-packs/uk.ts +17 -5
- package/src/core/ui-packs/vi.ts +17 -5
- package/src/core/ui-packs/zh-tw.ts +17 -5
- package/src/core/ui-packs/zh.ts +17 -5
- package/src/core/unrecognized-keys.ts +1 -1
- package/src/core/version-cut.ts +17 -2
- package/src/core/versions.ts +4 -1
- package/src/deploy/adapters/node.ts +5 -2
- package/src/deploy/adapters/registry.ts +2 -1
- package/src/deploy/adapters/types.ts +13 -1
- package/src/deploy/artifacts.ts +25 -5
- package/src/deploy/cloudflare-negotiation.ts +23 -4
- package/src/deploy/headers.ts +67 -51
- package/src/deploy/node-headers.ts +148 -27
- package/src/deploy/platforms/cloudflare.ts +1 -0
- package/src/deploy/platforms/netlify.ts +82 -5
- package/src/deploy/platforms/node.ts +7 -5
- package/src/deploy/platforms/static.ts +1 -0
- package/src/deploy/platforms/types.ts +7 -0
- package/src/deploy/platforms/vercel.ts +9 -3
- package/src/deploy/redirects.ts +14 -3
- package/src/deploy/vercel-negotiation.ts +35 -3
- package/src/eval/agents.ts +10 -2
- package/src/eval/run.ts +25 -0
- package/src/markdown/base-links.ts +55 -8
- package/src/markdown/index.ts +6 -3
- package/src/markdown/relative-links.ts +3 -23
- package/src/markdown/route-snapshot.ts +37 -0
- package/src/og/card.ts +20 -4
- package/src/og/derive.ts +145 -4
- package/src/openapi/graphql-build.ts +28 -2
- package/src/openapi/model.ts +77 -13
- package/src/openapi/render-mdx.ts +10 -1
- package/src/registry/eject.ts +135 -37
- package/src/search/documents.ts +24 -3
- package/src/search/orama-index.ts +1 -1
- package/src/search/sync/algolia.ts +36 -2
- package/src/sources/registry.ts +5 -0
- package/src/theme/entry.ts +11 -4
- package/src/translate/agents.ts +6 -1
- package/src/translate/ledger.ts +26 -3
- package/src/translate/meta.ts +11 -3
- package/src/translate/report.ts +1 -1
- package/src/translate/run.ts +11 -5
- package/src/translate/validate.ts +10 -1
- package/src/translate/work-list.ts +36 -3
- package/src/upgrade/upgrade.ts +37 -5
- package/dist/cli/chunk-1w8dp3qb.js.map +0 -10
- package/dist/cli/chunk-5a2z0198.js.map +0 -10
- package/dist/cli/chunk-6k8vp3ta.js.map +0 -19
- package/dist/cli/chunk-79njf86q.js.map +0 -11
- package/dist/cli/chunk-a9kptbw5.js.map +0 -14
- package/dist/cli/chunk-abh8yjkn.js +0 -31
- package/dist/cli/chunk-abh8yjkn.js.map +0 -10
- package/dist/cli/chunk-bctazmbk.js.map +0 -10
- package/dist/cli/chunk-beat36xx.js.map +0 -10
- package/dist/cli/chunk-d1tadaw7.js.map +0 -10
- package/dist/cli/chunk-fa25z98p.js.map +0 -11
- package/dist/cli/chunk-j8mw0za6.js.map +0 -35
- package/dist/cli/chunk-mnqj32sj.js.map +0 -12
- package/dist/cli/chunk-mwt1k8n7.js.map +0 -10
- package/dist/cli/chunk-nk3ts2xk.js +0 -51
- package/dist/cli/chunk-nk3ts2xk.js.map +0 -10
- package/dist/cli/chunk-sqn5t4q0.js.map +0 -10
- package/dist/cli/chunk-tzne8qfq.js.map +0 -10
- package/dist/cli/chunk-xaz13gwg.js.map +0 -182
- package/dist/cli/chunk-z01ze5c1.js.map +0 -10
- package/dist/cli/chunk-z1f5arsg.js.map +0 -36
- package/dist/cli/chunk-zg2gtj10.js.map +0 -35
- /package/dist/cli/{chunk-f2972sbt.js.map → chunk-00gs3wqs.js.map} +0 -0
- /package/dist/cli/{chunk-7ez8ny0t.js.map → chunk-bbnwccaz.js.map} +0 -0
- /package/dist/cli/{chunk-zxccj738.js.map → chunk-esh98wmb.js.map} +0 -0
- /package/dist/cli/{chunk-88cpgt6h.js.map → chunk-fsmrqk8a.js.map} +0 -0
- /package/dist/cli/{chunk-b5aj94ah.js.map → chunk-g698a744.js.map} +0 -0
- /package/dist/cli/{chunk-41za066z.js.map → chunk-h2ez8dzb.js.map} +0 -0
- /package/dist/cli/{chunk-by2290sx.js.map → chunk-h7k3nq3v.js.map} +0 -0
- /package/dist/cli/{chunk-y3e45rc8.js.map → chunk-n1yg3tj3.js.map} +0 -0
- /package/dist/cli/{chunk-f7t03s3g.js.map → chunk-wdrt2k2v.js.map} +0 -0
|
@@ -92,7 +92,7 @@ The codemod touches **only frontmatter**. Icons in MDX **body** (`<Icon icon="
|
|
|
92
92
|
| `life-ring` | `life-buoy` | | `shield-halved` | `shield` |
|
|
93
93
|
| `rocket`/`book`/`book-open`/`code`/`terminal`/`key`/`lock`/`user`/`users`/`database`/`server`/`cloud`/`bell`/`calendar`/`star`/`heart`/`tag`/`folder`/`globe`/`link`/`download`/`upload`/`check`/`copy`/`play`/`filter` | _(same name — verify)_ |
|
|
94
94
|
|
|
95
|
-
**Rules:** verify each Lucide name exists at [lucide.dev/icons](https://lucide.dev/icons) before writing it. **Brand icons** (`fa6-brands:*` — github, discord, x, slack, linkedin…) mostly have **no** Lucide equivalent: for GitHub use the `github` config (renders the header repo link); for other socials, drop the icon and report it (or add via a Footer override after `blume eject`). Where no Lucide counterpart exists, **drop the icon and report it
|
|
95
|
+
**Rules:** verify each Lucide name exists at [lucide.dev/icons](https://lucide.dev/icons) before writing it. **Brand icons** (`fa6-brands:*` — github, discord, x, slack, linkedin…) mostly have **no** Lucide equivalent: for GitHub use the `github` config (renders the header repo link); for other socials, drop the icon and report it (or add via a Footer override after `blume eject`). Where no Lucide counterpart exists, **drop the icon and report it**. The build won't catch a wrong name for you: an unknown icon renders nothing, and it's only a warning (`BLUME_UNKNOWN_ICON`) for navigation icons — an icon prop on a component like `<Card>` fails silently — so check every name.
|
|
96
96
|
|
|
97
97
|
## Navigation: `docs.json` `navigation` → filesystem + tabs
|
|
98
98
|
|
|
@@ -143,7 +143,7 @@ Mintlify page frontmatter → Blume's strict schema. **`scripts/mintlify-codemod
|
|
|
143
143
|
| `canonical` | `seo.canonical` | renames |
|
|
144
144
|
| `og:image` | `seo.image` | renames |
|
|
145
145
|
| `hidden: true` | valid top-level in Blume — **kept as-is**; add `noindex: true` yourself if the page must also leave the search index | left (do by hand) |
|
|
146
|
-
| `openapi`/`asyncapi`/`api` | usually an endpoint stub → **delete the page** (Blume generates operation pages); else `
|
|
146
|
+
| `openapi`/`asyncapi`/`api` | usually an endpoint stub → **delete the page** (Blume generates operation pages); else drop the key and keep it as a normal page (there's no built-in `api` page type) | **flags** for review — never auto-deletes a page |
|
|
147
147
|
| `mode`, `public`, `rss`, `groups`, `keywords`, `hideApiMarker`, `hideFooterPagination`, `iconType` | **drop** (report) | drops |
|
|
148
148
|
|
|
149
149
|
The codemod leaves the source key in place and reports a conflict rather than clobbering data when a rename target already exists (e.g. a page already has `sidebar.label`) or the value is too structured to move safely — resolve those by hand. Remove any duplicate H1 in the body — `title` renders the H1. (The codemod only edits frontmatter; it never touches the body.)
|
|
@@ -153,7 +153,7 @@ The codemod leaves the source key in place and reports a conflict rather than cl
|
|
|
153
153
|
Top-level `openapi`, `api.openapi`, or a per-group/per-tab `openapi` → `reference: [openapi({ sources: [{ spec, label?, route? }] })]`, with `openapi` imported from `blume/reference` (`spec` alone is the single-source shorthand; several per-tab specs become several sources, or several `openapi()` entries when they need different routes; a spec the source embedded with Scalar becomes a `scalar({ spec })` entry). A Mintlify `{ source, directory }` object: `directory` → the source's `route`. An `asyncapi` field maps the same way to `asyncapi({ … })` in the list. **Delete every per-endpoint stub page** (frontmatter `openapi: "GET /path"` or a `"GET /path"` nav entry) — Blume's native renderer generates one real page per operation. **Add a `navigation.tabs` entry pointing at the reference `route` yourself** (Mintlify's API tab maps to it); the reference does not create a header tab automatically.
|
|
154
154
|
|
|
155
155
|
- **Vendor the spec.** Mintlify usually points at a spec **URL**. Copying that straight into `spec:` makes every build fetch it at build time — a single point of failure in CI/offline/behind a proxy, and a failed fetch silently drops the reference (leaving the tab pointing at a route that 404s). Prefer downloading it into the repo (`curl … -o openapi/<name>.json`) and pointing `spec` at that local path. If you keep the URL, report the dependency and consider a `prebuild` refresh-with-fallback.
|
|
156
|
-
- **Fix endpoint links.** Blume operation routes are `<route>/<slugified-tag>/<slugified-operationId>` (tag `Models` + id `listModels` → `/api-reference/models/
|
|
156
|
+
- **Fix endpoint links.** Blume operation routes are `<route>/<slugified-tag>/<slugified-operationId>` (tag `Models` + id `listModels` → `/api-reference/models/list-models`: a camelCase id is split into kebab-case, not just lowercased — see SKILL.md "OpenAPI") — this differs from Mintlify's endpoint URLs, so **rewrite every inbound link to an operation**. `blume validate` resolves operation pages like any other route and flags the ones you miss.
|
|
157
157
|
- **Keep the "Introduction" page.** Mintlify commonly has a written intro/auth page in an "Introduction" group beside the "Endpoints" (openapi) group in the same tab. Keep it: a normal content page placed under the `openapi()` adapter's `route` (e.g. `<root>/api-reference/introduction.mdx`) merges into the reference tab's sidebar alongside the generated operations. Delete only the per-endpoint stubs, not the conceptual pages.
|
|
158
158
|
|
|
159
159
|
## Assets
|
|
@@ -56,7 +56,7 @@ Most Nextra pages have **no frontmatter**; the title falls back `_meta` title
|
|
|
56
56
|
|
|
57
57
|
## Code fences
|
|
58
58
|
|
|
59
|
-
Nextra's fence meta differs from Blume's — rewrite it: `filename="app.js"` → a space-separated title (` ```js app.js `); `showLineNumbers` → `lineNumbers`; line highlighting `{1,4-5}` carries over unchanged; **drop** word-highlight `/word
|
|
59
|
+
Nextra's fence meta differs from Blume's — rewrite it: `filename="app.js"` → a space-separated title (` ```js app.js `); `showLineNumbers` → `lineNumbers`; line highlighting `{1,4-5}` carries over unchanged; **drop** word-highlight `/word/` and `copy`/`copy=false`. **Keep** inline-code `{:lang}` suffixes (`` `useState(){:js}` ``) — Blume highlights them natively. ` ```sh npm2yarn ` fences → ` ```package-install `.
|
|
60
60
|
|
|
61
61
|
## Math
|
|
62
62
|
|
|
@@ -12,7 +12,7 @@ Keep content where it is — set `content.root: "src/content/docs"`.
|
|
|
12
12
|
|
|
13
13
|
## Config: `starlight({…})` → `blume.config.ts`
|
|
14
14
|
|
|
15
|
-
**Harvest the surrounding `astro.config.*` too, not just the `starlight()` call:** top-level Astro `redirects` → Blume `redirects`; `site` →
|
|
15
|
+
**Harvest the surrounding `astro.config.*` too, not just the `starlight()` call:** top-level Astro `redirects` → Blume `redirects`; `site` → `deployment.site`, unless the target host is Vercel, Netlify, or Cloudflare Pages, which Blume auto-detects (see SKILL.md); other integrations → report.
|
|
16
16
|
|
|
17
17
|
| Starlight option | Blume |
|
|
18
18
|
| --- | --- |
|
|
@@ -70,7 +70,7 @@ Starlight's primary callout syntax is the `:::note`/`:::tip`/`:::caution`/`:::da
|
|
|
70
70
|
|
|
71
71
|
## Components
|
|
72
72
|
|
|
73
|
-
- **Renames:** `<CardGrid>` → `<CardGroup>`; `<LinkCard>` → `<Card>` (its `description` prop drops — fold into the body); `<TabItem label="…">` → `<Tab title="…">`. `<Tabs>` and `<Card>` stay; a `<Tabs syncKey="…">`
|
|
73
|
+
- **Renames:** `<CardGrid>` → `<CardGroup>`; `<LinkCard>` → `<Card>` (its `description` prop drops — fold into the body); `<TabItem label="…">` → `<Tab title="…">`. `<Tabs>` and `<Card>` stay; **keep** a `<Tabs syncKey="…">` prop as is — Blume's `Tabs` takes `syncKey` with the same scoping (only groups sharing the key switch together). One difference: Blume groups without a key also sync, page-wide, by tab title, where Starlight leaves them independent — add `sync={false}` to a keyless group whose same-titled tabs must stay unlinked.
|
|
74
74
|
- **`<Badge>` needs conversion, not pass-through:** Starlight puts content in a `text` prop and uses variants `note`/`tip`/`caution`/`danger`/`success`/`default` with sizes `small`/`medium`/`large`. Blume's `<Badge>` renders **children** with variants `default`/`accent`/`success`/`warning`/`danger` and sizes `xs`/`sm`/`md`/`lg`. Move `text` into the children; remap variant (`note`→`default`, `tip`→`accent`, `caution`→`warning`, `danger`→`danger`, `success`→`success`) and size (`small`→`sm`, `medium`→`md`, `large`→`lg`).
|
|
75
75
|
- **Convert yourself:** `<Steps>` → Blume `<Steps>`/`<Step>`; `<FileTree>` → Blume `<FileTree>`; `<Code code={…}>` → a fenced code block; `<LinkButton>` → a Markdown link or `<Card>`.
|
|
76
76
|
- Strip `import … from "@astrojs/starlight/*"` and `astro:assets` lines.
|
|
@@ -88,8 +88,8 @@ Starlight content is full of Expressive Code fence meta; Blume understands some
|
|
|
88
88
|
## Plugins — map, don't drop
|
|
89
89
|
|
|
90
90
|
- `starlight-openapi` → an `openapi({ sources })` entry in Blume's `reference` list, imported from `blume/reference` (delete any generated pages; add the `navigation.tabs` entry).
|
|
91
|
-
- `starlight-blog` → `type: blog` pages.
|
|
92
|
-
- `starlight-versions` → `navigation.selectors` with `
|
|
91
|
+
- `starlight-blog` → `type: blog` pages (RSS at `/blog/rss.xml`). Blume generates **no** blog index, tag, or author pages: write a `blog/index.mdx` whose `CardGroup` links each post (see `docs/advanced/blog.mdx` in the installed package), and report the tag and author pages as dropped.
|
|
92
|
+
- `starlight-versions` → Blume's native versioning, not a `navigation.selectors` dropdown: each archived version's content goes in a top-level folder under `content.root` named for its id, listed in `versions.archived` (newest first), and Blume adds the switcher, the old-version notice, and version-scoped search. Ids must start with a letter (`1.0/` → `v1.0/`, with `redirects` from the old URLs), and a version-shaped folder left out of `versions.archived` only warns (`BLUME_VERSIONS_UNCONFIGURED_VERSION`) and publishes as current content. Full reference: `docs/content/versioning.mdx` in the installed package.
|
|
93
93
|
- `starlight-image-zoom` → delete (Blume zooms content images by default).
|
|
94
94
|
- `starlight-links-validator` → delete (`blume validate` covers it).
|
|
95
95
|
- Anything else → report.
|
|
@@ -113,4 +113,4 @@ Remove `@astrojs/starlight` (and plugin deps) from deps, delete the Starlight bi
|
|
|
113
113
|
|
|
114
114
|
## Dropped — report these
|
|
115
115
|
|
|
116
|
-
Non-GitHub socials, badge variants, sidebar/item `attrs` + `translations`, `customCss` beyond `theme.css`, `head` entries, `routeMiddleware`, splash/hero pages (rebuild as custom pages), aside custom icons, EC frames/collapse/text markers, prev/next toggles, unmapped plugins, any `<Icon>` name with no Lucide equivalent.
|
|
116
|
+
Non-GitHub socials, badge variants, sidebar/item `attrs` + `translations`, `customCss` beyond `theme.css`, `head` entries, `routeMiddleware`, splash/hero pages (rebuild as custom pages), starlight-blog's tag and author pages, aside custom icons, EC frames/collapse/text markers, prev/next toggles, unmapped plugins, any `<Icon>` name with no Lucide equivalent.
|
|
@@ -177,8 +177,8 @@ const RENAME = {
|
|
|
177
177
|
};
|
|
178
178
|
|
|
179
179
|
// Keys we deliberately do NOT auto-transform — they usually mean the page is an
|
|
180
|
-
// OpenAPI endpoint stub that should be deleted (Blume generates operation pages)
|
|
181
|
-
// or
|
|
180
|
+
// OpenAPI endpoint stub that should be deleted (Blume generates operation pages),
|
|
181
|
+
// or else a normal page that just loses the key. Flag for the human; never guess.
|
|
182
182
|
const FLAG = new Set(["api", "asyncapi", "openapi"]);
|
|
183
183
|
|
|
184
184
|
// Which change kinds actually edit the file. Report-only kinds (flags,
|
|
@@ -32,7 +32,7 @@ Skip the edit when the only available change is subjective polish, wording prefe
|
|
|
32
32
|
- Preserve existing page order and `defineMeta` style; update `pages` arrays when adding, renaming, or removing pages.
|
|
33
33
|
- Use the Blume components already present in the docs (callout directives, steps, cards) instead of inventing new markup patterns.
|
|
34
34
|
- Match nearby code fences: filenames, language tags, and line numbers where the surrounding docs use them.
|
|
35
|
-
- Keep internal links root-relative (`/
|
|
35
|
+
- Keep internal links root-relative (`/guides/setup`), in the form nearby pages already use.
|
|
36
36
|
- Do not edit generated `.blume/` or `dist/` output.
|
|
37
37
|
|
|
38
38
|
## PR notes
|
|
@@ -34,7 +34,7 @@ const usagePolicy = (
|
|
|
34
34
|
};
|
|
35
35
|
|
|
36
36
|
/**
|
|
37
|
-
* The advertised
|
|
37
|
+
* The advertised assistant URL. An external endpoint is not served under
|
|
38
38
|
* `deployment.base`, so a root-relative one absolutizes against the site
|
|
39
39
|
* origin alone; the built-in route gets site and base via `abs`.
|
|
40
40
|
*/
|
|
@@ -154,7 +154,7 @@ const wellKnownArtifacts = (
|
|
|
154
154
|
/**
|
|
155
155
|
* Build `agent-readability.json`: a root manifest that indexes the project's
|
|
156
156
|
* agent-facing surface — llms.txt, the raw-Markdown mirrors, the JSON docs
|
|
157
|
-
* API and its OpenAPI description, the MCP server,
|
|
157
|
+
* API and its OpenAPI description, the MCP server, the assistant, sitemap, and feeds
|
|
158
158
|
* — so agents can discover and cite the docs without
|
|
159
159
|
* scraping HTML. URLs are absolute when a `site` is configured and root-relative
|
|
160
160
|
* (still under `deployment.base`) otherwise. Returns null when the manifest is
|
|
@@ -194,8 +194,8 @@ export const buildAgentReadability = (
|
|
|
194
194
|
url: abs(config.agents.mcp.route),
|
|
195
195
|
};
|
|
196
196
|
}
|
|
197
|
-
if (config.ai.
|
|
198
|
-
artifacts.askApi = askApiUrl(config.ai.
|
|
197
|
+
if (config.ai.assistant?.enabled) {
|
|
198
|
+
artifacts.askApi = askApiUrl(config.ai.assistant.endpoint, site, abs);
|
|
199
199
|
}
|
|
200
200
|
Object.assign(artifacts, wellKnownArtifacts(config, abs));
|
|
201
201
|
if (site && config.seo.sitemap) {
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { routeIsTaken } from "../astro/pages.ts";
|
|
2
|
+
import type { BlumeProject } from "../core/project-graph.ts";
|
|
3
|
+
import type { ResolvedConfig } from "../core/schema.ts";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* What a build actually serves of the agent surfaces whose config flag alone
|
|
7
|
+
* doesn't guarantee them.
|
|
8
|
+
*/
|
|
9
|
+
export interface EmittedAgentSurface {
|
|
10
|
+
/** The MCP server was generated (see {@link servesMcp}). */
|
|
11
|
+
mcp: boolean;
|
|
12
|
+
/**
|
|
13
|
+
* A skills discovery index is served: generated from `agents.skills` (at
|
|
14
|
+
* least one valid skill), or shipped by the user in `public/`.
|
|
15
|
+
*/
|
|
16
|
+
skills: boolean;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Whether the build generates the MCP server: it is enabled and no content
|
|
21
|
+
* or custom page owns its route. When one does, the generator skips the
|
|
22
|
+
* server with a warning rather than collide with the page (`planMcp`).
|
|
23
|
+
*/
|
|
24
|
+
export const servesMcp = (
|
|
25
|
+
project: BlumeProject,
|
|
26
|
+
userPages: { pattern: string }[]
|
|
27
|
+
): boolean =>
|
|
28
|
+
project.config.agents.mcp.enabled &&
|
|
29
|
+
!routeIsTaken(
|
|
30
|
+
userPages,
|
|
31
|
+
project.graph.pages,
|
|
32
|
+
project.config.agents.mcp.route
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* The config the discovery documents are built from: `agents.mcp` and
|
|
37
|
+
* `agents.skills` switched off when the build didn't emit them, so llms.txt,
|
|
38
|
+
* agent-readability.json, the catalogs, and the header rules only point at
|
|
39
|
+
* what is there. A config flag says what was asked for; the MCP server is
|
|
40
|
+
* skipped when a page owns its route, and skills publish nothing when their
|
|
41
|
+
* directory is missing or holds no valid skill.
|
|
42
|
+
*/
|
|
43
|
+
export const advertisedConfig = (
|
|
44
|
+
config: ResolvedConfig,
|
|
45
|
+
emitted: EmittedAgentSurface
|
|
46
|
+
): ResolvedConfig => ({
|
|
47
|
+
...config,
|
|
48
|
+
agents: {
|
|
49
|
+
...config.agents,
|
|
50
|
+
mcp: {
|
|
51
|
+
...config.agents.mcp,
|
|
52
|
+
enabled: config.agents.mcp.enabled && emitted.mcp,
|
|
53
|
+
},
|
|
54
|
+
skills: emitted.skills ? config.agents.skills : undefined,
|
|
55
|
+
},
|
|
56
|
+
});
|
package/src/ai/api/paths.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Where the JSON docs API and its OpenAPI description are served. Base-less
|
|
3
3
|
* (like every route Blume emits); callers layer `deployment.base` on top.
|
|
4
|
-
* Under `/api/` alongside the
|
|
4
|
+
* Under `/api/` alongside the assistant endpoint (`/api/ask`) so the namespace a
|
|
5
5
|
* Blume site reserves for live endpoints stays one prefix, and under its own
|
|
6
6
|
* `docs` segment so a search provider's proxy at `/api/search` never collides.
|
|
7
7
|
*/
|
package/src/ai/api/spec.ts
CHANGED
|
@@ -113,6 +113,7 @@ export interface ApiSpecDocument {
|
|
|
113
113
|
}
|
|
114
114
|
|
|
115
115
|
const JSON_TYPE = "application/json";
|
|
116
|
+
const EVENT_STREAM_TYPE = "text/event-stream";
|
|
116
117
|
const MARKDOWN_TYPE = "text/markdown";
|
|
117
118
|
const TEXT_TYPE = "text/plain";
|
|
118
119
|
|
|
@@ -623,14 +624,26 @@ export const buildApiSpec = (input: ApiSpecInput): ApiSpecDocument => {
|
|
|
623
624
|
{
|
|
624
625
|
post: {
|
|
625
626
|
description:
|
|
626
|
-
"The Model Context Protocol server (Streamable HTTP, stateless, JSON responses). Tools: `search_docs`, `get_page`, `list_pages`, `get_navigation` — the same operations this API exposes — plus every page as a `text/markdown` resource. Discovery document at `/.well-known/mcp.json`.",
|
|
627
|
+
"The Model Context Protocol server (Streamable HTTP, stateless, JSON responses). Send `Accept: application/json, text/event-stream`: the Streamable HTTP transport requires a client to accept both and answers `406` otherwise, though this server always replies with JSON. Tools: `search_docs`, `get_page`, `list_pages`, `get_navigation` — the same operations this API exposes — plus every page as a `text/markdown` resource. Discovery document at `/.well-known/mcp.json`.",
|
|
627
628
|
operationId: "mcp",
|
|
628
629
|
requestBody: {
|
|
629
630
|
content: { [JSON_TYPE]: { schema: ref("JsonRpcRequest") } },
|
|
630
631
|
required: true,
|
|
631
632
|
},
|
|
632
633
|
responses: {
|
|
633
|
-
|
|
634
|
+
// Both media types, so a generated client sends the Accept header
|
|
635
|
+
// the transport requires; OpenAPI ignores an `Accept` parameter.
|
|
636
|
+
"200": {
|
|
637
|
+
content: {
|
|
638
|
+
[JSON_TYPE]: { schema: ref("JsonRpcResponse") },
|
|
639
|
+
[EVENT_STREAM_TYPE]: { schema: { type: "string" } },
|
|
640
|
+
},
|
|
641
|
+
description: "The JSON-RPC response.",
|
|
642
|
+
},
|
|
643
|
+
"406": jsonResponse(
|
|
644
|
+
"The request's `Accept` header doesn't list both `application/json` and `text/event-stream`.",
|
|
645
|
+
"JsonRpcResponse"
|
|
646
|
+
),
|
|
634
647
|
},
|
|
635
648
|
summary: "Call the MCP server",
|
|
636
649
|
tags: ["MCP"],
|
package/src/ai/api-catalog.ts
CHANGED
|
@@ -17,7 +17,13 @@ import { API_BASE, OPENAPI_PATH } from "./api/paths.ts";
|
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
19
|
export const API_CATALOG_PATH = "/.well-known/api-catalog";
|
|
20
|
-
|
|
20
|
+
/** The profile URI RFC 9727 registers for an API catalog linkset. */
|
|
21
|
+
export const API_CATALOG_PROFILE = "https://www.rfc-editor.org/info/rfc9727";
|
|
22
|
+
/**
|
|
23
|
+
* The catalog's media type: a linkset carrying the RFC 9727 profile
|
|
24
|
+
* parameter, which the RFC says an API catalog SHOULD be served with.
|
|
25
|
+
*/
|
|
26
|
+
export const API_CATALOG_TYPE = `application/linkset+json; profile="${API_CATALOG_PROFILE}"`;
|
|
21
27
|
|
|
22
28
|
/** An RFC 9264 linkset entry, restricted to the relations Blume emits. */
|
|
23
29
|
interface LinksetEntry {
|
package/src/ai/ask-context.ts
CHANGED
|
@@ -4,7 +4,7 @@ import type { FenceState } from "../core/code-fences.ts";
|
|
|
4
4
|
import { buildOramaIndex, queryOramaIndex } from "../search/orama-index.ts";
|
|
5
5
|
import type { OramaDoc } from "../search/orama-index.ts";
|
|
6
6
|
|
|
7
|
-
/** A chat message as posted by the
|
|
7
|
+
/** A chat message as posted by the assistant island (`{ role, content }`). */
|
|
8
8
|
export interface AskMessage {
|
|
9
9
|
content: string;
|
|
10
10
|
role: string;
|
|
@@ -16,7 +16,7 @@ export interface AskPage {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
|
-
* The self-contained snapshot the grounded
|
|
19
|
+
* The self-contained snapshot the assistant's grounded endpoint imports. Bundles the
|
|
20
20
|
* search documents so retrieval works regardless of the configured search
|
|
21
21
|
* provider and needs no filesystem access at request time. Serialized to
|
|
22
22
|
* `generated/ask-data.json` and built by {@link buildAskData}.
|
|
@@ -30,6 +30,13 @@ export interface AskData {
|
|
|
30
30
|
defaultLocale?: string;
|
|
31
31
|
documents: OramaDoc[];
|
|
32
32
|
site: string | null;
|
|
33
|
+
/**
|
|
34
|
+
* Present on a versioned site, whose documents then carry their `version`
|
|
35
|
+
* (`""` for the current docs): retrieval keeps to the version the reader
|
|
36
|
+
* is viewing — the current docs unless they're on an archived page — as
|
|
37
|
+
* the search dialog does.
|
|
38
|
+
*/
|
|
39
|
+
versioned?: boolean;
|
|
33
40
|
}
|
|
34
41
|
|
|
35
42
|
/** Documents retrieved per question and injected into the system prompt. */
|
|
@@ -47,7 +54,7 @@ const CONTEXT_BUDGET = 10_000;
|
|
|
47
54
|
const MIN_EXCERPT_CHARS = 200;
|
|
48
55
|
|
|
49
56
|
/**
|
|
50
|
-
* How much retrieved documentation a question carries (the `ai.
|
|
57
|
+
* How much retrieved documentation a question carries (the `ai.assistant.retrieval`
|
|
51
58
|
* config). Every field falls back to the built-in default, so a partial object
|
|
52
59
|
* only changes what it names. Injected characters dominate time-to-first-token
|
|
53
60
|
* on a self-hosted backend, and the three knobs aren't interchangeable: the
|
|
@@ -309,7 +316,7 @@ const interleave = (lists: OramaDoc[][], limit: number): OramaDoc[] => {
|
|
|
309
316
|
*
|
|
310
317
|
* Pages are indexed whole (one document each), so a naive head slice of a long
|
|
311
318
|
* page returns its intro and misses sections below the fold — the exact failure
|
|
312
|
-
* where "How does
|
|
319
|
+
* where "How does the assistant work?" retrieves the right page but only sees its
|
|
313
320
|
* opening paragraph. This centers the window on the densest cluster of query
|
|
314
321
|
* terms so the injected text is the part that actually answers the question.
|
|
315
322
|
* Exported for testing; {@link createAskContext} is the runtime entry point.
|
|
@@ -585,7 +592,7 @@ export const sectionExcerpt = (
|
|
|
585
592
|
): string => excerptPage(parsePage(content), query, max);
|
|
586
593
|
|
|
587
594
|
/**
|
|
588
|
-
* Build the request-time grounding function for the
|
|
595
|
+
* Build the request-time grounding function for the assistant endpoint.
|
|
589
596
|
*
|
|
590
597
|
* Lexical retrieval over Orama (the same index/ranking the search dialog and MCP
|
|
591
598
|
* server use). The index is built once and memoized across requests. Returns a
|
|
@@ -593,12 +600,12 @@ export const sectionExcerpt = (
|
|
|
593
600
|
* viewing — or `undefined` when there is nothing to ground on, so the endpoint
|
|
594
601
|
* can fall back to its plain prompt.
|
|
595
602
|
*
|
|
596
|
-
* `options.instructions` (the `ai.
|
|
603
|
+
* `options.instructions` (the `ai.assistant.instructions` config) is appended after
|
|
597
604
|
* the base instruction rather than replacing it: the base carries the
|
|
598
605
|
* functional contract (answer only from the excerpts, cite pages as Markdown
|
|
599
606
|
* links) that the panel's citation rendering depends on.
|
|
600
607
|
*
|
|
601
|
-
* `options.retrieval` (the `ai.
|
|
608
|
+
* `options.retrieval` (the `ai.assistant.retrieval` config) sizes how much
|
|
602
609
|
* documentation each question carries; omitted fields keep today's defaults.
|
|
603
610
|
*/
|
|
604
611
|
export const createAskContext = (
|
|
@@ -644,12 +651,17 @@ export const createAskContext = (
|
|
|
644
651
|
// which part of each page is quoted.
|
|
645
652
|
const [query = ""] = queries;
|
|
646
653
|
|
|
647
|
-
// The current page anchors retrieval to its locale and
|
|
654
|
+
// The current page anchors retrieval to its locale and docs version, and
|
|
655
|
+
// is injected first. Without one, a versioned site grounds in the
|
|
656
|
+
// current docs rather than every archived copy of each page.
|
|
648
657
|
const current = page?.path
|
|
649
658
|
? byRoute.get(normalizeRoute(page.path))
|
|
650
659
|
: undefined;
|
|
651
660
|
const db = await index();
|
|
652
|
-
const filters = {
|
|
661
|
+
const filters = {
|
|
662
|
+
locale: current?.locale || undefined,
|
|
663
|
+
version: data.versioned ? (current?.version ?? "") : undefined,
|
|
664
|
+
};
|
|
653
665
|
const hits = interleave(
|
|
654
666
|
await Promise.all(
|
|
655
667
|
queries.map((text) => queryOramaIndex(db, text, maxResults, filters))
|
package/src/ai/ask-data.ts
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import type { BlumeProject } from "../core/project-graph.ts";
|
|
2
2
|
import { buildSearchDocuments } from "../search/documents.ts";
|
|
3
|
+
import type { OramaDoc } from "../search/orama-index.ts";
|
|
3
4
|
import type { AskData } from "./ask-context.ts";
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
|
-
* Build the grounding snapshot the
|
|
7
|
-
*
|
|
8
|
-
* search provider is `none` (`includeWhenDisabled`). `locale` is kept
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
7
|
+
* Build the grounding snapshot the assistant endpoint serves. Like the MCP server,
|
|
8
|
+
* the assistant is independent of on-page search, so documents are indexed even when the
|
|
9
|
+
* search provider is `none` (`includeWhenDisabled`). `locale` is kept so
|
|
10
|
+
* retrieval can be filtered to the current page's language, and on a
|
|
11
|
+
* versioned site `version` too, so archived snapshots don't crowd the docs
|
|
12
|
+
* being read out of the answer. Content is kept as Markdown so grounding sees
|
|
13
|
+
* fenced code examples — the model answers "what does the config look like?"
|
|
14
|
+
* from the docs instead of declining.
|
|
12
15
|
* The reader is an AI agent, so `<Visibility>` resolves for the agents audience
|
|
13
16
|
* (web-only content removed, agents-only unwrapped) and components downlevel to
|
|
14
17
|
* Markdown, both matching llms-full.txt.
|
|
@@ -19,15 +22,26 @@ export const buildAskData = async (project: BlumeProject): Promise<AskData> => {
|
|
|
19
22
|
content: "markdown",
|
|
20
23
|
includeWhenDisabled: true,
|
|
21
24
|
});
|
|
22
|
-
|
|
25
|
+
const versioned = Boolean(project.config.versions);
|
|
26
|
+
const data: AskData = {
|
|
23
27
|
defaultLocale: project.config.i18n?.defaultLocale,
|
|
24
|
-
documents: documents.map((doc) =>
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
documents: documents.map((doc) => {
|
|
29
|
+
const document: OramaDoc = {
|
|
30
|
+
content: doc.content,
|
|
31
|
+
description: doc.description,
|
|
32
|
+
locale: doc.locale,
|
|
33
|
+
route: doc.route,
|
|
34
|
+
title: doc.title,
|
|
35
|
+
};
|
|
36
|
+
if (versioned) {
|
|
37
|
+
document.version = doc.version;
|
|
38
|
+
}
|
|
39
|
+
return document;
|
|
40
|
+
}),
|
|
31
41
|
site: project.config.deployment.options.site ?? null,
|
|
32
42
|
};
|
|
43
|
+
if (versioned) {
|
|
44
|
+
data.versioned = true;
|
|
45
|
+
}
|
|
46
|
+
return data;
|
|
33
47
|
};
|