blume 2.0.3 → 2.1.1
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 -0
- package/CHANGELOG.md +142 -0
- package/README.md +1 -1
- package/dist/cli/{chunk-5f86nr5m.js → chunk-073rdvgb.js} +21 -48
- package/dist/cli/{chunk-5f86nr5m.js.map → chunk-073rdvgb.js.map} +4 -5
- package/dist/cli/{chunk-ga0pf4aj.js → chunk-0n9xkp3d.js} +12 -3
- package/dist/cli/{chunk-ga0pf4aj.js.map → chunk-0n9xkp3d.js.map} +3 -3
- package/dist/cli/chunk-150jk7km.js +52 -0
- package/dist/cli/chunk-150jk7km.js.map +10 -0
- package/dist/cli/{chunk-9t7a85s3.js → chunk-313vnn40.js} +30 -19
- package/dist/cli/chunk-313vnn40.js.map +10 -0
- package/dist/cli/{chunk-tkacnehg.js → chunk-3v3ffbrj.js} +2 -2
- package/dist/cli/{chunk-q58y5e6a.js → chunk-3x6x3pph.js} +46 -24
- package/dist/cli/chunk-3x6x3pph.js.map +10 -0
- package/dist/cli/{chunk-1d7ve1dm.js → chunk-42t4jxdx.js} +37 -5
- package/dist/cli/chunk-42t4jxdx.js.map +12 -0
- package/dist/cli/{chunk-8ktnccpt.js → chunk-54ztw1nj.js} +21 -2
- package/dist/cli/chunk-54ztw1nj.js.map +10 -0
- package/dist/cli/{chunk-hm3vjy5s.js → chunk-5vjtgs6e.js} +28 -10
- package/dist/cli/{chunk-hm3vjy5s.js.map → chunk-5vjtgs6e.js.map} +4 -4
- package/dist/cli/chunk-66w9j7p6.js +322 -0
- package/dist/cli/chunk-66w9j7p6.js.map +14 -0
- package/dist/cli/{chunk-2hsdwb9n.js → chunk-7ppf1rva.js} +34 -18
- package/dist/cli/chunk-7ppf1rva.js.map +10 -0
- package/dist/cli/{chunk-r9rcc4w7.js → chunk-8y2kmjv8.js} +7 -7
- package/dist/cli/{chunk-r20tn01b.js → chunk-c1y538kd.js} +8 -2
- package/dist/cli/{chunk-r20tn01b.js.map → chunk-c1y538kd.js.map} +3 -3
- package/dist/cli/{chunk-2eytanqx.js → chunk-c887fj0s.js} +2 -2
- package/dist/cli/{chunk-p3v96n38.js → chunk-cfyg47zg.js} +16 -6
- package/dist/cli/chunk-cfyg47zg.js.map +10 -0
- package/dist/cli/chunk-cm89scdv.js +443 -0
- package/dist/cli/chunk-cm89scdv.js.map +11 -0
- package/dist/cli/{chunk-akbpwfxc.js → chunk-dzwehpy7.js} +2 -2
- package/dist/cli/{chunk-wrr3j9w9.js → chunk-e6atmn4h.js} +299 -72
- package/dist/cli/chunk-e6atmn4h.js.map +36 -0
- package/dist/cli/{chunk-tzmab476.js → chunk-e8xw9qkh.js} +8 -6
- package/dist/cli/{chunk-tzmab476.js.map → chunk-e8xw9qkh.js.map} +3 -3
- package/dist/cli/{chunk-6dsbexzp.js → chunk-e9q7a2ak.js} +17 -15
- package/dist/cli/{chunk-6dsbexzp.js.map → chunk-e9q7a2ak.js.map} +2 -2
- package/dist/cli/{chunk-pv29h0wf.js → chunk-ehweg4fr.js} +5155 -1249
- package/dist/cli/chunk-ehweg4fr.js.map +218 -0
- package/dist/cli/{chunk-c8chx29p.js → chunk-ep6nd0rn.js} +390 -318
- package/dist/cli/chunk-ep6nd0rn.js.map +36 -0
- package/dist/cli/{chunk-p73c0m7w.js → chunk-fdrkhpjy.js} +18 -15
- package/dist/cli/{chunk-p73c0m7w.js.map → chunk-fdrkhpjy.js.map} +3 -3
- package/dist/cli/{chunk-2z928egk.js → chunk-ft9vfys6.js} +5 -5
- package/dist/cli/{chunk-5m5nmvyq.js → chunk-gb420vvz.js} +316 -79
- package/dist/cli/chunk-gb420vvz.js.map +17 -0
- package/dist/cli/{chunk-vg9r4eb9.js → chunk-hebn0tpx.js} +86 -13
- package/dist/cli/chunk-hebn0tpx.js.map +14 -0
- package/dist/cli/{chunk-35d4wj9f.js → chunk-htrwgabr.js} +41 -23
- package/dist/cli/chunk-htrwgabr.js.map +15 -0
- package/dist/cli/{chunk-g4hq16wv.js → chunk-hx3xqnk9.js} +16 -14
- package/dist/cli/{chunk-g4hq16wv.js.map → chunk-hx3xqnk9.js.map} +2 -2
- package/dist/cli/chunk-j134vrp2.js +65 -0
- package/dist/cli/chunk-j134vrp2.js.map +10 -0
- package/dist/cli/{chunk-a58773jm.js → chunk-kma9f6sf.js} +2 -2
- package/dist/cli/chunk-kwrg63tm.js +31 -0
- package/dist/cli/chunk-kwrg63tm.js.map +10 -0
- package/dist/cli/{chunk-ey84smr6.js → chunk-mrcccgnh.js} +6 -6
- package/dist/cli/{chunk-ey84smr6.js.map → chunk-mrcccgnh.js.map} +1 -1
- package/dist/cli/{chunk-yfyb25rh.js → chunk-n0v7m8ry.js} +24 -8
- package/dist/cli/chunk-n0v7m8ry.js.map +14 -0
- package/dist/cli/{chunk-j85vccga.js → chunk-ncj7w596.js} +576 -367
- package/dist/cli/chunk-ncj7w596.js.map +35 -0
- package/dist/cli/{chunk-5xvm6tfj.js → chunk-nq1d20w2.js} +17 -15
- package/dist/cli/{chunk-5xvm6tfj.js.map → chunk-nq1d20w2.js.map} +2 -2
- package/dist/cli/{chunk-pehfxfta.js → chunk-nrns10mj.js} +6 -98
- package/dist/cli/chunk-nrns10mj.js.map +10 -0
- package/dist/cli/{chunk-crgn1q09.js → chunk-sds923fa.js} +4 -4
- package/dist/cli/chunk-t2m5j4pr.js +104 -0
- package/dist/cli/chunk-t2m5j4pr.js.map +11 -0
- package/dist/cli/{chunk-acanzt5p.js → chunk-tdqhyxfz.js} +6 -6
- package/dist/cli/chunk-tphac74f.js +126 -0
- package/dist/cli/chunk-tphac74f.js.map +11 -0
- package/dist/cli/chunk-w1r4vase.js +18 -0
- package/dist/cli/chunk-w1r4vase.js.map +10 -0
- package/dist/cli/{chunk-3em5wd2y.js → chunk-zccbjcj0.js} +4 -3
- package/dist/cli/{chunk-3em5wd2y.js.map → chunk-zccbjcj0.js.map} +2 -2
- package/dist/cli/index.js +31 -20
- package/dist/cli/index.js.map +5 -5
- package/dist/types/ai/agent-surface.d.ts +8 -7
- package/dist/types/ai/ai-catalog.d.ts +7 -0
- package/dist/types/ai/ask-context.d.ts +26 -0
- package/dist/types/ai/ask.d.ts +271 -58
- package/dist/types/ai/component-markdown.d.ts +2 -0
- package/dist/types/ai/index.d.ts +2 -2
- package/dist/types/ai/openapi-components.d.ts +4 -1
- package/dist/types/ai/site-skill.d.ts +26 -0
- package/dist/types/ai/skills.d.ts +16 -0
- package/dist/types/astro/integration.d.ts +9 -0
- package/dist/types/astro/markdown-negotiation.d.ts +3 -0
- package/dist/types/astro/pages.d.ts +10 -0
- package/dist/types/captcha/hcaptcha.d.ts +27 -0
- package/dist/types/captcha/index.d.ts +28 -0
- package/dist/types/captcha/schema.d.ts +29 -0
- package/dist/types/captcha/turnstile.d.ts +28 -0
- package/dist/types/cli/init/scaffold.d.ts +1 -1
- package/dist/types/components/content/api-field.d.ts +62 -0
- package/dist/types/components/content/api-page.d.ts +100 -0
- package/dist/types/components/layout/nav-utils.d.ts +26 -0
- package/dist/types/components/openapi/code-samples.d.ts +29 -0
- package/dist/types/components/openapi/helpers.d.ts +158 -0
- package/dist/types/components/openapi/security.d.ts +95 -0
- package/dist/types/components/openapi/snippets.d.ts +60 -0
- package/dist/types/consent/ethyca.d.ts +48 -0
- package/dist/types/consent/index.d.ts +37 -0
- package/dist/types/consent/native.d.ts +28 -0
- package/dist/types/consent/osano.d.ts +42 -0
- package/dist/types/consent/schema.d.ts +110 -0
- package/dist/types/core/changelog-index.d.ts +8 -0
- package/dist/types/core/config-input.d.ts +217 -23
- package/dist/types/core/data.d.ts +53 -4
- package/dist/types/core/footer.d.ts +8 -0
- package/dist/types/core/i18n-ui.d.ts +88 -0
- package/dist/types/core/includes.d.ts +8 -2
- package/dist/types/core/links.d.ts +8 -0
- package/dist/types/core/localizable.d.ts +7 -0
- package/dist/types/core/page-modes.d.ts +29 -0
- package/dist/types/core/probe.d.ts +2 -0
- package/dist/types/core/project-graph.d.ts +6 -0
- package/dist/types/core/redirect-patterns.d.ts +152 -0
- package/dist/types/core/related.d.ts +40 -0
- package/dist/types/core/schema.d.ts +670 -56
- package/dist/types/core/sources/cache.d.ts +3 -0
- package/dist/types/core/sources/contentful-rich-text.d.ts +11 -2
- package/dist/types/core/sources/contentful.d.ts +17 -1
- package/dist/types/core/sources/lexical.d.ts +5 -0
- package/dist/types/core/sources/normalize.d.ts +20 -1
- package/dist/types/core/sources/read.d.ts +5 -0
- package/dist/types/core/sources/remote.d.ts +37 -10
- package/dist/types/core/sources/sanity.d.ts +1 -1
- package/dist/types/core/types.d.ts +18 -1
- package/dist/types/core/variables.d.ts +42 -0
- package/dist/types/deploy/adapter-output.d.ts +2 -1
- package/dist/types/deploy/adapters/cloudflare.d.ts +7 -5
- package/dist/types/deploy/adapters/node.d.ts +58 -23
- package/dist/types/deploy/adapters/registry.d.ts +10 -0
- package/dist/types/deploy/adapters/types.d.ts +3 -2
- package/dist/types/deploy/node-headers.d.ts +13 -2
- package/dist/types/deploy/platforms/cloudflare.d.ts +15 -7
- package/dist/types/deploy/platforms/netlify.d.ts +7 -0
- package/dist/types/deploy/platforms/node.d.ts +3 -1
- package/dist/types/deploy/platforms/types.d.ts +18 -7
- package/dist/types/deploy/platforms/vercel.d.ts +26 -1
- package/dist/types/deploy/redirects.d.ts +55 -11
- package/dist/types/deploy/sitemap.d.ts +2 -1
- package/dist/types/deploy/vercel-negotiation.d.ts +51 -21
- package/dist/types/markdown/code-title.d.ts +17 -0
- package/dist/types/markdown/features.d.ts +3 -2
- package/dist/types/narration/build.d.ts +70 -0
- package/dist/types/narration/provider.d.ts +26 -0
- package/dist/types/narration/script.d.ts +154 -0
- package/dist/types/openapi/checks.d.ts +27 -0
- package/dist/types/openapi/graphql.d.ts +6 -0
- package/dist/types/openapi/model.d.ts +27 -10
- package/dist/types/openapi/overlay.d.ts +54 -0
- package/dist/types/openapi/parse.d.ts +16 -0
- package/dist/types/openapi/references.d.ts +30 -4
- package/dist/types/ratelimit/cloudflare.d.ts +39 -0
- package/dist/types/ratelimit/index.d.ts +27 -0
- package/dist/types/ratelimit/memory.d.ts +36 -0
- package/dist/types/ratelimit/schema.d.ts +119 -0
- package/dist/types/ratelimit/upstash.d.ts +46 -0
- package/dist/types/ratelimit/wrangler.d.ts +23 -0
- package/dist/types/reference/asyncapi.d.ts +10 -10
- package/dist/types/reference/graphql.d.ts +89 -11
- package/dist/types/reference/index.d.ts +1 -1
- package/dist/types/reference/openapi.d.ts +33 -12
- package/dist/types/reference/options.d.ts +82 -6
- package/dist/types/reference/scalar.d.ts +13 -0
- package/dist/types/reference/schema.d.ts +144 -36
- package/dist/types/search/adapters/registry.d.ts +3 -0
- package/dist/types/search/adapters/typesense.d.ts +14 -4
- package/dist/types/search/build.d.ts +3 -1
- package/dist/types/search/documents.d.ts +12 -1
- package/dist/types/search/orama-index.d.ts +13 -9
- package/dist/types/search/sync/algolia.d.ts +5 -2
- package/dist/types/search/sync/index.d.ts +3 -1
- package/dist/types/search/sync/typesense.d.ts +11 -7
- package/dist/types/seo/metatags.d.ts +20 -0
- package/dist/types/sources/contentful.d.ts +16 -0
- package/dist/types/sources/github-releases.d.ts +8 -1
- package/dist/types/sources/payload.d.ts +2 -0
- package/dist/types/sources/registry.d.ts +54 -0
- package/dist/types/sources/shared.d.ts +3 -0
- package/dist/types/sources/strapi.d.ts +2 -0
- package/docs/01-quickstart.mdx +4 -2
- package/docs/02-deployment.mdx +71 -17
- package/docs/03-upgrading.mdx +4 -4
- package/docs/04-migrating.mdx +1 -1
- package/docs/advanced/changelog.mdx +13 -2
- package/docs/advanced/skills.mdx +15 -1
- package/docs/cli/audit.mdx +51 -8
- package/docs/cli/doctor.mdx +5 -1
- package/docs/cli/evals.mdx +4 -4
- package/docs/cli/index.mdx +1 -0
- package/docs/cli/translate.mdx +1 -0
- package/docs/cli/validate.mdx +4 -3
- package/docs/configuration/analytics.mdx +3 -1
- package/docs/configuration/assistant.mdx +194 -38
- package/docs/configuration/consent.mdx +100 -0
- package/docs/configuration/customization.mdx +8 -6
- package/docs/configuration/export.mdx +5 -3
- package/docs/configuration/index.mdx +64 -5
- package/docs/configuration/meta.ts +3 -0
- package/docs/configuration/narration.mdx +119 -0
- package/docs/configuration/rate-limiting.mdx +90 -0
- package/docs/configuration/search.mdx +63 -12
- package/docs/configuration/theming.mdx +3 -1
- package/docs/content/components.mdx +108 -2
- package/docs/content/frontmatter.mdx +80 -2
- package/docs/content/i18n.mdx +39 -4
- package/docs/content/includes.mdx +16 -0
- package/docs/content/meta.mdx +1 -0
- package/docs/content/meta.ts +1 -0
- package/docs/content/navigation.mdx +32 -10
- package/docs/content/sources/contentful.mdx +35 -0
- package/docs/content/sources/custom.mdx +43 -0
- package/docs/content/sources/github-releases.mdx +39 -0
- package/docs/content/sources/index.mdx +91 -0
- package/docs/content/sources/meta.ts +16 -0
- package/docs/content/sources/notion.mdx +32 -0
- package/docs/content/sources/obsidian.mdx +37 -0
- package/docs/content/sources/payload.mdx +31 -0
- package/docs/content/sources/remote-mdx.mdx +44 -0
- package/docs/content/sources/sanity.mdx +29 -0
- package/docs/content/sources/strapi.mdx +32 -0
- package/docs/content/syntax.mdx +69 -4
- package/docs/content/variables.mdx +41 -0
- package/docs/discoverability/agent-discovery.mdx +29 -2
- package/docs/discoverability/index.mdx +2 -2
- package/docs/discoverability/json-api.mdx +2 -0
- package/docs/discoverability/llms-txt.mdx +2 -2
- package/docs/discoverability/markdown.mdx +3 -1
- package/docs/discoverability/mcp.mdx +4 -0
- package/docs/discoverability/metadata.mdx +17 -0
- package/docs/discoverability/sitemap-and-robots.mdx +1 -1
- package/docs/references/api-pages.mdx +74 -0
- package/docs/references/asyncapi.mdx +4 -2
- package/docs/references/graphql.mdx +14 -2
- package/docs/references/meta.ts +1 -1
- package/docs/references/openapi.mdx +148 -7
- package/docs/references/scalar.mdx +3 -1
- package/package.json +43 -8
- package/skills/blume/SKILL.md +3 -0
- package/skills/blume-migrate/SKILL.md +6 -6
- package/skills/blume-migrate/references/docusaurus.md +7 -7
- package/skills/blume-migrate/references/fumadocs.md +17 -13
- package/skills/blume-migrate/references/mintlify.md +37 -19
- package/skills/blume-migrate/references/nextra.md +10 -7
- package/skills/blume-migrate/references/starlight.md +11 -8
- package/skills/blume-migrate/scripts/mintlify-codemod.mjs +60 -14
- package/skills/blume-write-skill/SKILL.md +82 -0
- package/src/ai/agent-readability.ts +2 -1
- package/src/ai/agent-surface.ts +9 -7
- package/src/ai/ai-catalog.ts +6 -3
- package/src/ai/ask-context.ts +103 -20
- package/src/ai/ask-data.ts +6 -0
- package/src/ai/ask-limits.ts +13 -0
- package/src/ai/ask-tools.ts +142 -0
- package/src/ai/ask.ts +354 -76
- package/src/ai/changelog-markdown.ts +11 -6
- package/src/ai/component-markdown.ts +76 -1
- package/src/ai/cors.ts +14 -3
- package/src/ai/index.ts +12 -0
- package/src/ai/llms.ts +6 -2
- package/src/ai/markdown.ts +2 -1
- package/src/ai/mcp/data.ts +6 -0
- package/src/ai/mcp/query.ts +14 -6
- package/src/ai/openapi-components.ts +36 -6
- package/src/ai/relative-links.ts +4 -38
- package/src/ai/site-skill.ts +274 -0
- package/src/ai/skills.ts +35 -2
- package/src/ai/write-skill.ts +97 -0
- package/src/astro/generate.ts +210 -66
- package/src/astro/index.ts +1 -0
- package/src/astro/integration.ts +42 -4
- package/src/astro/markdown-negotiation.ts +3 -0
- package/src/astro/module-types.ts +9 -1
- package/src/astro/pages.ts +23 -0
- package/src/astro/templates.ts +406 -108
- package/src/astro/variables.ts +31 -0
- package/src/audit/catalog.ts +38 -3
- package/src/audit/checks/contrast.ts +183 -0
- package/src/audit/checks/i18n.ts +2 -3
- package/src/audit/checks/indexability.ts +2 -3
- package/src/audit/checks/links.ts +19 -13
- package/src/audit/checks/network.ts +110 -6
- package/src/audit/checks/redirects.ts +6 -4
- package/src/audit/checks/robots.ts +58 -2
- package/src/audit/checks/sitemap.ts +2 -3
- package/src/audit/redirects.ts +46 -15
- package/src/audit/run.ts +5 -0
- package/src/audit/types.ts +4 -1
- package/src/audit/url.ts +14 -5
- package/src/blume-modules.d.ts +12 -1
- package/src/captcha/client.ts +152 -0
- package/src/captcha/hcaptcha.ts +36 -0
- package/src/captcha/index.ts +28 -0
- package/src/captcha/schema.ts +32 -0
- package/src/captcha/turnstile.ts +38 -0
- package/src/captcha/verify.ts +71 -0
- package/src/cli/args.ts +51 -0
- package/src/cli/build-failure.ts +23 -0
- package/src/cli/command-meta.ts +5 -0
- package/src/cli/commands/audit.ts +10 -1
- package/src/cli/commands/dev.ts +18 -2
- package/src/cli/commands/doctor.ts +67 -28
- package/src/cli/commands/eval.ts +36 -4
- package/src/cli/commands/init.ts +6 -4
- package/src/cli/commands/skill.ts +96 -0
- package/src/cli/commands/validate.ts +10 -1
- package/src/cli/index.ts +5 -0
- package/src/cli/init/scaffold.ts +3 -3
- package/src/cli/prepare.ts +6 -3
- package/src/cli/required-secrets.ts +72 -30
- package/src/components/BlumePage.astro +2 -0
- package/src/components/content/ApiEndpoint.astro +18 -0
- package/src/components/content/ApiField.astro +79 -0
- package/src/components/content/ApiPlayground.astro +66 -0
- package/src/components/content/ApiRail.astro +19 -0
- package/src/components/content/Color.astro +1 -0
- package/src/components/content/FileTree.astro +1 -0
- package/src/components/content/GithubInfo.astro +1 -0
- package/src/components/content/Panel.astro +1 -0
- package/src/components/content/ParamField.astro +25 -0
- package/src/components/content/RequestExample.astro +17 -0
- package/src/components/content/ResponseExample.astro +17 -0
- package/src/components/content/ResponseField.astro +32 -0
- package/src/components/content/Step.astro +1 -0
- package/src/components/content/Tile.astro +1 -0
- package/src/components/content/Tooltip.astro +1 -0
- package/src/components/content/Tree.astro +1 -0
- package/src/components/content/TypeTable.astro +4 -1
- package/src/components/content/View.astro +21 -0
- package/src/components/content/ViewSwitcher.astro +168 -0
- package/src/components/content/api-field.ts +103 -0
- package/src/components/content/api-page.ts +248 -0
- package/src/components/content/mermaid-element.ts +15 -1
- package/src/components/content/view-switcher.ts +71 -0
- package/src/components/index.ts +2 -0
- package/src/components/islands/Assistant.astro +10 -1
- package/src/components/islands/assistant.tsx +104 -14
- package/src/components/islands/code-question.ts +62 -0
- package/src/components/islands/hooks.ts +136 -21
- package/src/components/islands/support-link.ts +68 -0
- package/src/components/layout/Analytics.astro +11 -2
- package/src/components/layout/Banner.astro +14 -10
- package/src/components/layout/Breadcrumbs.astro +6 -2
- package/src/components/layout/ConsentBanner.astro +62 -0
- package/src/components/layout/ConsentHead.astro +38 -0
- package/src/components/layout/Directory.astro +94 -0
- package/src/components/layout/DrawerSwitchers.astro +51 -0
- package/src/components/layout/Empty.astro +2 -2
- package/src/components/layout/Header.astro +122 -80
- package/src/components/layout/LanguageSwitcher.astro +48 -15
- package/src/components/layout/NarrationPlayer.astro +1085 -0
- package/src/components/layout/NavSelector.astro +33 -7
- package/src/components/layout/PageActions.astro +139 -24
- package/src/components/layout/PageFeedback.astro +54 -49
- package/src/components/layout/PageLayout.astro +71 -3
- package/src/components/layout/ReferenceLayout.astro +17 -6
- package/src/components/layout/RelatedPages.astro +42 -0
- package/src/components/layout/RootLayout.astro +318 -47
- package/src/components/layout/Search.astro +47 -19
- package/src/components/layout/SiteFooter.astro +124 -0
- package/src/components/layout/SiteMetatags.astro +16 -0
- package/src/components/layout/TableOfContents.astro +24 -17
- package/src/components/layout/consent/native.ts +79 -0
- package/src/components/layout/consent/types.ts +37 -0
- package/src/components/layout/footer-links.ts +53 -0
- package/src/components/layout/footer-socials.ts +87 -0
- package/src/components/layout/head-scripts.ts +6 -1
- package/src/components/layout/locale-redirect.ts +107 -0
- package/src/components/layout/nav-utils.ts +83 -0
- package/src/components/layout/page-feedback.ts +96 -0
- package/src/components/layout/search/algolia.ts +10 -1
- package/src/components/layout/search/analytics.ts +126 -0
- package/src/components/layout/search/endpoint.ts +48 -5
- package/src/components/layout/search/flexsearch.ts +17 -5
- package/src/components/layout/search/orama-cloud.ts +26 -14
- package/src/components/layout/search/pagefind.ts +114 -5
- package/src/components/layout/search/types.ts +32 -0
- package/src/components/layout/search/typesense.ts +19 -3
- package/src/components/openapi/AsyncApiOperation.astro +14 -7
- package/src/components/openapi/Authorization.astro +10 -0
- package/src/components/openapi/GraphqlOperation.astro +5 -0
- package/src/components/openapi/Operation.astro +184 -13
- package/src/components/openapi/ParametersTable.astro +8 -4
- package/src/components/openapi/Playground.astro +7 -1
- package/src/components/openapi/RequestBody.astro +24 -5
- package/src/components/openapi/RequestPanel.astro +59 -7
- package/src/components/openapi/Responses.astro +7 -4
- package/src/components/openapi/SchemaTable.astro +15 -3
- package/src/components/openapi/async-snippets.ts +65 -9
- package/src/components/openapi/async.ts +123 -29
- package/src/components/openapi/code-samples.ts +97 -0
- package/src/components/openapi/graphql-helpers.ts +35 -12
- package/src/components/openapi/helpers.ts +36 -2
- package/src/components/openapi/message-model.ts +54 -11
- package/src/components/openapi/message.ts +14 -4
- package/src/components/openapi/operation-model.ts +16 -7
- package/src/components/openapi/playground-client.ts +24 -5
- package/src/components/openapi/playground-schema.ts +1 -1
- package/src/components/openapi/schema-tree.ts +44 -14
- package/src/components/openapi/security.ts +16 -3
- package/src/components/openapi/snippets.ts +873 -10
- package/src/components/openapi/validate-json.ts +4 -3
- package/src/components/props.ts +6 -0
- package/src/consent/client.ts +95 -0
- package/src/consent/clients.ts +19 -0
- package/src/consent/ethyca.ts +71 -0
- package/src/consent/head.ts +24 -0
- package/src/consent/index.ts +37 -0
- package/src/consent/init.ts +29 -0
- package/src/consent/native.ts +36 -0
- package/src/consent/osano.ts +59 -0
- package/src/consent/schema.ts +30 -0
- package/src/core/builtin-tags.ts +5 -0
- package/src/core/changelog-index.ts +31 -1
- package/src/core/client-address.ts +19 -0
- package/src/core/component-diagnostics.ts +53 -0
- package/src/core/component-overrides.ts +32 -0
- package/src/core/config-input.ts +225 -23
- package/src/core/data.ts +46 -4
- package/src/core/diagnostics.ts +8 -2
- package/src/core/footer.ts +26 -0
- package/src/core/graph.ts +39 -36
- package/src/core/i18n-ui.ts +84 -2
- package/src/core/includes.ts +21 -4
- package/src/core/links.ts +63 -19
- package/src/core/localizable.ts +26 -0
- package/src/core/navigation.ts +43 -12
- package/src/core/page-modes.ts +56 -0
- package/src/core/probe.ts +26 -6
- package/src/core/project-graph.ts +163 -16
- package/src/core/redirect-patterns.ts +520 -0
- package/src/core/related.ts +131 -0
- package/src/core/schema.ts +339 -66
- package/src/core/sources/cache.ts +6 -0
- package/src/core/sources/contentful-rich-text.ts +29 -6
- package/src/core/sources/contentful.ts +135 -25
- package/src/core/sources/filesystem.ts +26 -4
- package/src/core/sources/github-releases.ts +12 -1
- package/src/core/sources/lexical.ts +15 -10
- package/src/core/sources/mdx-remote.ts +62 -10
- package/src/core/sources/normalize.ts +228 -41
- package/src/core/sources/notion.ts +7 -1
- package/src/core/sources/obsidian.ts +16 -3
- package/src/core/sources/payload.ts +38 -15
- package/src/core/sources/read.ts +8 -3
- package/src/core/sources/remote.ts +72 -15
- package/src/core/sources/resolve.ts +11 -1
- package/src/core/sources/sanity.ts +43 -25
- package/src/core/sources/strapi.ts +2 -2
- package/src/core/types.ts +19 -1
- package/src/core/ui-packs/ar.ts +44 -0
- package/src/core/ui-packs/bg.ts +46 -0
- package/src/core/ui-packs/bn.ts +44 -0
- package/src/core/ui-packs/ca.ts +47 -0
- package/src/core/ui-packs/cs.ts +45 -0
- package/src/core/ui-packs/da.ts +46 -0
- package/src/core/ui-packs/de.ts +47 -0
- package/src/core/ui-packs/el.ts +46 -0
- package/src/core/ui-packs/es.ts +47 -0
- package/src/core/ui-packs/fa.ts +46 -0
- package/src/core/ui-packs/fi.ts +46 -0
- package/src/core/ui-packs/fr.ts +47 -0
- package/src/core/ui-packs/he.ts +44 -0
- package/src/core/ui-packs/hi.ts +45 -0
- package/src/core/ui-packs/hr.ts +46 -0
- package/src/core/ui-packs/hu.ts +45 -0
- package/src/core/ui-packs/id.ts +46 -0
- package/src/core/ui-packs/it.ts +46 -0
- package/src/core/ui-packs/ja.ts +46 -0
- package/src/core/ui-packs/ko.ts +45 -0
- package/src/core/ui-packs/nl.ts +47 -0
- package/src/core/ui-packs/no.ts +45 -0
- package/src/core/ui-packs/pl.ts +46 -0
- package/src/core/ui-packs/pt-br.ts +47 -0
- package/src/core/ui-packs/pt.ts +46 -0
- package/src/core/ui-packs/ro.ts +46 -0
- package/src/core/ui-packs/ru.ts +46 -0
- package/src/core/ui-packs/sk.ts +45 -0
- package/src/core/ui-packs/sr.ts +46 -0
- package/src/core/ui-packs/sv.ts +45 -0
- package/src/core/ui-packs/th.ts +44 -0
- package/src/core/ui-packs/tr.ts +46 -0
- package/src/core/ui-packs/uk.ts +46 -0
- package/src/core/ui-packs/vi.ts +46 -0
- package/src/core/ui-packs/zh-tw.ts +44 -0
- package/src/core/ui-packs/zh.ts +44 -0
- package/src/core/variables.ts +103 -0
- package/src/deploy/adapter-output.ts +7 -2
- package/src/deploy/adapters/cloudflare.ts +7 -5
- package/src/deploy/adapters/node.ts +47 -9
- package/src/deploy/adapters/types.ts +7 -3
- package/src/deploy/artifacts.ts +79 -9
- package/src/deploy/cloudflare-negotiation.ts +35 -5
- package/src/deploy/headers.ts +2 -1
- package/src/deploy/node-headers.ts +63 -9
- package/src/deploy/platforms/cloudflare.ts +45 -9
- package/src/deploy/platforms/netlify.ts +35 -2
- package/src/deploy/platforms/node.ts +12 -2
- package/src/deploy/platforms/types.ts +21 -7
- package/src/deploy/platforms/vercel.ts +149 -17
- package/src/deploy/redirects.ts +151 -24
- package/src/deploy/rss.ts +3 -1
- package/src/deploy/sitemap.ts +39 -5
- package/src/deploy/vercel-negotiation.ts +326 -102
- package/src/eval/agents.ts +18 -1
- package/src/eval/prompts.ts +6 -3
- package/src/eval/report.ts +34 -13
- package/src/eval/run.ts +5 -0
- package/src/markdown/api-rail.ts +259 -0
- package/src/markdown/code-title.ts +35 -9
- package/src/markdown/features.ts +3 -2
- package/src/markdown/fence-meta.ts +2 -0
- package/src/markdown/include.ts +11 -1
- package/src/markdown/index.ts +28 -5
- package/src/markdown/math.ts +4 -4
- package/src/markdown/relative-links.ts +3 -2
- package/src/markdown/variables.ts +56 -0
- package/src/markdown/views.ts +82 -0
- package/src/narration/build.ts +412 -0
- package/src/narration/player.ts +249 -0
- package/src/narration/provider.ts +29 -0
- package/src/narration/script.ts +592 -0
- package/src/og/card.ts +7 -6
- package/src/openapi/checks.ts +273 -0
- package/src/openapi/graphql-build.ts +21 -0
- package/src/openapi/graphql.ts +11 -0
- package/src/openapi/model.ts +72 -27
- package/src/openapi/overlay.ts +256 -0
- package/src/openapi/parse.ts +182 -4
- package/src/openapi/references.ts +64 -8
- package/src/openapi/render-mdx.ts +5 -1
- package/src/openapi/scalar.ts +40 -6
- package/src/openapi/source.ts +40 -15
- package/src/ratelimit/cloudflare.ts +54 -0
- package/src/ratelimit/index.ts +30 -0
- package/src/ratelimit/memory.ts +45 -0
- package/src/ratelimit/runtime.ts +247 -0
- package/src/ratelimit/schema.ts +28 -0
- package/src/ratelimit/upstash.ts +60 -0
- package/src/ratelimit/wrangler.ts +70 -0
- package/src/reference/asyncapi.ts +2 -2
- package/src/reference/graphql.ts +20 -3
- package/src/reference/index.ts +1 -0
- package/src/reference/openapi.ts +21 -7
- package/src/reference/options.ts +80 -8
- package/src/reference/scalar.ts +33 -8
- package/src/registry/eject.ts +23 -5
- package/src/registry/registry.ts +7 -0
- package/src/search/adapters/locale-scope.ts +30 -0
- package/src/search/adapters/typesense.ts +14 -4
- package/src/search/build.ts +21 -3
- package/src/search/documents.ts +26 -2
- package/src/search/orama-index.ts +191 -34
- package/src/search/pagefind-ranking.ts +39 -0
- package/src/search/source-pages.ts +29 -0
- package/src/search/sync/algolia.ts +111 -10
- package/src/search/sync/index.ts +52 -13
- package/src/search/sync/orama-cloud.ts +3 -0
- package/src/search/sync/typesense.ts +76 -26
- package/src/seo/metatags.ts +67 -0
- package/src/sources/contentful.ts +12 -0
- package/src/sources/github-releases.ts +7 -1
- package/src/sources/shared.ts +3 -0
- package/src/theme/chrome-icons.ts +1 -0
- package/src/theme/color.ts +500 -0
- package/src/theme/entry.ts +85 -6
- package/src/theme/palette.ts +121 -45
- package/src/translate/prompts.ts +1 -0
- package/src/translate/validate.ts +31 -3
- package/src/upgrade/upgrade.ts +4 -171
- package/dist/cli/chunk-1d7ve1dm.js.map +0 -12
- package/dist/cli/chunk-2hsdwb9n.js.map +0 -10
- package/dist/cli/chunk-35d4wj9f.js.map +0 -15
- package/dist/cli/chunk-364znk6q.js +0 -75
- package/dist/cli/chunk-364znk6q.js.map +0 -11
- package/dist/cli/chunk-5m5nmvyq.js.map +0 -13
- package/dist/cli/chunk-8ktnccpt.js.map +0 -10
- package/dist/cli/chunk-9t7a85s3.js.map +0 -10
- package/dist/cli/chunk-b07cmahc.js +0 -145
- package/dist/cli/chunk-b07cmahc.js.map +0 -11
- package/dist/cli/chunk-c8chx29p.js.map +0 -36
- package/dist/cli/chunk-e04dxsz1.js +0 -39
- package/dist/cli/chunk-e04dxsz1.js.map +0 -10
- package/dist/cli/chunk-j85vccga.js.map +0 -36
- package/dist/cli/chunk-p3v96n38.js.map +0 -10
- package/dist/cli/chunk-pehfxfta.js.map +0 -10
- package/dist/cli/chunk-pv29h0wf.js.map +0 -190
- package/dist/cli/chunk-q58y5e6a.js.map +0 -10
- package/dist/cli/chunk-vg9r4eb9.js.map +0 -14
- package/dist/cli/chunk-wrr3j9w9.js.map +0 -35
- package/dist/cli/chunk-yfyb25rh.js.map +0 -14
- package/docs/content/sources.mdx +0 -334
- /package/dist/cli/{chunk-tkacnehg.js.map → chunk-3v3ffbrj.js.map} +0 -0
- /package/dist/cli/{chunk-r9rcc4w7.js.map → chunk-8y2kmjv8.js.map} +0 -0
- /package/dist/cli/{chunk-2eytanqx.js.map → chunk-c887fj0s.js.map} +0 -0
- /package/dist/cli/{chunk-akbpwfxc.js.map → chunk-dzwehpy7.js.map} +0 -0
- /package/dist/cli/{chunk-2z928egk.js.map → chunk-ft9vfys6.js.map} +0 -0
- /package/dist/cli/{chunk-a58773jm.js.map → chunk-kma9f6sf.js.map} +0 -0
- /package/dist/cli/{chunk-crgn1q09.js.map → chunk-sds923fa.js.map} +0 -0
- /package/dist/cli/{chunk-acanzt5p.js.map → chunk-tdqhyxfz.js.map} +0 -0
|
@@ -14,22 +14,103 @@
|
|
|
14
14
|
* prerendered Markdown 404 body with the 404 status, instead of the HTML
|
|
15
15
|
* shell, and one that prefers JSON (or asks for a `.json` URL) gets the
|
|
16
16
|
* prerendered problem-details 404.
|
|
17
|
+
*
|
|
18
|
+
* Under `deployment.base` every route here matches the served URL, base
|
|
19
|
+
* included, and names the files where Blume moves them (`static/<base>/`, see
|
|
20
|
+
* {@link rebaseAdapterRoutes}); `base` is the normalized base, `""` for none.
|
|
17
21
|
*/
|
|
18
22
|
|
|
23
|
+
import { mountBasePath } from "../core/base-path.ts";
|
|
19
24
|
import { SVG_ASSET_HEADERS } from "./headers.ts";
|
|
20
25
|
|
|
21
|
-
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
26
|
+
/*
|
|
27
|
+
* The `accept` header conditions. Dev and the Cloudflare Worker negotiate the
|
|
28
|
+
* way `prefersMarkdown` (`astro/markdown-negotiation.ts`) does: media types in
|
|
29
|
+
* any case, and Markdown only when its q-value is above zero and at least
|
|
30
|
+
* HTML's. A routing condition is a regex over the whole header, with no
|
|
31
|
+
* arithmetic, so the comparison is spelled as two routes per rewrite:
|
|
32
|
+
*
|
|
33
|
+
* - a Markdown entry at full weight (no q-value, or `q=1`) always wins, since
|
|
34
|
+
* nothing can outrank it;
|
|
35
|
+
* - a Markdown entry below full weight wins only when the header has no
|
|
36
|
+
* `text/html` entry above zero (a `missing` condition), since two q-values
|
|
37
|
+
* below 1 can't be compared. That case, like `text/markdown;q=0.9,
|
|
38
|
+
* text/html;q=0.8`, gets HTML on Vercel where dev and Cloudflare send
|
|
39
|
+
* Markdown.
|
|
40
|
+
*
|
|
41
|
+
* Every pattern is anchored at both ends and lets `(?:.*,)?` absorb the
|
|
42
|
+
* earlier list entries, so it holds under full-string and substring matching
|
|
43
|
+
* alike. Case-insensitivity is spelled out letter by letter and the patterns
|
|
44
|
+
* are lookaround-free, so they read the same in RE2, PCRE, and JavaScript.
|
|
45
|
+
* Like dev, only the first `q=` parameter of an entry counts, and a `q=`
|
|
46
|
+
* value is read as a decimal. Browsers never send `text/markdown`, so
|
|
47
|
+
* ordinary page requests are unaffected.
|
|
30
48
|
*/
|
|
31
|
-
|
|
32
|
-
|
|
49
|
+
|
|
50
|
+
/** `word` in any case, one character class per letter: `[Tt][Ee][Xx][Tt]`. */
|
|
51
|
+
const anyCase = (word: string): string =>
|
|
52
|
+
word.replaceAll(/[a-z]/gu, (letter) => `[${letter.toUpperCase()}${letter}]`);
|
|
53
|
+
|
|
54
|
+
/** An entry's parameters before its first `q=`: any that isn't one. */
|
|
55
|
+
const OTHER_PARAMS = String.raw`(?:;\s*(?:[^\sq;,][^;,]*|q(?:[^=;,][^;,]*)?)?)*`;
|
|
56
|
+
|
|
57
|
+
/** Everything after an entry's first `q=` value, up to the next entry. */
|
|
58
|
+
const LATER_PARAMS = "(?:;[^,]*)?";
|
|
59
|
+
|
|
60
|
+
/** A `q=` value of 1 or more: full weight. */
|
|
61
|
+
const FULL_WEIGHT = String.raw`0*[1-9][0-9]*(?:\.[0-9]*)?`;
|
|
62
|
+
|
|
63
|
+
/** A `q=` value above zero and below 1. */
|
|
64
|
+
const PARTIAL_WEIGHT = String.raw`0*\.[0-9]*[1-9][0-9]*`;
|
|
65
|
+
|
|
66
|
+
/** A `q=` value that isn't zero: it has a character besides `0` and `.`. */
|
|
67
|
+
const NONZERO_WEIGHT = String.raw`[\s0.]*[^\s0.;,][^;,]*`;
|
|
68
|
+
|
|
69
|
+
/** A header with an entry of `type` weighed by `weight`, or by no `q=` when it's optional. */
|
|
70
|
+
const acceptEntry = (type: string, weight: string, optional: boolean) =>
|
|
71
|
+
String.raw`^(?:.*,)?\s*${type}\s*${OTHER_PARAMS}(?:;\s*q=\s*${weight}\s*${LATER_PARAMS})${optional ? "?" : ""}(?:,.*)?$`;
|
|
72
|
+
|
|
73
|
+
/** A header with a `type` entry at full weight. */
|
|
74
|
+
const fullWeight = (type: string) => acceptEntry(type, FULL_WEIGHT, true);
|
|
75
|
+
|
|
76
|
+
/** A header with a `type` entry weighed above zero and below 1. */
|
|
77
|
+
const partialWeight = (type: string) =>
|
|
78
|
+
acceptEntry(type, PARTIAL_WEIGHT, false);
|
|
79
|
+
|
|
80
|
+
/** A header with a `text/html` entry weighed above zero. */
|
|
81
|
+
const ACCEPT_HTML = acceptEntry(anyCase("text/html"), NONZERO_WEIGHT, true);
|
|
82
|
+
|
|
83
|
+
const MARKDOWN_TYPE = `${anyCase("text/")}(?:${anyCase("x-")})?${anyCase("markdown")}`;
|
|
84
|
+
|
|
85
|
+
const JSON_TYPE = `${anyCase("application/")}(?:${anyCase("problem")}\\+)?${anyCase("json")}`;
|
|
86
|
+
|
|
87
|
+
/** One header condition on a Build Output route. */
|
|
88
|
+
export interface VercelCondition {
|
|
89
|
+
key?: string;
|
|
90
|
+
type: string;
|
|
91
|
+
value?: string;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** The conditions of one route: all of `has`, none of `missing`. */
|
|
95
|
+
export interface AcceptConditions {
|
|
96
|
+
has: VercelCondition[];
|
|
97
|
+
missing?: VercelCondition[];
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const accept = (value: string): VercelCondition => ({
|
|
101
|
+
key: "accept",
|
|
102
|
+
type: "header",
|
|
103
|
+
value,
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
/** The pair of conditions a route answering `type` is written once for each. */
|
|
107
|
+
const preferring = (type: string): AcceptConditions[] => [
|
|
108
|
+
{ has: [accept(fullWeight(type))] },
|
|
109
|
+
{ has: [accept(partialWeight(type))], missing: [accept(ACCEPT_HTML)] },
|
|
110
|
+
];
|
|
111
|
+
|
|
112
|
+
/** When a client prefers `text/markdown` (or `text/x-markdown`) over HTML. */
|
|
113
|
+
export const ACCEPT_MARKDOWN_CONDITIONS = preferring(MARKDOWN_TYPE);
|
|
33
114
|
|
|
34
115
|
/**
|
|
35
116
|
* The JSON counterpart, for the problem-details 404: `application/json` or
|
|
@@ -37,8 +118,7 @@ export const ACCEPT_MARKDOWN_HEADER_VALUE =
|
|
|
37
118
|
* (the catch-all wildcard does not match), so ordinary page requests are
|
|
38
119
|
* unaffected.
|
|
39
120
|
*/
|
|
40
|
-
export const
|
|
41
|
-
"(.*,)?\\s*application/(problem\\+)?json(\\s*[;,].*)?$";
|
|
121
|
+
export const ACCEPT_JSON_CONDITIONS = preferring(JSON_TYPE);
|
|
42
122
|
|
|
43
123
|
/**
|
|
44
124
|
* A Build Output API route — the subset these helpers read and write. Parsed
|
|
@@ -49,23 +129,29 @@ export interface VercelRoute {
|
|
|
49
129
|
continue?: boolean;
|
|
50
130
|
dest?: string;
|
|
51
131
|
handle?: string;
|
|
52
|
-
has?:
|
|
132
|
+
has?: VercelCondition[];
|
|
53
133
|
headers?: Record<string, string>;
|
|
134
|
+
missing?: VercelCondition[];
|
|
54
135
|
src?: string;
|
|
55
136
|
status?: number;
|
|
56
137
|
}
|
|
57
138
|
|
|
139
|
+
/** `route` once per condition pair, so it fires when either holds. */
|
|
140
|
+
const conditioned = (
|
|
141
|
+
route: VercelRoute,
|
|
142
|
+
conditions: readonly AcceptConditions[]
|
|
143
|
+
): VercelRoute[] => conditions.map((condition) => ({ ...route, ...condition }));
|
|
144
|
+
|
|
58
145
|
/** Whether a parsed route field is a real string (the config is raw JSON). */
|
|
59
146
|
const isString = (value: string | undefined): value is string =>
|
|
60
147
|
typeof value === "string";
|
|
61
148
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
];
|
|
149
|
+
/** The Markdown conditions' `has` values, to recognize a route this module wrote. */
|
|
150
|
+
const MARKDOWN_VALUES = new Set(
|
|
151
|
+
ACCEPT_MARKDOWN_CONDITIONS.flatMap(({ has }) =>
|
|
152
|
+
has.map((condition) => condition.value)
|
|
153
|
+
)
|
|
154
|
+
);
|
|
69
155
|
|
|
70
156
|
const VARY_ACCEPT = { vary: "Accept" };
|
|
71
157
|
|
|
@@ -78,44 +164,6 @@ const NOT_FOUND_JSON_DEST = "/404.json";
|
|
|
78
164
|
/** The adapter's own not-found fallback — the anchor the Markdown 404 precedes. */
|
|
79
165
|
const NOT_FOUND_HTML_DEST = "/404.html";
|
|
80
166
|
|
|
81
|
-
/**
|
|
82
|
-
* Miss-phase routes that answer a missing page with the Markdown 404 body: any
|
|
83
|
-
* path when the client prefers Markdown, and any `.md`/`.mdx` URL (a request
|
|
84
|
-
* for a raw-Markdown mirror that has no page wants Markdown back, not the HTML
|
|
85
|
-
* shell). Both keep the 404 status. Spliced immediately before the adapter's
|
|
86
|
-
* `/404.html` fallback, so they run after every server route (the MCP
|
|
87
|
-
* endpoint, server islands, images) has had its turn and never hijack a
|
|
88
|
-
* request one of those would have answered.
|
|
89
|
-
*/
|
|
90
|
-
const NOT_FOUND_MARKDOWN_ROUTES: readonly VercelRoute[] = [
|
|
91
|
-
{
|
|
92
|
-
dest: NOT_FOUND_MARKDOWN_DEST,
|
|
93
|
-
has: ACCEPT_MARKDOWN_CONDITION,
|
|
94
|
-
headers: VARY_ACCEPT,
|
|
95
|
-
src: "^/.*$",
|
|
96
|
-
status: 404,
|
|
97
|
-
},
|
|
98
|
-
{ dest: NOT_FOUND_MARKDOWN_DEST, src: "^/.*\\.mdx?$", status: 404 },
|
|
99
|
-
];
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* The JSON 404's miss-phase routes, the problem-details twin of the Markdown
|
|
103
|
-
* ones: any path when the client prefers JSON, and any `.json` URL no file
|
|
104
|
-
* backs. Spliced at the same anchor, after every server route — so the
|
|
105
|
-
* `/api/` catch-all (which answers its own namespace with a problem document)
|
|
106
|
-
* has already had its turn.
|
|
107
|
-
*/
|
|
108
|
-
const NOT_FOUND_JSON_ROUTES: readonly VercelRoute[] = [
|
|
109
|
-
{
|
|
110
|
-
dest: NOT_FOUND_JSON_DEST,
|
|
111
|
-
has: ACCEPT_JSON_CONDITION,
|
|
112
|
-
headers: VARY_ACCEPT,
|
|
113
|
-
src: "^/.*$",
|
|
114
|
-
status: 404,
|
|
115
|
-
},
|
|
116
|
-
{ dest: NOT_FOUND_JSON_DEST, src: "^/.*\\.json$", status: 404 },
|
|
117
|
-
];
|
|
118
|
-
|
|
119
167
|
/** Which prerendered 404 twins the build emitted, so their routes get wired. */
|
|
120
168
|
export interface NotFoundVariants {
|
|
121
169
|
json?: boolean;
|
|
@@ -140,6 +188,53 @@ const REGEX_SPECIALS = /[$()*+.?[\]^{|}\\]/gu;
|
|
|
140
188
|
const routePattern = (route: string): string =>
|
|
141
189
|
encodeURI(route).replace(REGEX_SPECIALS, "\\$&");
|
|
142
190
|
|
|
191
|
+
/**
|
|
192
|
+
* The `src` matching the homepage: `^/$`, or the base itself under one, served
|
|
193
|
+
* without a trailing slash (the adapter's trailing-slash route strips it).
|
|
194
|
+
*/
|
|
195
|
+
const homeSource = (base: string): string =>
|
|
196
|
+
`^${routePattern(mountBasePath(base, "/"))}$`;
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Miss-phase routes that answer a missing page with the Markdown 404 body: any
|
|
200
|
+
* path when the client prefers Markdown, and any `.md`/`.mdx` URL (a request
|
|
201
|
+
* for a raw-Markdown mirror that has no page wants Markdown back, not the HTML
|
|
202
|
+
* shell). Both keep the 404 status. Spliced immediately before the adapter's
|
|
203
|
+
* `/404.html` fallback, so they run after every server route (the MCP
|
|
204
|
+
* endpoint, server islands, images) has had its turn and never hijack a
|
|
205
|
+
* request one of those would have answered.
|
|
206
|
+
*/
|
|
207
|
+
const notFoundMarkdownRoutes = (base: string): VercelRoute[] => {
|
|
208
|
+
const dest = mountBasePath(base, NOT_FOUND_MARKDOWN_DEST);
|
|
209
|
+
const prefix = routePattern(base);
|
|
210
|
+
return [
|
|
211
|
+
...conditioned(
|
|
212
|
+
{ dest, headers: VARY_ACCEPT, src: `^${prefix}/.*$`, status: 404 },
|
|
213
|
+
ACCEPT_MARKDOWN_CONDITIONS
|
|
214
|
+
),
|
|
215
|
+
{ dest, src: `^${prefix}/.*\\.mdx?$`, status: 404 },
|
|
216
|
+
];
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* The JSON 404's miss-phase routes, the problem-details twin of the Markdown
|
|
221
|
+
* ones: any path when the client prefers JSON, and any `.json` URL no file
|
|
222
|
+
* backs. Spliced at the same anchor, after every server route — so the
|
|
223
|
+
* `/api/` catch-all (which answers its own namespace with a problem document)
|
|
224
|
+
* has already had its turn.
|
|
225
|
+
*/
|
|
226
|
+
const notFoundJsonRoutes = (base: string): VercelRoute[] => {
|
|
227
|
+
const dest = mountBasePath(base, NOT_FOUND_JSON_DEST);
|
|
228
|
+
const prefix = routePattern(base);
|
|
229
|
+
return [
|
|
230
|
+
...conditioned(
|
|
231
|
+
{ dest, headers: VARY_ACCEPT, src: `^${prefix}/.*$`, status: 404 },
|
|
232
|
+
ACCEPT_JSON_CONDITIONS
|
|
233
|
+
),
|
|
234
|
+
{ dest, src: `^${prefix}/.*\\.json$`, status: 404 },
|
|
235
|
+
];
|
|
236
|
+
};
|
|
237
|
+
|
|
143
238
|
/** Group patterns so each group's alternation stays under the `src` limit. */
|
|
144
239
|
const chunkPatterns = (patterns: readonly string[]): string[][] => {
|
|
145
240
|
const chunks: string[][] = [];
|
|
@@ -190,41 +285,49 @@ export interface NegotiationRoutes {
|
|
|
190
285
|
* rewrite also stamps `x-markdown-tokens` — the estimated token count of the
|
|
191
286
|
* homepage mirror (Cloudflare's Markdown for Agents convention). Only the home
|
|
192
287
|
* route can carry it: the other rewrites are chunked alternations spanning
|
|
193
|
-
* many pages, and a count is per-page.
|
|
288
|
+
* many pages, and a count is per-page. Under a `base`, each path is matched
|
|
289
|
+
* and rewritten where it's served (`/docs` → `/docs/index.md`).
|
|
194
290
|
*/
|
|
195
291
|
export const buildNegotiationRoutes = (
|
|
196
292
|
routePaths: readonly string[],
|
|
197
|
-
homeTokens?: number
|
|
293
|
+
homeTokens?: number,
|
|
294
|
+
base = ""
|
|
198
295
|
): NegotiationRoutes => {
|
|
199
296
|
const home = routePaths.includes("/");
|
|
200
297
|
const rest = routePaths
|
|
201
298
|
.filter((path) => path !== "/")
|
|
202
|
-
.map((path) => routePattern(path));
|
|
299
|
+
.map((path) => routePattern(mountBasePath(base, path)));
|
|
203
300
|
const chunks = chunkPatterns(rest);
|
|
204
301
|
|
|
205
302
|
const rewriteRoutes: VercelRoute[] = home
|
|
206
|
-
?
|
|
303
|
+
? conditioned(
|
|
207
304
|
{
|
|
208
|
-
dest: "/index.md",
|
|
209
|
-
has: ACCEPT_MARKDOWN_CONDITION,
|
|
305
|
+
dest: mountBasePath(base, "/index.md"),
|
|
210
306
|
headers:
|
|
211
307
|
homeTokens === undefined
|
|
212
308
|
? VARY_ACCEPT
|
|
213
309
|
: { ...VARY_ACCEPT, "x-markdown-tokens": String(homeTokens) },
|
|
214
|
-
src:
|
|
310
|
+
src: homeSource(base),
|
|
215
311
|
},
|
|
216
|
-
|
|
312
|
+
ACCEPT_MARKDOWN_CONDITIONS
|
|
313
|
+
)
|
|
217
314
|
: [];
|
|
218
315
|
for (const chunk of chunks) {
|
|
219
|
-
rewriteRoutes.push(
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
316
|
+
rewriteRoutes.push(
|
|
317
|
+
...conditioned(
|
|
318
|
+
{
|
|
319
|
+
dest: "$1.md",
|
|
320
|
+
headers: VARY_ACCEPT,
|
|
321
|
+
src: `^(${chunk.join("|")})/?$`,
|
|
322
|
+
},
|
|
323
|
+
ACCEPT_MARKDOWN_CONDITIONS
|
|
324
|
+
)
|
|
325
|
+
);
|
|
225
326
|
}
|
|
226
327
|
|
|
227
|
-
const headerChunks = chunkPatterns(
|
|
328
|
+
const headerChunks = chunkPatterns(
|
|
329
|
+
home ? [routePattern(mountBasePath(base, "/")), ...rest] : rest
|
|
330
|
+
);
|
|
228
331
|
const headerRoutes: VercelRoute[] = headerChunks.map((chunk) => ({
|
|
229
332
|
continue: true,
|
|
230
333
|
headers: VARY_ACCEPT,
|
|
@@ -234,9 +337,6 @@ export const buildNegotiationRoutes = (
|
|
|
234
337
|
return { headerRoutes, rewriteRoutes };
|
|
235
338
|
};
|
|
236
339
|
|
|
237
|
-
/** The `src` of the injected homepage `Link` header route. */
|
|
238
|
-
const HOME_SRC = "^/$";
|
|
239
|
-
|
|
240
340
|
const ALLOW_ANY_ORIGIN = "*";
|
|
241
341
|
|
|
242
342
|
/**
|
|
@@ -244,18 +344,18 @@ const ALLOW_ANY_ORIGIN = "*";
|
|
|
244
344
|
* one static discovery document (see `crossOriginDiscoveryPaths`), so a
|
|
245
345
|
* registry reading it from another origin isn't refused by the browser.
|
|
246
346
|
*/
|
|
247
|
-
const corsRoute = (path: string): VercelRoute => ({
|
|
347
|
+
const corsRoute = (path: string, base: string): VercelRoute => ({
|
|
248
348
|
continue: true,
|
|
249
349
|
headers: { "access-control-allow-origin": ALLOW_ANY_ORIGIN },
|
|
250
|
-
src: `^${routePattern(path)}$`,
|
|
350
|
+
src: `^${routePattern(mountBasePath(base, path))}$`,
|
|
251
351
|
});
|
|
252
352
|
|
|
253
353
|
/**
|
|
254
354
|
* The `src` of the route stamping the content-source SVG headers: every `.svg`
|
|
255
|
-
* under `/blume-assets/`.
|
|
256
|
-
* Output tree without the deployment base, like every path matched here.
|
|
355
|
+
* under `/blume-assets/`.
|
|
257
356
|
*/
|
|
258
|
-
const
|
|
357
|
+
const svgAssetSource = (base: string): string =>
|
|
358
|
+
String.raw`^${routePattern(base)}/blume-assets/.+\.svg$`;
|
|
259
359
|
|
|
260
360
|
/**
|
|
261
361
|
* A main-phase `continue` route stamping the sandbox headers
|
|
@@ -263,7 +363,7 @@ const SVG_ASSET_SRC = String.raw`^/blume-assets/.+\.svg$`;
|
|
|
263
363
|
* static layer — where the prerendered asset endpoint's own headers never
|
|
264
364
|
* reach.
|
|
265
365
|
*/
|
|
266
|
-
const svgAssetRoute = (): VercelRoute => ({
|
|
366
|
+
const svgAssetRoute = (base: string): VercelRoute => ({
|
|
267
367
|
continue: true,
|
|
268
368
|
headers: Object.fromEntries(
|
|
269
369
|
Object.entries(SVG_ASSET_HEADERS).map(([name, value]) => [
|
|
@@ -271,7 +371,7 @@ const svgAssetRoute = (): VercelRoute => ({
|
|
|
271
371
|
value,
|
|
272
372
|
])
|
|
273
373
|
),
|
|
274
|
-
src:
|
|
374
|
+
src: svgAssetSource(base),
|
|
275
375
|
});
|
|
276
376
|
|
|
277
377
|
/** Whether a route is a `corsRoute` — the same three-field shape test as the others. */
|
|
@@ -291,22 +391,23 @@ const isCorsRoute = (route: VercelRoute): boolean =>
|
|
|
291
391
|
* no user-authored route competes in this file); the Markdown 404 routes by
|
|
292
392
|
* their `/404.md` destination.
|
|
293
393
|
*/
|
|
294
|
-
const isNegotiationRoute = (route: VercelRoute): boolean =>
|
|
295
|
-
route.has?.some(
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
(route.dest === NOT_FOUND_JSON_DEST &&
|
|
394
|
+
const isNegotiationRoute = (route: VercelRoute, base: string): boolean =>
|
|
395
|
+
route.has?.some((condition) => MARKDOWN_VALUES.has(condition.value)) ===
|
|
396
|
+
true ||
|
|
397
|
+
(route.dest === mountBasePath(base, NOT_FOUND_MARKDOWN_DEST) &&
|
|
398
|
+
route.status === 404) ||
|
|
399
|
+
(route.dest === mountBasePath(base, NOT_FOUND_JSON_DEST) &&
|
|
400
|
+
route.status === 404) ||
|
|
300
401
|
(route.continue === true &&
|
|
301
402
|
route.headers?.vary === "Accept" &&
|
|
302
403
|
isString(route.src) &&
|
|
303
404
|
Object.keys(route).length === 3) ||
|
|
304
405
|
(route.continue === true &&
|
|
305
406
|
isString(route.headers?.link) &&
|
|
306
|
-
route.src ===
|
|
407
|
+
route.src === homeSource(base) &&
|
|
307
408
|
Object.keys(route).length === 3) ||
|
|
308
409
|
isCorsRoute(route) ||
|
|
309
|
-
(route.continue === true && route.src ===
|
|
410
|
+
(route.continue === true && route.src === svgAssetSource(base));
|
|
310
411
|
|
|
311
412
|
/**
|
|
312
413
|
* Splice the negotiation routes into a Build Output `config.json`, plus — when
|
|
@@ -325,7 +426,9 @@ const isNegotiationRoute = (route: VercelRoute): boolean =>
|
|
|
325
426
|
* phase right before the adapter's `/404.html` fallback — and nowhere when
|
|
326
427
|
* that fallback is absent, since a `dest` with no file behind it would serve
|
|
327
428
|
* nothing. With `svgAssets`, a main-phase route also sandboxes the SVGs a
|
|
328
|
-
* content source downloaded (see {@link svgAssetRoute}).
|
|
429
|
+
* content source downloaded (see {@link svgAssetRoute}). Under a `base`, every
|
|
430
|
+
* route matches and names paths beneath it, and the fallback anchor is the
|
|
431
|
+
* one {@link rebaseAdapterRoutes} moved there. Returns the updated JSON
|
|
329
432
|
* text (tab-indented, like the adapter's own output), or `null` when there is
|
|
330
433
|
* nowhere safe to splice: an unparsable config, no `routes` array, or no
|
|
331
434
|
* `handle: "filesystem"` marker to anchor the splice.
|
|
@@ -338,7 +441,8 @@ export const injectNegotiationRoutes = (
|
|
|
338
441
|
homeTokens?: number,
|
|
339
442
|
notFound: NotFoundVariants = {},
|
|
340
443
|
corsPaths: readonly string[] = [],
|
|
341
|
-
svgAssets = false
|
|
444
|
+
svgAssets = false,
|
|
445
|
+
base = ""
|
|
342
446
|
): string | null => {
|
|
343
447
|
const overrideEntries = Object.entries(contentTypeOverrides ?? {});
|
|
344
448
|
let config: {
|
|
@@ -358,7 +462,9 @@ export const injectNegotiationRoutes = (
|
|
|
358
462
|
// user's own override of the same path is simply refreshed.
|
|
359
463
|
config.overrides = { ...config.overrides, [path]: { contentType } };
|
|
360
464
|
}
|
|
361
|
-
const routes = config.routes.filter(
|
|
465
|
+
const routes = config.routes.filter(
|
|
466
|
+
(route) => !isNegotiationRoute(route, base)
|
|
467
|
+
);
|
|
362
468
|
const filesystemIndex = routes.findIndex(
|
|
363
469
|
(route) => route.handle === "filesystem"
|
|
364
470
|
);
|
|
@@ -367,30 +473,32 @@ export const injectNegotiationRoutes = (
|
|
|
367
473
|
}
|
|
368
474
|
const { headerRoutes, rewriteRoutes } = buildNegotiationRoutes(
|
|
369
475
|
routePaths,
|
|
370
|
-
homeTokens
|
|
476
|
+
homeTokens,
|
|
477
|
+
base
|
|
371
478
|
);
|
|
372
479
|
if (homeLinkHeader) {
|
|
373
480
|
headerRoutes.push({
|
|
374
481
|
continue: true,
|
|
375
482
|
headers: { link: homeLinkHeader },
|
|
376
|
-
src:
|
|
483
|
+
src: homeSource(base),
|
|
377
484
|
});
|
|
378
485
|
}
|
|
379
|
-
headerRoutes.push(...corsPaths.map(corsRoute));
|
|
486
|
+
headerRoutes.push(...corsPaths.map((path) => corsRoute(path, base)));
|
|
380
487
|
if (svgAssets) {
|
|
381
|
-
headerRoutes.push(svgAssetRoute());
|
|
488
|
+
headerRoutes.push(svgAssetRoute(base));
|
|
382
489
|
}
|
|
383
490
|
// Headers first: `continue` routes accumulate, so a request the rewrite
|
|
384
491
|
// route then terminates (Markdown negotiation on the homepage) still carries
|
|
385
492
|
// the Link header.
|
|
386
493
|
routes.splice(filesystemIndex, 0, ...headerRoutes, ...rewriteRoutes);
|
|
387
494
|
const notFoundRoutes = [
|
|
388
|
-
...(notFound.markdown ?
|
|
389
|
-
...(notFound.json ?
|
|
495
|
+
...(notFound.markdown ? notFoundMarkdownRoutes(base) : []),
|
|
496
|
+
...(notFound.json ? notFoundJsonRoutes(base) : []),
|
|
390
497
|
];
|
|
391
498
|
if (notFoundRoutes.length > 0) {
|
|
499
|
+
const fallbackDest = mountBasePath(base, NOT_FOUND_HTML_DEST);
|
|
392
500
|
const fallbackIndex = routes.findIndex(
|
|
393
|
-
(route) => route.status === 404 && route.dest ===
|
|
501
|
+
(route) => route.status === 404 && route.dest === fallbackDest
|
|
394
502
|
);
|
|
395
503
|
if (fallbackIndex !== -1) {
|
|
396
504
|
routes.splice(fallbackIndex, 0, ...notFoundRoutes);
|
|
@@ -399,3 +507,119 @@ export const injectNegotiationRoutes = (
|
|
|
399
507
|
config.routes = routes;
|
|
400
508
|
return `${JSON.stringify(config, null, "\t")}\n`;
|
|
401
509
|
};
|
|
510
|
+
|
|
511
|
+
/**
|
|
512
|
+
* Splice routes for the pattern redirects (see `vercelPatternRoutes`) into a
|
|
513
|
+
* Build Output `config.json`, in the main phase just ahead of
|
|
514
|
+
* `handle: "filesystem"`: after the exact redirects the adapter puts first,
|
|
515
|
+
* so an exact path still wins. A second pass replaces its own routes. Returns
|
|
516
|
+
* the updated JSON text, or `null` when there is nowhere safe to splice: an
|
|
517
|
+
* unparsable config, no `routes` array, or no `handle: "filesystem"` marker.
|
|
518
|
+
*/
|
|
519
|
+
export const injectRedirectRoutes = (
|
|
520
|
+
configText: string,
|
|
521
|
+
redirectRoutes: readonly VercelRoute[]
|
|
522
|
+
): string | null => {
|
|
523
|
+
let config: { routes?: VercelRoute[] };
|
|
524
|
+
try {
|
|
525
|
+
config = JSON.parse(configText);
|
|
526
|
+
} catch {
|
|
527
|
+
return null;
|
|
528
|
+
}
|
|
529
|
+
if (!Array.isArray(config.routes)) {
|
|
530
|
+
return null;
|
|
531
|
+
}
|
|
532
|
+
const ours = new Set(redirectRoutes.map((route) => route.src));
|
|
533
|
+
const routes = config.routes.filter(
|
|
534
|
+
(route) => !(ours.has(route.src) && isString(route.headers?.Location))
|
|
535
|
+
);
|
|
536
|
+
const filesystemIndex = routes.findIndex(
|
|
537
|
+
(route) => route.handle === "filesystem"
|
|
538
|
+
);
|
|
539
|
+
if (filesystemIndex === -1) {
|
|
540
|
+
return null;
|
|
541
|
+
}
|
|
542
|
+
routes.splice(filesystemIndex, 0, ...redirectRoutes);
|
|
543
|
+
config.routes = routes;
|
|
544
|
+
return `${JSON.stringify(config, null, "\t")}\n`;
|
|
545
|
+
};
|
|
546
|
+
|
|
547
|
+
/**
|
|
548
|
+
* The trailing-slash route `trailingSlash: "never"` gives the adapter's config
|
|
549
|
+
* (`^/(.*)/$` → `/$1`): it keeps whatever path it strips the slash from, base
|
|
550
|
+
* and all, so it already serves a based site.
|
|
551
|
+
*/
|
|
552
|
+
const isTrailingSlashRoute = (route: VercelRoute): boolean =>
|
|
553
|
+
route.headers?.Location === "/$1";
|
|
554
|
+
|
|
555
|
+
/** The pattern body of the root route, anchored (`^/$`) or not (`/`). */
|
|
556
|
+
const ROOT_BODY = /^\/\$?$/u;
|
|
557
|
+
|
|
558
|
+
/**
|
|
559
|
+
* Re-anchor an adapter route pattern under the base, whose escaped form is
|
|
560
|
+
* `prefix`: each matches a base-less path from its start, and the root route
|
|
561
|
+
* becomes the base itself, served without a trailing slash.
|
|
562
|
+
*/
|
|
563
|
+
const rebaseSource = (src: string, prefix: string): string => {
|
|
564
|
+
const body = src.startsWith("^") ? src.slice(1) : src;
|
|
565
|
+
return `^${prefix}${ROOT_BODY.test(body) ? "$" : body}`;
|
|
566
|
+
};
|
|
567
|
+
|
|
568
|
+
/**
|
|
569
|
+
* Move the adapter's routes under `deployment.base`, to match the static files
|
|
570
|
+
* Blume moves to `static/<base>/`. `@astrojs/vercel` routes a server build as
|
|
571
|
+
* if it were served from the root: its route patterns (the `_astro/` cache
|
|
572
|
+
* header, every server route) match base-less paths, its 404 fallback names
|
|
573
|
+
* `/404.html`, and it joins the base onto each redirect with no slash on the
|
|
574
|
+
* `from` side and a second time on the `to` side, which Astro hands it
|
|
575
|
+
* already based (`^/docsold$` → `/docs/docs/new`). Each pattern is
|
|
576
|
+
* re-anchored under the base and the fallback names the base's `404.html`;
|
|
577
|
+
* the adapter's redirects make way for `redirectRoutes`, the exact redirects
|
|
578
|
+
* as the host matches them. Returns the updated JSON text, or `null` when
|
|
579
|
+
* there is nowhere safe to splice: an unparsable config, no `routes` array,
|
|
580
|
+
* or no `handle: "filesystem"` marker.
|
|
581
|
+
*/
|
|
582
|
+
export const rebaseAdapterRoutes = (
|
|
583
|
+
configText: string,
|
|
584
|
+
base: string,
|
|
585
|
+
redirectRoutes: readonly VercelRoute[]
|
|
586
|
+
): string | null => {
|
|
587
|
+
let config: { routes?: VercelRoute[] };
|
|
588
|
+
try {
|
|
589
|
+
config = JSON.parse(configText);
|
|
590
|
+
} catch {
|
|
591
|
+
return null;
|
|
592
|
+
}
|
|
593
|
+
if (!Array.isArray(config.routes)) {
|
|
594
|
+
return null;
|
|
595
|
+
}
|
|
596
|
+
const filesystemIndex = config.routes.findIndex(
|
|
597
|
+
(route) => route.handle === "filesystem"
|
|
598
|
+
);
|
|
599
|
+
if (filesystemIndex === -1) {
|
|
600
|
+
return null;
|
|
601
|
+
}
|
|
602
|
+
const prefix = routePattern(base);
|
|
603
|
+
const routes = config.routes.flatMap((route, index): VercelRoute[] => {
|
|
604
|
+
// Ahead of the filesystem handler, the adapter writes its redirects and
|
|
605
|
+
// nothing else with a `Location`.
|
|
606
|
+
if (index < filesystemIndex && isString(route.headers?.Location)) {
|
|
607
|
+
return isTrailingSlashRoute(route) ? [route] : [];
|
|
608
|
+
}
|
|
609
|
+
const rebased = { ...route };
|
|
610
|
+
if (isString(route.src)) {
|
|
611
|
+
rebased.src = rebaseSource(route.src, prefix);
|
|
612
|
+
}
|
|
613
|
+
if (route.status === 404 && route.dest === NOT_FOUND_HTML_DEST) {
|
|
614
|
+
rebased.dest = mountBasePath(base, NOT_FOUND_HTML_DEST);
|
|
615
|
+
}
|
|
616
|
+
return [rebased];
|
|
617
|
+
});
|
|
618
|
+
routes.splice(
|
|
619
|
+
routes.findIndex((route) => route.handle === "filesystem"),
|
|
620
|
+
0,
|
|
621
|
+
...redirectRoutes
|
|
622
|
+
);
|
|
623
|
+
config.routes = routes;
|
|
624
|
+
return `${JSON.stringify(config, null, "\t")}\n`;
|
|
625
|
+
};
|
package/src/eval/agents.ts
CHANGED
|
@@ -188,7 +188,24 @@ const CLAUDE_READER_MAX_TURNS = "25";
|
|
|
188
188
|
const CLAUDE_JUDGE_MAX_TURNS = "1";
|
|
189
189
|
|
|
190
190
|
const claudeArgs = (context: InvocationContext): string[] => {
|
|
191
|
-
|
|
191
|
+
// `--tools ""` turns off every Claude Code built-in, including ones the
|
|
192
|
+
// deny list below doesn't name (`Monitor` runs shell commands, `Skill`
|
|
193
|
+
// loads the user's skills), so a reader has only the docs MCP tools and the
|
|
194
|
+
// judge has no tools at all. The deny list stays as a second layer.
|
|
195
|
+
// `--setting-sources ""` is codex's `--ignore-user-config`: no settings
|
|
196
|
+
// files, so the user's hooks, plugins, and CLAUDE.md can't hand the reader
|
|
197
|
+
// context the docs never gave it. Not `--bare`, which also stops reading a
|
|
198
|
+
// subscription login and fails with "Not logged in".
|
|
199
|
+
const base = [
|
|
200
|
+
"-p",
|
|
201
|
+
"--output-format",
|
|
202
|
+
"json",
|
|
203
|
+
"--strict-mcp-config",
|
|
204
|
+
"--tools",
|
|
205
|
+
"",
|
|
206
|
+
"--setting-sources",
|
|
207
|
+
"",
|
|
208
|
+
];
|
|
192
209
|
if (context.mcp) {
|
|
193
210
|
const allowed = MCP_TOOL_NAMES.map(
|
|
194
211
|
(tool) => `mcp__${MCP_SERVER_NAME}__${tool}`
|
package/src/eval/prompts.ts
CHANGED
|
@@ -40,8 +40,11 @@ Reply with ONLY this JSON object on a single line, no markdown fences:
|
|
|
40
40
|
{"pass": true|false, "score": 0.0-1.0, "missing": ["expected facts absent or contradicted"], "notes": "one sentence"}`;
|
|
41
41
|
};
|
|
42
42
|
|
|
43
|
-
/**
|
|
44
|
-
|
|
43
|
+
/**
|
|
44
|
+
* The `--fix` handoff prompt: where the report is, the ground rules, and the
|
|
45
|
+
* `blume eval` command that verifies the fixes (the run's own flags).
|
|
46
|
+
*/
|
|
47
|
+
export const evalFixPrompt = (reportPath: string, command: string): string =>
|
|
45
48
|
`Fix the documentation gaps found by \`blume eval\` in this project.
|
|
46
49
|
|
|
47
50
|
The full report is at ${reportPath}. It is JSON: each entry in \`eval.results\` with status "fail" is one question the documentation could not answer. Each carries the \`question\`, the \`expected\` facts, the judge's \`missing\` facts, and the reader agent's \`answer\` (what the docs currently convey). The matching \`diagnostics\` entry names the source \`file\` of the page that should answer it.
|
|
@@ -51,7 +54,7 @@ Work through every failed question:
|
|
|
51
54
|
2. Edit the documentation so it states the missing facts explicitly. Add prose, not filler; keep the page's voice.
|
|
52
55
|
3. Never delete questions from the evals file or weaken expected facts.
|
|
53
56
|
|
|
54
|
-
When you are done, run \`
|
|
57
|
+
When you are done, run \`${command}\` to verify, and repeat until every question passes.`;
|
|
55
58
|
|
|
56
59
|
/** The `eval init` prompt: draft a starter evals file from the docs. */
|
|
57
60
|
export const initPrompt = (evalsPath: string): string =>
|