blume 2.0.1 → 2.0.3
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/CHANGELOG.md +147 -0
- package/dist/cli/{chunk-qwsrynx5.js → chunk-1d7ve1dm.js} +38 -19
- package/dist/cli/{chunk-qwsrynx5.js.map → chunk-1d7ve1dm.js.map} +4 -4
- package/dist/cli/{chunk-s6jhgk0q.js → chunk-2eytanqx.js} +2 -2
- package/dist/cli/{chunk-kdp5q7ke.js → chunk-2hsdwb9n.js} +18 -19
- package/dist/cli/{chunk-kdp5q7ke.js.map → chunk-2hsdwb9n.js.map} +2 -2
- package/dist/cli/{chunk-hdpx1tax.js → chunk-2z928egk.js} +5 -5
- package/dist/cli/{chunk-jwyddg7y.js → chunk-35d4wj9f.js} +30 -24
- package/dist/cli/chunk-35d4wj9f.js.map +15 -0
- package/dist/cli/{chunk-ah61y8py.js → chunk-364znk6q.js} +2 -2
- package/dist/cli/{chunk-jts8mvcz.js → chunk-3em5wd2y.js} +25 -6
- package/dist/cli/{chunk-jts8mvcz.js.map → chunk-3em5wd2y.js.map} +3 -3
- package/dist/cli/{chunk-s1p84fyh.js → chunk-5f86nr5m.js} +63 -22
- package/dist/cli/chunk-5f86nr5m.js.map +11 -0
- package/dist/cli/{chunk-2hn4b8z7.js → chunk-5m5nmvyq.js} +170 -76
- package/dist/cli/chunk-5m5nmvyq.js.map +13 -0
- package/dist/cli/{chunk-epjnccmv.js → chunk-5xvm6tfj.js} +18 -15
- package/dist/cli/chunk-5xvm6tfj.js.map +10 -0
- package/dist/cli/{chunk-fz5wtpmh.js → chunk-6dsbexzp.js} +18 -15
- package/dist/cli/chunk-6dsbexzp.js.map +10 -0
- package/dist/cli/{chunk-vtk4a6dg.js → chunk-8ktnccpt.js} +1 -1
- package/dist/cli/{chunk-6hsn950k.js → chunk-9t7a85s3.js} +178 -48
- package/dist/cli/chunk-9t7a85s3.js.map +10 -0
- package/dist/cli/{chunk-fxypxtvm.js → chunk-a58773jm.js} +2 -2
- package/dist/cli/{chunk-mb2919y2.js → chunk-acanzt5p.js} +17 -6
- package/dist/cli/chunk-acanzt5p.js.map +10 -0
- package/dist/cli/{chunk-27g6wdth.js → chunk-akbpwfxc.js} +90 -26
- package/dist/cli/chunk-akbpwfxc.js.map +10 -0
- package/dist/cli/{chunk-wm7js3j9.js → chunk-b07cmahc.js} +2 -2
- package/dist/cli/{chunk-wgm7m9qk.js → chunk-c8chx29p.js} +179 -51
- package/dist/cli/chunk-c8chx29p.js.map +36 -0
- package/dist/cli/{chunk-qs4q5p4e.js → chunk-crgn1q09.js} +32 -14
- package/dist/cli/chunk-crgn1q09.js.map +10 -0
- package/dist/cli/chunk-e04dxsz1.js +39 -0
- package/dist/cli/chunk-e04dxsz1.js.map +10 -0
- package/dist/cli/{chunk-yt5n7ppj.js → chunk-ey84smr6.js} +17 -7
- package/dist/cli/chunk-ey84smr6.js.map +10 -0
- package/dist/cli/{chunk-f2z5v128.js → chunk-g4hq16wv.js} +14 -15
- package/dist/cli/{chunk-f2z5v128.js.map → chunk-g4hq16wv.js.map} +2 -2
- package/dist/cli/{chunk-fa25z98p.js → chunk-ga0pf4aj.js} +9 -8
- package/dist/cli/chunk-ga0pf4aj.js.map +11 -0
- package/dist/cli/{chunk-kpf8rrjc.js → chunk-hm3vjy5s.js} +109 -58
- package/dist/cli/chunk-hm3vjy5s.js.map +19 -0
- package/dist/cli/{chunk-fs23ddbb.js → chunk-j85vccga.js} +625 -750
- package/dist/cli/chunk-j85vccga.js.map +36 -0
- package/dist/cli/{chunk-ch6g3ar0.js → chunk-p3v96n38.js} +6 -6
- package/dist/cli/{chunk-ch6g3ar0.js.map → chunk-p3v96n38.js.map} +3 -3
- package/dist/cli/{chunk-q5163e60.js → chunk-p73c0m7w.js} +21 -19
- package/dist/cli/chunk-p73c0m7w.js.map +11 -0
- package/dist/cli/{chunk-dh8cwk36.js → chunk-pehfxfta.js} +24 -9
- package/dist/cli/chunk-pehfxfta.js.map +10 -0
- package/dist/cli/{chunk-qkqwkpte.js → chunk-pv29h0wf.js} +3688 -1313
- package/dist/cli/chunk-pv29h0wf.js.map +190 -0
- package/dist/cli/{chunk-6vm74dry.js → chunk-q58y5e6a.js} +10 -10
- package/dist/cli/{chunk-6vm74dry.js.map → chunk-q58y5e6a.js.map} +3 -3
- package/dist/cli/{chunk-zxcczpyx.js → chunk-r20tn01b.js} +1 -1
- package/dist/cli/{chunk-m3vmjgmq.js → chunk-r9rcc4w7.js} +16 -8
- package/dist/cli/chunk-r9rcc4w7.js.map +10 -0
- package/dist/cli/{chunk-5shv93fd.js → chunk-tkacnehg.js} +2 -2
- package/dist/cli/{chunk-zxh4d9vy.js → chunk-tzmab476.js} +4 -4
- package/dist/cli/{chunk-yw7dm696.js → chunk-vg9r4eb9.js} +24 -11
- package/dist/cli/chunk-vg9r4eb9.js.map +14 -0
- package/dist/cli/{chunk-79jhk4py.js → chunk-wrr3j9w9.js} +260 -132
- package/dist/cli/chunk-wrr3j9w9.js.map +35 -0
- package/dist/cli/{chunk-6crbhc3x.js → chunk-yfyb25rh.js} +54 -27
- package/dist/cli/chunk-yfyb25rh.js.map +14 -0
- package/dist/cli/index.js +162 -35
- package/dist/cli/index.js.map +4 -4
- package/dist/types/ai/agent-surface.d.ts +32 -0
- package/dist/types/ai/api-catalog.d.ts +7 -1
- package/dist/types/ai/ask-context.d.ts +7 -0
- package/dist/types/ai/component-markdown.d.ts +4 -4
- package/dist/types/ai/link-headers.d.ts +8 -1
- package/dist/types/ai/openapi-components.d.ts +5 -2
- package/dist/types/ai/relative-links.d.ts +11 -4
- package/dist/types/ai/skills.d.ts +4 -1
- package/dist/types/ai/static-expression.d.ts +28 -0
- package/dist/types/ai/tar.d.ts +1 -3
- package/dist/types/analytics/databuddy.d.ts +43 -0
- package/dist/types/analytics/index.d.ts +4 -0
- package/dist/types/analytics/one-dollar-stats.d.ts +48 -0
- package/dist/types/analytics/schema.d.ts +28 -0
- package/dist/types/astro/integration.d.ts +3 -2
- 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 +24 -1
- package/dist/types/core/config-input.d.ts +13 -11
- package/dist/types/core/config.d.ts +2 -2
- package/dist/types/core/directive-diagnostics.d.ts +12 -0
- package/dist/types/core/graph.d.ts +2 -0
- package/dist/types/core/heading-markers.d.ts +5 -7
- package/dist/types/core/i18n-ui.d.ts +31 -0
- package/dist/types/core/i18n.d.ts +9 -1
- package/dist/types/core/last-modified.d.ts +10 -0
- 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 +13 -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 +59 -13
- package/dist/types/core/sources/github-releases.d.ts +5 -0
- package/dist/types/core/sources/lower.d.ts +38 -13
- package/dist/types/core/sources/normalize.d.ts +23 -2
- 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/sources/watch.d.ts +12 -5
- package/dist/types/core/standard-schema.d.ts +5 -0
- package/dist/types/core/types.d.ts +9 -0
- package/dist/types/deploy/adapters/node.d.ts +5 -2
- package/dist/types/deploy/adapters/types.d.ts +7 -0
- package/dist/types/deploy/artifacts.d.ts +6 -4
- package/dist/types/deploy/cloudflare-negotiation.d.ts +3 -2
- package/dist/types/deploy/headers.d.ts +36 -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 +15 -0
- package/dist/types/deploy/platforms/vercel.d.ts +3 -2
- package/dist/types/deploy/redirects.d.ts +31 -15
- package/dist/types/deploy/vercel-negotiation.d.ts +3 -2
- package/dist/types/markdown/directives.d.ts +62 -0
- package/dist/types/markdown/features.d.ts +21 -0
- package/dist/types/markdown/mdast.d.ts +63 -0
- package/dist/types/openapi/asyncapi.d.ts +4 -2
- package/dist/types/openapi/model.d.ts +20 -6
- package/dist/types/search/sync/algolia.d.ts +3 -1
- package/docs/01-quickstart.mdx +3 -2
- package/docs/02-deployment.mdx +20 -9
- package/docs/08-faq.mdx +10 -3
- package/docs/advanced/changelog.mdx +1 -1
- package/docs/advanced/custom-pages.mdx +7 -5
- package/docs/cli/audit.mdx +19 -3
- package/docs/cli/doctor.mdx +2 -2
- package/docs/cli/evals.mdx +4 -4
- package/docs/cli/index.mdx +4 -1
- package/docs/cli/translate.mdx +4 -4
- package/docs/cli/version.mdx +1 -1
- package/docs/configuration/analytics.mdx +42 -2
- package/docs/configuration/assistant.mdx +1 -1
- package/docs/configuration/customization.mdx +6 -3
- package/docs/configuration/index.mdx +5 -3
- package/docs/configuration/search.mdx +2 -2
- package/docs/content/components.mdx +2 -2
- package/docs/content/frontmatter.mdx +5 -1
- package/docs/content/i18n.mdx +3 -1
- package/docs/content/index.mdx +8 -4
- package/docs/content/islands.mdx +1 -1
- package/docs/content/meta.mdx +7 -3
- package/docs/content/navigation.mdx +29 -4
- package/docs/content/sources.mdx +18 -16
- package/docs/content/syntax.mdx +14 -0
- package/docs/content/versioning.mdx +2 -1
- package/docs/discoverability/agent-discovery.mdx +22 -8
- package/docs/discoverability/index.mdx +4 -3
- package/docs/discoverability/llms-txt.mdx +2 -5
- package/docs/discoverability/markdown.mdx +6 -4
- package/docs/discoverability/mcp.mdx +4 -0
- package/docs/discoverability/metadata.mdx +3 -2
- package/docs/discoverability/open-graph.mdx +8 -4
- package/docs/discoverability/rss.mdx +4 -2
- package/docs/references/asyncapi.mdx +2 -2
- package/docs/references/graphql.mdx +2 -2
- package/docs/references/openapi.mdx +6 -4
- package/package.json +1 -1
- package/skills/blume-migrate/SKILL.md +6 -6
- package/skills/blume-migrate/references/docusaurus.md +6 -6
- package/skills/blume-migrate/references/fumadocs.md +1 -1
- 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 +2 -2
- package/skills/blume-migrate/references/starlight.md +5 -5
- package/skills/blume-migrate/scripts/mintlify-codemod.mjs +9 -4
- package/skills/blume-update-docs/references/audit-checklist.md +1 -1
- package/src/ai/agent-readability.ts +2 -2
- package/src/ai/agent-surface.ts +56 -0
- package/src/ai/ai-catalog.ts +6 -2
- package/src/ai/api/handlers.ts +2 -2
- package/src/ai/api/spec.ts +17 -4
- package/src/ai/api-catalog.ts +13 -3
- package/src/ai/ask-context.ts +14 -2
- package/src/ai/ask-data.ts +26 -12
- package/src/ai/changelog-markdown.ts +2 -2
- package/src/ai/component-markdown.ts +43 -37
- package/src/ai/link-headers.ts +22 -8
- package/src/ai/llms.ts +22 -10
- package/src/ai/markdown.ts +23 -11
- package/src/ai/mcp/discovery.ts +2 -2
- package/src/ai/mcp/query.ts +2 -2
- package/src/ai/mcp/server.ts +80 -9
- package/src/ai/openapi-components.ts +22 -6
- package/src/ai/relative-links.ts +99 -15
- package/src/ai/serializers.ts +2 -1
- package/src/ai/skills.ts +14 -1
- package/src/ai/static-expression.ts +416 -0
- package/src/ai/tar.ts +139 -12
- package/src/ai/visibility.ts +45 -14
- package/src/analytics/databuddy.ts +67 -0
- package/src/analytics/head.ts +8 -0
- package/src/analytics/index.ts +7 -0
- package/src/analytics/one-dollar-stats.ts +86 -0
- package/src/analytics/posthog.ts +21 -3
- package/src/analytics/schema.ts +4 -0
- package/src/astro/generate.ts +72 -28
- package/src/astro/include-hmr.ts +31 -12
- package/src/astro/include-refresh.ts +19 -8
- package/src/astro/integration.ts +108 -14
- package/src/astro/runtime-modules.ts +28 -13
- package/src/astro/templates.ts +139 -57
- 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 +22 -1
- 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/graph.ts +3 -1
- package/src/audit/report.ts +54 -17
- package/src/audit/run.ts +13 -9
- package/src/audit/snapshot.ts +5 -0
- package/src/audit/types.ts +18 -0
- package/src/audit/url.ts +37 -6
- package/src/cli/args.ts +32 -0
- package/src/cli/build-failure.ts +50 -0
- package/src/cli/commands/audit.ts +11 -1
- package/src/cli/commands/build.ts +19 -5
- package/src/cli/commands/check.ts +2 -0
- package/src/cli/commands/doctor.ts +3 -1
- package/src/cli/commands/eval.ts +20 -18
- package/src/cli/commands/init.ts +15 -5
- package/src/cli/commands/preview.ts +15 -0
- package/src/cli/commands/sync.ts +2 -0
- package/src/cli/commands/translate.ts +18 -18
- package/src/cli/commands/upgrade.ts +11 -0
- package/src/cli/commands/validate.ts +3 -1
- package/src/cli/dev-lock.ts +157 -37
- 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/report-format.ts +11 -6
- package/src/components/colors.ts +19 -0
- package/src/components/content/AccordionItem.astro +26 -22
- package/src/components/content/Badge.astro +7 -12
- package/src/components/content/Card.astro +2 -2
- package/src/components/content/Component.astro +11 -5
- 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/Tab.astro +0 -1
- package/src/components/content/Tabs.astro +58 -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 +20 -0
- package/src/components/content/base-href.ts +14 -22
- package/src/components/content/inline-markdown.ts +27 -7
- package/src/components/copy-feedback.ts +35 -8
- package/src/components/islands/assistant.tsx +37 -6
- package/src/components/islands/base-path.ts +47 -10
- package/src/components/islands/hooks.ts +42 -21
- package/src/components/islands/webmcp.ts +16 -10
- package/src/components/layout/Banner.astro +23 -4
- package/src/components/layout/Breadcrumbs.astro +5 -2
- package/src/components/layout/DiscoveryLinks.astro +9 -5
- package/src/components/layout/Header.astro +23 -10
- package/src/components/layout/LanguageSwitcher.astro +2 -2
- package/src/components/layout/Logo.astro +5 -0
- package/src/components/layout/NavSelector.astro +8 -3
- package/src/components/layout/NavTabMenu.astro +133 -0
- package/src/components/layout/NavTree.astro +31 -12
- package/src/components/layout/NavTreeCache.astro +5 -2
- package/src/components/layout/NavTreeScript.astro +45 -5
- package/src/components/layout/PageActions.astro +4 -3
- package/src/components/layout/PageLayout.astro +28 -13
- package/src/components/layout/Pagination.astro +3 -3
- package/src/components/layout/ReferenceLayout.astro +4 -1
- package/src/components/layout/RootLayout.astro +25 -12
- package/src/components/layout/Search.astro +38 -14
- package/src/components/layout/VersionBanner.astro +2 -2
- package/src/components/layout/analytics-client.ts +14 -0
- package/src/components/layout/toc-active.ts +41 -0
- package/src/components/layout/toc-element.ts +8 -14
- package/src/components/openapi/ApiTagOperations.astro +2 -2
- package/src/components/openapi/AsyncApiOperation.astro +7 -4
- package/src/components/openapi/GraphqlChip.astro +2 -2
- package/src/components/openapi/GraphqlType.astro +11 -3
- package/src/components/openapi/MessageComposer.astro +1 -1
- package/src/components/openapi/Operation.astro +23 -5
- package/src/components/openapi/PanelTabs.astro +4 -1
- package/src/components/openapi/Playground.astro +8 -2
- package/src/components/openapi/RequestPanel.astro +13 -6
- package/src/components/openapi/SchemaProperty.astro +11 -33
- package/src/components/openapi/SchemaTable.astro +34 -52
- package/src/components/openapi/async.ts +38 -6
- package/src/components/openapi/helpers.ts +100 -12
- package/src/components/openapi/message-composer.ts +14 -1
- package/src/components/openapi/message-model.ts +12 -2
- package/src/components/openapi/message.ts +21 -3
- package/src/components/openapi/operation-model.ts +119 -17
- package/src/components/openapi/panel.ts +31 -5
- package/src/components/openapi/param-style.ts +181 -0
- package/src/components/openapi/playground-client.ts +110 -23
- package/src/components/openapi/playground-schema.ts +25 -6
- package/src/components/openapi/request.ts +192 -26
- package/src/components/openapi/schema-tree.ts +209 -0
- package/src/components/openapi/snippets.ts +113 -19
- package/src/components/openapi/validate-json.ts +1 -1
- package/src/components/openapi/ws-client.ts +18 -2
- package/src/core/base-path.ts +69 -8
- package/src/core/config-input.ts +13 -11
- package/src/core/config.ts +18 -4
- package/src/core/diagnostics.ts +219 -30
- package/src/core/directive-diagnostics.ts +99 -0
- package/src/core/frontmatter.ts +21 -18
- package/src/core/graph.ts +120 -11
- package/src/core/heading-markers.ts +5 -18
- package/src/core/i18n-ui.ts +39 -2
- package/src/core/i18n.ts +44 -5
- package/src/core/last-modified.ts +25 -3
- package/src/core/links.ts +7 -4
- package/src/core/load-module.ts +20 -0
- package/src/core/locale-links.ts +22 -18
- package/src/core/manifest.ts +3 -2
- package/src/core/meta.ts +89 -12
- package/src/core/nav-diagnostics.ts +56 -1
- package/src/core/navigation.ts +272 -83
- package/src/core/ordering-prefix.ts +27 -0
- package/src/core/project-graph.ts +50 -6
- package/src/core/safe-href.ts +53 -1
- package/src/core/safe-links.ts +11 -2
- package/src/core/schema.ts +94 -18
- package/src/core/sources/assets.ts +83 -41
- package/src/core/sources/contentful-rich-text.ts +28 -20
- package/src/core/sources/contentful.ts +25 -12
- package/src/core/sources/filesystem.ts +25 -3
- package/src/core/sources/github-releases.ts +131 -11
- package/src/core/sources/lexical.ts +30 -20
- package/src/core/sources/lower.ts +276 -56
- package/src/core/sources/mdx-remote.ts +52 -16
- package/src/core/sources/normalize.ts +456 -119
- package/src/core/sources/notion.ts +77 -34
- package/src/core/sources/obsidian.ts +40 -9
- package/src/core/sources/payload.ts +1 -0
- package/src/core/sources/portable-text.ts +85 -49
- 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 +28 -19
- package/src/core/sources/strapi.ts +1 -0
- package/src/core/sources/types.ts +31 -0
- package/src/core/sources/watch.ts +20 -7
- package/src/core/standard-schema.ts +10 -6
- package/src/core/types.ts +9 -0
- package/src/core/ui-packs/ar.ts +13 -0
- package/src/core/ui-packs/bg.ts +13 -0
- package/src/core/ui-packs/bn.ts +13 -0
- package/src/core/ui-packs/ca.ts +13 -0
- package/src/core/ui-packs/cs.ts +13 -0
- package/src/core/ui-packs/da.ts +13 -0
- package/src/core/ui-packs/de.ts +13 -0
- package/src/core/ui-packs/el.ts +13 -0
- package/src/core/ui-packs/es.ts +13 -0
- package/src/core/ui-packs/fa.ts +13 -0
- package/src/core/ui-packs/fi.ts +13 -0
- package/src/core/ui-packs/fr.ts +13 -0
- package/src/core/ui-packs/he.ts +13 -0
- package/src/core/ui-packs/hi.ts +13 -0
- package/src/core/ui-packs/hr.ts +13 -0
- package/src/core/ui-packs/hu.ts +13 -0
- package/src/core/ui-packs/id.ts +13 -0
- package/src/core/ui-packs/it.ts +13 -0
- package/src/core/ui-packs/ja.ts +13 -0
- package/src/core/ui-packs/ko.ts +13 -0
- package/src/core/ui-packs/nl.ts +13 -0
- package/src/core/ui-packs/no.ts +13 -0
- package/src/core/ui-packs/pl.ts +13 -0
- package/src/core/ui-packs/pt-br.ts +13 -0
- package/src/core/ui-packs/pt.ts +13 -0
- package/src/core/ui-packs/ro.ts +13 -0
- package/src/core/ui-packs/ru.ts +13 -0
- package/src/core/ui-packs/sk.ts +13 -0
- package/src/core/ui-packs/sr.ts +13 -0
- package/src/core/ui-packs/sv.ts +13 -0
- package/src/core/ui-packs/th.ts +13 -0
- package/src/core/ui-packs/tr.ts +13 -0
- package/src/core/ui-packs/uk.ts +13 -0
- package/src/core/ui-packs/vi.ts +13 -0
- package/src/core/ui-packs/zh-tw.ts +13 -0
- package/src/core/ui-packs/zh.ts +13 -0
- package/src/core/version-cut.ts +69 -17
- 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 +52 -11
- package/src/deploy/cloudflare-negotiation.ts +27 -16
- package/src/deploy/headers.ts +75 -55
- package/src/deploy/node-headers.ts +148 -27
- package/src/deploy/platforms/cloudflare.ts +13 -3
- package/src/deploy/platforms/netlify.ts +83 -5
- package/src/deploy/platforms/node.ts +8 -5
- package/src/deploy/platforms/static.ts +2 -0
- package/src/deploy/platforms/types.ts +15 -0
- package/src/deploy/platforms/vercel.ts +10 -3
- package/src/deploy/redirects.ts +68 -21
- package/src/deploy/robots.ts +2 -2
- package/src/deploy/rss.ts +4 -3
- package/src/deploy/sitemap.ts +7 -5
- 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 +74 -29
- package/src/markdown/directives.ts +242 -36
- package/src/markdown/features.ts +17 -0
- package/src/markdown/index.ts +13 -9
- package/src/markdown/mdast.ts +5 -2
- package/src/markdown/relative-links.ts +15 -27
- package/src/markdown/route-snapshot.ts +37 -0
- package/src/og/card.ts +149 -9
- package/src/og/derive.ts +156 -5
- package/src/og/index.ts +1 -0
- package/src/openapi/asyncapi.ts +4 -2
- package/src/openapi/graphql-build.ts +28 -2
- package/src/openapi/model.ts +99 -27
- package/src/openapi/proxy.ts +63 -10
- package/src/openapi/render-mdx.ts +51 -3
- package/src/registry/eject.ts +297 -43
- package/src/search/adapters/version-scope.ts +30 -0
- package/src/search/documents.ts +89 -27
- package/src/search/popular.ts +2 -1
- package/src/search/sync/algolia.ts +36 -2
- package/src/seo/jsonld.ts +7 -3
- 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 +76 -24
- package/src/translate/run.ts +14 -8
- package/src/translate/validate.ts +14 -2
- package/src/translate/work-list.ts +91 -19
- package/src/upgrade/upgrade.ts +36 -4
- package/dist/cli/chunk-27g6wdth.js.map +0 -10
- package/dist/cli/chunk-2hn4b8z7.js.map +0 -12
- package/dist/cli/chunk-6crbhc3x.js.map +0 -14
- package/dist/cli/chunk-6hsn950k.js.map +0 -10
- package/dist/cli/chunk-79jhk4py.js.map +0 -35
- package/dist/cli/chunk-82bbrxdn.js +0 -51
- package/dist/cli/chunk-82bbrxdn.js.map +0 -10
- package/dist/cli/chunk-abh8yjkn.js +0 -31
- package/dist/cli/chunk-abh8yjkn.js.map +0 -10
- package/dist/cli/chunk-ce574jw2.js +0 -23
- package/dist/cli/chunk-ce574jw2.js.map +0 -10
- package/dist/cli/chunk-dh8cwk36.js.map +0 -10
- package/dist/cli/chunk-epjnccmv.js.map +0 -10
- package/dist/cli/chunk-fa25z98p.js.map +0 -11
- package/dist/cli/chunk-fs23ddbb.js.map +0 -35
- package/dist/cli/chunk-fz5wtpmh.js.map +0 -10
- package/dist/cli/chunk-jwyddg7y.js.map +0 -15
- package/dist/cli/chunk-kpf8rrjc.js.map +0 -19
- package/dist/cli/chunk-m3vmjgmq.js.map +0 -10
- package/dist/cli/chunk-mb2919y2.js.map +0 -10
- package/dist/cli/chunk-q5163e60.js.map +0 -11
- package/dist/cli/chunk-qkqwkpte.js.map +0 -182
- package/dist/cli/chunk-qs4q5p4e.js.map +0 -10
- package/dist/cli/chunk-s1p84fyh.js.map +0 -10
- package/dist/cli/chunk-wgm7m9qk.js.map +0 -36
- package/dist/cli/chunk-yt5n7ppj.js.map +0 -10
- package/dist/cli/chunk-yw7dm696.js.map +0 -14
- /package/dist/cli/{chunk-s6jhgk0q.js.map → chunk-2eytanqx.js.map} +0 -0
- /package/dist/cli/{chunk-hdpx1tax.js.map → chunk-2z928egk.js.map} +0 -0
- /package/dist/cli/{chunk-ah61y8py.js.map → chunk-364znk6q.js.map} +0 -0
- /package/dist/cli/{chunk-vtk4a6dg.js.map → chunk-8ktnccpt.js.map} +0 -0
- /package/dist/cli/{chunk-fxypxtvm.js.map → chunk-a58773jm.js.map} +0 -0
- /package/dist/cli/{chunk-wm7js3j9.js.map → chunk-b07cmahc.js.map} +0 -0
- /package/dist/cli/{chunk-zxcczpyx.js.map → chunk-r20tn01b.js.map} +0 -0
- /package/dist/cli/{chunk-5shv93fd.js.map → chunk-tkacnehg.js.map} +0 -0
- /package/dist/cli/{chunk-zxh4d9vy.js.map → chunk-tzmab476.js.map} +0 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/cli/commands/eval.ts", "../src/eval/prompts.ts", "../src/eval/report.ts", "../src/eval/run.ts", "../src/eval/schema.ts", "../src/eval/findings.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import { existsSync } from \"node:fs\";\n\nimport { defineCommand } from \"citty\";\nimport { resolve } from \"pathe\";\n\nimport { AGENTS, launchAgent } from \"../../audit/agent.ts\";\nimport type { AgentKind } from \"../../audit/agent.ts\";\nimport { BlumeError } from \"../../core/diagnostics.ts\";\nimport { scanProject } from \"../../core/project-graph.ts\";\nimport { evalFixPrompt, initPrompt } from \"../../eval/prompts.ts\";\nimport {\n evalReportJson,\n fixLines,\n headerLine,\n questionDetails,\n questionLine,\n startLine,\n summaryLine,\n warningLines,\n writeEvalReport,\n} from \"../../eval/report.ts\";\nimport { passFraction, runEval } from \"../../eval/run.ts\";\nimport type { EvalResult } from \"../../eval/run.ts\";\nimport { EvalsFileError, loadEvalsFile } from \"../../eval/schema.ts\";\nimport { parseTimeoutSeconds } from \"../args.ts\";\nimport { commandMeta } from \"../command-meta.ts\";\nimport { reportInternalError } from \"../internal-error.ts\";\nimport { flushStdout, logger, reportDiagnostics } from \"../log.ts\";\n\nconst DEFAULT_FILE = \"evals.yaml\";\n\n/** Reader wall-clock ceiling per question, in seconds. */\nconst DEFAULT_TIMEOUT_S = 180;\n\nconst isAgentKind = (value: string): value is AgentKind => value in AGENTS;\n\n/**\n * Launch the interactive agent CLI, turning a missing executable into the\n * install hint. Only `ENOENT` means \"not installed\" — any other spawn failure\n * (`EACCES`, `EMFILE`, …) must surface as itself.\n */\nconst notInstalled = (agent: AgentKind): never => {\n const cli = AGENTS[agent];\n logger.error(\n `${cli.name} (\\`${cli.bin}\\`) was not found on PATH. Install it with \\`${cli.install}\\`.`\n );\n return process.exit(1);\n};\n\nconst launchAgentCode = async (\n agent: AgentKind,\n prompt: string\n): Promise<number> => {\n try {\n return await launchAgent(AGENTS[agent].bin, prompt);\n } catch (error) {\n // SAFETY: only the `code` tag is inspected; a spawn failure throws an\n // ErrnoException, and any other thrown value fails the comparison and\n // rethrows unchanged.\n if ((error as NodeJS.ErrnoException)?.code !== \"ENOENT\") {\n throw error;\n }\n return notInstalled(agent);\n }\n};\n\ninterface EvalFlags {\n action?: string;\n agent: string;\n file: string;\n fix?: boolean;\n json?: boolean;\n threshold?: string;\n timeout?: string;\n}\n\n/** Validate the flag surface, exiting with a message on the first offense. */\nconst parseFlags = (args: EvalFlags) => {\n if (!isAgentKind(args.agent)) {\n logger.error(`Invalid --agent \"${args.agent}\" (use codex | claude).`);\n process.exit(1);\n }\n if (args.action !== undefined && args.action !== \"init\") {\n logger.error(`Unknown action \"${args.action}\" (did you mean \"init\"?).`);\n process.exit(1);\n }\n if (args.json && args.fix) {\n logger.error(\"--json and --fix are mutually exclusive.\");\n process.exit(1);\n }\n const threshold = args.threshold === undefined ? 1 : Number(args.threshold);\n // A bare `--threshold` (or `--threshold $UNSET_VAR`) arrives as \"\", which\n // `Number` reads as 0 — a gate that passes every run — so it's rejected.\n if (\n args.threshold?.trim() === \"\" ||\n !Number.isFinite(threshold) ||\n threshold < 0 ||\n threshold > 1\n ) {\n logger.error(`Invalid --threshold \"${args.threshold}\" (use 0..1).`);\n process.exit(1);\n }\n const timeoutS = parseTimeoutSeconds(args.timeout, DEFAULT_TIMEOUT_S);\n return { agent: args.agent, threshold, timeoutS };\n};\n\n/** `blume eval --fix`: hand the failing report to the interactive agent. */\nconst runFixHandoff = async (\n agent: AgentKind,\n result: EvalResult,\n root: string,\n threshold: number\n): Promise<void> => {\n const count = result.counts.fail + result.counts.error;\n if (count === 0) {\n return;\n }\n const cli = AGENTS[agent];\n const report = await writeEvalReport(result, root, threshold);\n process.stderr.write(\n ` Handing ${count} failed question${count === 1 ? \"\" : \"s\"} to ${cli.name}…\\n\\n`\n );\n const code = await launchAgentCode(agent, evalFixPrompt(report));\n if (code !== 0) {\n process.exit(code);\n }\n};\n\n/** `blume eval init`: draft a starter evals file via the interactive agent. */\nconst runInit = async (agent: AgentKind, file: string): Promise<void> => {\n const path = resolve(process.cwd(), file);\n if (existsSync(path)) {\n logger.error(\n `${file} already exists — edit it directly, or pass --file to draft elsewhere.`\n );\n process.exit(1);\n }\n const code = await launchAgentCode(agent, initPrompt(file));\n if (code !== 0) {\n process.exit(code);\n }\n};\n\nexport const evalCommand = defineCommand({\n args: {\n action: {\n description: 'Optional action: \"init\" drafts a starter evals file.',\n required: false,\n type: \"positional\",\n },\n agent: {\n default: \"codex\",\n description: \"Agent CLI that reads and grades the docs: codex | claude.\",\n type: \"string\",\n },\n file: {\n default: DEFAULT_FILE,\n description: \"The evals file to run.\",\n type: \"string\",\n },\n fix: {\n description:\n \"After a failing run, hand the report to the agent to fix the docs interactively.\",\n type: \"boolean\",\n },\n json: {\n description: \"Emit the report as JSON on stdout (for CI/editors).\",\n type: \"boolean\",\n },\n threshold: {\n description:\n \"Minimum passing fraction (0..1) before the run exits non-zero. Defaults to 1.\",\n type: \"string\",\n },\n timeout: {\n description: `Reader time limit per question, in seconds. Defaults to ${DEFAULT_TIMEOUT_S}.`,\n type: \"string\",\n },\n verbose: {\n description: \"Include the reader's full answer under each failure.\",\n type: \"boolean\",\n },\n },\n meta: commandMeta.eval,\n async run({ args }) {\n const root = process.cwd();\n const { agent, threshold, timeoutS } = parseFlags(args);\n if (args.action === \"init\") {\n await runInit(agent, args.file);\n return;\n }\n\n let result: EvalResult;\n try {\n // `scanProject`, not `prepareProject`: the eval reads the content tree\n // and never regenerates the runtime, so it doesn't contend with a\n // running dev server. Same reasoning as `blume audit`.\n const project = await scanProject(root, { mode: \"build\" });\n // `resolve`, not `join`: an absolute `--file` (`/ci/evals.yaml`) is\n // used as given instead of being nested under the project root.\n const evalsPath = resolve(root, args.file);\n const { evals, raw } = await loadEvalsFile(evalsPath);\n\n process.stderr.write(`${headerLine(evals.questions.length, agent)}\\n\\n`);\n result = await runEval({\n agent,\n evals,\n evalsPath,\n onProgress: (event) => {\n // Straight to stderr, not `logger.info` — consola drops info-level\n // lines in test and CI environments.\n if (event.kind === \"question-start\") {\n process.stderr.write(\n `${startLine(event.id, event.index, event.total)}\\n`\n );\n return;\n }\n const lines = [\n questionLine(event.result),\n ...questionDetails(event.result, Boolean(args.verbose)),\n ];\n process.stderr.write(`${lines.join(\"\\n\")}\\n`);\n },\n project,\n rawEvals: raw,\n readerTimeoutMs: timeoutS * 1000,\n });\n } catch (error) {\n if (error instanceof EvalsFileError) {\n logger.error(error.message);\n process.exit(1);\n }\n if (error instanceof BlumeError) {\n reportDiagnostics([error.diagnostic], root);\n process.exit(1);\n }\n // SAFETY: only the `code` tag is inspected; a spawn failure throws an\n // ErrnoException, and any other thrown value fails the comparison and\n // falls through to the internal-error report.\n if ((error as NodeJS.ErrnoException)?.code === \"ENOENT\") {\n notInstalled(agent);\n }\n reportInternalError(error);\n process.exit(1);\n }\n\n const tail = [\n \"\",\n ...warningLines(result, root),\n ...fixLines(result, root),\n \"\",\n ` ${summaryLine(result)}`,\n \"\",\n ];\n process.stderr.write(tail.join(\"\\n\"));\n\n const failed = passFraction(result) < threshold;\n\n if (args.fix) {\n // The gate is a CI concern; a handoff run succeeds when the agent\n // session does, not when the docs already passed.\n await runFixHandoff(agent, result, root, threshold);\n return;\n }\n\n if (args.json) {\n process.stdout.write(evalReportJson(result, root, threshold));\n if (failed) {\n // `process.exit` doesn't flush a piped stdout — without this the JSON\n // is truncated mid-write in exactly the CI setups that consume it.\n await flushStdout();\n process.exit(1);\n }\n return;\n }\n\n if (failed) {\n // Set the code and return rather than `process.exit`, which doesn't wait\n // for a piped stderr: a long `--verbose` report was cut off mid-write, in\n // exactly the CI logs that need to show every failure.\n process.exitCode = 1;\n }\n },\n});\n",
|
|
6
|
+
"import type { EvalQuestion } from \"./schema.ts\";\n\n/**\n * The reader's instructions. The agent is spawned in an empty directory with\n * its file/shell/web tools disabled, so the prompt's job is to direct it at\n * the MCP docs tools and forbid the one escape hatch that remains: answering\n * from prior knowledge of the product.\n */\nexport const readerPrompt = (question: EvalQuestion): string =>\n `You are evaluating whether a product's documentation can answer a user's question.\n\nAnswer the question below using ONLY the connected documentation tools (search_docs, get_page, list_pages, get_navigation). Rules:\n- Do not use prior knowledge about the product. Do not guess.\n- Do not read files, run commands, or access the network.\n- Search first, then read the most relevant pages with get_page.\n- If the documentation does not contain the answer, say exactly what information is missing instead of inventing one.\n\nQuestion: ${question.question}\n\nReply with a concise answer containing the specific facts the documentation provides. Plain text only.`;\n\n/** The judge's instructions: grade the answer against the expected facts. */\nexport const judgePrompt = (question: EvalQuestion, answer: string): string => {\n const facts = question.expected.map((fact) => `- ${fact}`).join(\"\\n\");\n return `You are grading an answer against expected facts. Do not use any tools.\n\nQuestion: ${question.question}\n\nExpected facts — each must be present in substance (paraphrase is fine, contradiction is not):\n${facts}\n\nAnswer to grade:\n\"\"\"\n${answer}\n\"\"\"\n\nAn answer that states the documentation lacks the information FAILS.\n\nReply with ONLY this JSON object on a single line, no markdown fences:\n{\"pass\": true|false, \"score\": 0.0-1.0, \"missing\": [\"expected facts absent or contradicted\"], \"notes\": \"one sentence\"}`;\n};\n\n/** The `--fix` handoff prompt: where the report is and the ground rules. */\nexport const evalFixPrompt = (reportPath: string): string =>\n `Fix the documentation gaps found by \\`blume eval\\` in this project.\n\nThe 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.\n\nWork through every failed question:\n1. Read the page named in the finding (or choose the best page when none is named).\n2. Edit the documentation so it states the missing facts explicitly. Add prose, not filler; keep the page's voice.\n3. Never delete questions from the evals file or weaken expected facts.\n\nWhen you are done, run \\`blume eval\\` to verify, and repeat until every question passes.`;\n\n/** The `eval init` prompt: draft a starter evals file from the docs. */\nexport const initPrompt = (evalsPath: string): string =>\n `Draft a starter evals file for \\`blume eval\\` in this documentation project.\n\nRead the documentation source pages in this project and write ${evalsPath} with about 10 high-value questions a real user would ask — installation, configuration, deployment, and the project's headline features. For each question, list the expected facts a correct answer must state, grounded in what the documentation actually promises (never invent facts the docs don't state).\n\nThe file format is YAML:\n\nquestions:\n - id: kebab-case-slug\n question: One user question?\n expected:\n - a fact the answer must contain\n - another required fact\n routes:\n - /route/of/the/page/that/answers/it\n\nRules:\n- Every \\`expected\\` fact must be verifiable in the docs today.\n- Prefer questions whose answers live on one page; set \\`routes\\` to that page.\n- Keep ids unique and questions short.\n\nWhen you are done, print the file and suggest running \\`blume eval\\` to try it.`;\n",
|
|
7
|
+
"import { mkdtemp, writeFile } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\n\nimport { colors } from \"consola/utils\";\nimport type { ColorFunction } from \"consola/utils\";\nimport { join, relative } from \"pathe\";\n\nimport { AGENTS } from \"../audit/agent.ts\";\nimport { duration, money, seconds } from \"../cli/report-format.ts\";\nimport { countBySeverity } from \"../core/diagnostics.ts\";\nimport type { EvalResult, QuestionResult, QuestionStatus } from \"./run.ts\";\n\nconst GLYPH = {\n error: \"!\",\n fail: \"✖\",\n pass: \"✔\",\n skip: \"⊘\",\n} satisfies Record<QuestionStatus, string>;\n\nconst STATUS_COLOR = {\n error: colors.yellow,\n fail: colors.red,\n pass: colors.green,\n skip: colors.dim,\n} satisfies Record<QuestionStatus, ColorFunction>;\n\n/** Longest id gets the room; everything shorter aligns to it. */\nconst ID_PAD = 28;\n\n/** One question's progress/report line: glyph, id, status, score, time, cost. */\nexport const questionLine = (result: QuestionResult): string => {\n const color = STATUS_COLOR[result.status];\n const glyph = color(GLYPH[result.status]);\n const id = result.id.padEnd(ID_PAD);\n if (result.status === \"skip\") {\n return ` ${glyph} ${id} ${colors.dim(\"skipped\")}`;\n }\n const score = result.score === undefined ? \"\" : result.score.toFixed(2);\n const cost = money(result.costUsd);\n const cells = [\n color(result.status),\n score,\n colors.dim(seconds(result.durationMs)),\n cost === \"\" ? \"\" : colors.dim(cost),\n ]\n .filter((cell) => cell !== \"\")\n .join(\" \");\n return ` ${glyph} ${id} ${cells}`;\n};\n\n/** Indented context under a question's line: missing facts, error detail. */\nexport const questionDetails = (\n result: QuestionResult,\n verbose: boolean\n): string[] => {\n const lines: string[] = [];\n if (result.status === \"fail\") {\n for (const fact of result.missing) {\n lines.push(` ${colors.dim(`missing: ${fact}`)}`);\n }\n }\n if (result.status === \"error\" && result.detail) {\n lines.push(` ${colors.dim(result.detail)}`);\n }\n if (verbose && result.answer && result.status !== \"pass\") {\n lines.push(\n ...result.answer\n .split(\"\\n\")\n .map((line) => ` ${colors.dim(`> ${line}`)}`)\n );\n }\n return lines;\n};\n\n/** The one-line totals: `9 passed · 2 failed · 1 skipped · 1m 42s · $0.71`. */\nexport const summaryLine = (result: EvalResult): string => {\n const { counts } = result;\n const parts = [\n `${counts.pass} passed`,\n counts.fail > 0 ? `${counts.fail} failed` : \"\",\n counts.error > 0 ? `${counts.error} errored` : \"\",\n counts.skip > 0 ? `${counts.skip} skipped` : \"\",\n duration(result.durationMs),\n money(result.costUsd),\n ].filter((part) => part !== \"\");\n return parts.join(\" · \");\n};\n\n/** The header line the command prints before the first question runs. */\nexport const headerLine = (total: number, agent: EvalResult[\"agent\"]): string =>\n `${colors.bold(\"blume eval\")} ${total} question(s) · ${AGENTS[agent].name}`;\n\n/** The dim announce line while a question's agents run. */\nexport const startLine = (id: string, index: number, total: number): string =>\n ` ${colors.dim(`▸ ${id} (${index + 1}/${total})`)}`;\n\n/**\n * `fix:` pointers for failed questions, naming the file that resolves each. A\n * question whose agent run errored gets a `run failed:` line pointing at the\n * question instead: the run never graded the docs, so there's no page to fix.\n */\nexport const fixLines = (result: EvalResult, root: string): string[] =>\n result.diagnostics\n .filter((diagnostic) => diagnostic.code !== \"BLUME_EVAL_ROUTE_UNKNOWN\")\n .map((finding) => {\n const site = finding.file\n ? `${relative(root, finding.file)}${finding.line ? `:${finding.line}` : \"\"}`\n : \"\";\n const label =\n finding.code === \"BLUME_EVAL_QUESTION_ERROR\"\n ? colors.red(\"run failed:\")\n : colors.cyan(\"fix:\");\n return ` ${label} ${site} ${colors.dim(finding.message)}`;\n });\n\n/** Dim warnings for route hints that no longer match a page. */\nexport const warningLines = (result: EvalResult, root: string): string[] =>\n result.diagnostics\n .filter((diagnostic) => diagnostic.code === \"BLUME_EVAL_ROUTE_UNKNOWN\")\n .map((finding) => {\n const site = finding.file\n ? ` ${relative(root, finding.file)}${finding.line ? `:${finding.line}` : \"\"}`\n : \"\";\n return ` ${colors.yellow(\"⚠\")}${site} ${colors.dim(finding.message)}`;\n });\n\n/** The human report, written to stderr by the command. */\nexport const formatEvalReport = (\n result: EvalResult,\n root: string,\n options: { verbose?: boolean } = {}\n): string => {\n const lines: string[] = [headerLine(result.results.length, result.agent), \"\"];\n\n for (const question of result.results) {\n lines.push(\n questionLine(question),\n ...questionDetails(question, Boolean(options.verbose))\n );\n }\n lines.push(\"\");\n\n // The finding tells the author which file fixes which failure.\n const failures = fixLines(result, root);\n lines.push(...failures);\n if (failures.length > 0) {\n lines.push(\"\");\n }\n\n lines.push(` ${summaryLine(result)}`, \"\");\n return lines.join(\"\\n\");\n};\n\n/**\n * The machine-readable report. The `diagnostics` + `summary` shape matches\n * `blume validate --json` and `blume audit --json` exactly — anything parsing\n * those keeps working — with the eval run's own results alongside.\n */\nexport const evalReportJson = (\n result: EvalResult,\n root: string,\n threshold: number\n): string => {\n const diagnostics = result.diagnostics.map((diagnostic) =>\n diagnostic.file\n ? { ...diagnostic, file: relative(root, diagnostic.file) }\n : diagnostic\n );\n return `${JSON.stringify(\n {\n diagnostics,\n eval: {\n agent: result.agent,\n costUsd: result.costUsd,\n counts: result.counts,\n durationMs: result.durationMs,\n results: result.results,\n threshold,\n },\n summary: countBySeverity(result.diagnostics),\n },\n null,\n 2\n )}\\n`;\n};\n\n/**\n * Write the full JSON report where a `--fix` agent can read it — a file\n * rather than inline prompt text, because a long run's answers would exceed\n * the platform's argv limit.\n */\nexport const writeEvalReport = async (\n result: EvalResult,\n root: string,\n threshold: number\n): Promise<string> => {\n const dir = await mkdtemp(join(tmpdir(), \"blume-eval-\"));\n const path = join(dir, \"report.json\");\n await writeFile(path, evalReportJson(result, root, threshold));\n return path;\n};\n",
|
|
8
|
+
"import { mkdir, mkdtemp, writeFile } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\n\nimport { join } from \"pathe\";\n\nimport { buildMcpData } from \"../ai/mcp/data.ts\";\nimport { AGENTS } from \"../audit/agent.ts\";\nimport type { AgentKind } from \"../audit/agent.ts\";\nimport type { BlumeProject } from \"../core/project-graph.ts\";\nimport type { Diagnostic } from \"../core/types.ts\";\nimport {\n agentArgs,\n parseVerdict,\n readAgentOutput,\n runAgentHeadless,\n writeMcpConfig,\n} from \"./agents.ts\";\nimport type { HeadlessRunner } from \"./agents.ts\";\nimport { questionFinding, routeFindings } from \"./findings.ts\";\nimport { judgePrompt, readerPrompt } from \"./prompts.ts\";\nimport type { EvalQuestion, EvalsFile } from \"./schema.ts\";\n\n/** Reader runs search and read several pages; the judge grades one answer. */\nconst DEFAULT_READER_TIMEOUT_MS = 180_000;\nconst DEFAULT_JUDGE_TIMEOUT_MS = 60_000;\n\nexport type QuestionStatus = \"error\" | \"fail\" | \"pass\" | \"skip\";\n\n/** One question's outcome, carrying everything the reports print. */\nexport interface QuestionResult {\n answer?: string;\n costUsd?: number;\n /** Why the run errored (timeout, agent failure, unparseable verdict). */\n detail?: string;\n durationMs: number;\n expected: string[];\n id: string;\n missing: string[];\n notes?: string;\n question: string;\n routes: string[];\n score?: number;\n status: QuestionStatus;\n}\n\nexport interface EvalResult {\n agent: AgentKind;\n /** Total spend, when the agent CLI reports it (claude does, codex doesn't). */\n costUsd?: number;\n counts: Record<QuestionStatus, number>;\n diagnostics: Diagnostic[];\n durationMs: number;\n results: QuestionResult[];\n}\n\nexport type EvalProgress =\n | {\n kind: \"question-end\";\n index: number;\n result: QuestionResult;\n total: number;\n }\n | { kind: \"question-start\"; id: string; index: number; total: number };\n\nexport interface EvalRunOptions {\n agent: AgentKind;\n evals: EvalsFile;\n /** Where the evals file lives, for findings with no usable route hint. */\n evalsPath: string;\n judgeTimeoutMs?: number;\n onProgress?: (event: EvalProgress) => void;\n project: BlumeProject;\n /** The evals file's raw text, for line-anchoring findings. */\n rawEvals: string;\n readerTimeoutMs?: number;\n /** The spawn function — injectable so tests never launch a real agent. */\n run?: HeadlessRunner;\n}\n\ninterface QuestionContext {\n bin: string;\n dir: string;\n judgeTimeoutMs: number;\n kind: AgentKind;\n mcp: Awaited<ReturnType<typeof writeMcpConfig>>;\n readerTimeoutMs: number;\n run: HeadlessRunner;\n}\n\nconst errored = (\n question: EvalQuestion,\n detail: string,\n durationMs: number\n): QuestionResult => ({\n detail,\n durationMs,\n expected: question.expected,\n id: question.id,\n missing: [],\n question: question.question,\n routes: question.routes,\n status: \"error\",\n});\n\n/** Run one question: a fresh empty cwd, the reader, then the judge. */\nconst runQuestion = async (\n question: EvalQuestion,\n index: number,\n context: QuestionContext\n): Promise<QuestionResult> => {\n const started = performance.now();\n const elapsed = () => Math.round(performance.now() - started);\n\n // An empty working directory per invocation is the fresh-eyes guardrail:\n // even if a tool restriction slips, there is nothing here to read.\n const workDir = join(context.dir, `work-${index}`);\n await mkdir(workDir, { recursive: true });\n\n const answerPath = join(workDir, \"answer.txt\");\n const reader = await context.run(\n context.bin,\n agentArgs(context.kind, { lastMessagePath: answerPath, mcp: context.mcp }),\n {\n cwd: workDir,\n prompt: readerPrompt(question),\n timeoutMs: context.readerTimeoutMs,\n }\n );\n const answer = await readAgentOutput(context.kind, reader, answerPath);\n if (answer.isError) {\n return {\n ...errored(question, `reader ${answer.detail ?? \"failed\"}`, elapsed()),\n costUsd: answer.costUsd,\n };\n }\n\n const verdictPath = join(workDir, \"verdict.txt\");\n const judge = await context.run(\n context.bin,\n agentArgs(context.kind, { lastMessagePath: verdictPath }),\n {\n cwd: workDir,\n prompt: judgePrompt(question, answer.text),\n timeoutMs: context.judgeTimeoutMs,\n }\n );\n const graded = await readAgentOutput(context.kind, judge, verdictPath);\n const costUsd =\n answer.costUsd === undefined && graded.costUsd === undefined\n ? undefined\n : (answer.costUsd ?? 0) + (graded.costUsd ?? 0);\n if (graded.isError) {\n return {\n ...errored(question, `judge ${graded.detail ?? \"failed\"}`, elapsed()),\n answer: answer.text,\n costUsd,\n };\n }\n\n const verdict = parseVerdict(graded.text);\n if (!verdict) {\n return {\n ...errored(question, \"judge returned no parseable verdict\", elapsed()),\n answer: answer.text,\n costUsd,\n };\n }\n\n return {\n answer: answer.text,\n costUsd,\n durationMs: elapsed(),\n expected: question.expected,\n id: question.id,\n missing: verdict.missing,\n notes: verdict.notes || undefined,\n question: question.question,\n routes: question.routes,\n score: verdict.score,\n status: verdict.pass ? \"pass\" : \"fail\",\n };\n};\n\n/** The findings a missed question produces: failed, or its agent run errored. */\nconst MISS_CODES: ReadonlySet<string> = new Set([\n \"BLUME_EVAL_QUESTION_ERROR\",\n \"BLUME_EVAL_QUESTION_FAILED\",\n]);\n\n/**\n * The fraction of run (non-skipped) questions that pass the CI gate. A miss on\n * a `severity: warning` question is reported as a warning and never counts\n * against the gate — each miss's finding carries its question's severity, so\n * the gate reads the same findings the JSON summary counts, and the exit code\n * can't disagree with the summary's error total.\n */\nexport const passFraction = (result: EvalResult): number => {\n const ran = result.results.length - result.counts.skip;\n if (ran === 0) {\n return 1;\n }\n const misses = result.diagnostics.filter(\n (diagnostic) =>\n MISS_CODES.has(diagnostic.code) && diagnostic.severity === \"error\"\n ).length;\n return (ran - misses) / ran;\n};\n\n/**\n * Run every question through the reader/judge pair, sequentially: each\n * question is already two agent sessions, and a serial run keeps progress\n * output ordered and cost attribution obvious.\n */\nexport const runEval = async (options: EvalRunOptions): Promise<EvalResult> => {\n const started = performance.now();\n const kind = options.agent;\n const run = options.run ?? runAgentHeadless;\n const anchor = { path: options.evalsPath, raw: options.rawEvals };\n\n const dir = await mkdtemp(join(tmpdir(), \"blume-eval-\"));\n const snapshotPath = join(dir, \"mcp-data.json\");\n await writeFile(\n snapshotPath,\n JSON.stringify(await buildMcpData(options.project))\n );\n const mcp = await writeMcpConfig(dir, snapshotPath);\n\n const context: QuestionContext = {\n bin: AGENTS[kind].bin,\n dir,\n judgeTimeoutMs: options.judgeTimeoutMs ?? DEFAULT_JUDGE_TIMEOUT_MS,\n kind,\n mcp,\n readerTimeoutMs: options.readerTimeoutMs ?? DEFAULT_READER_TIMEOUT_MS,\n run,\n };\n\n const diagnostics: Diagnostic[] = [];\n const results: QuestionResult[] = [];\n const { questions } = options.evals;\n\n for (const [index, question] of questions.entries()) {\n diagnostics.push(...routeFindings(question, options.project, anchor));\n\n if (question.skip) {\n results.push({\n durationMs: 0,\n expected: question.expected,\n id: question.id,\n missing: [],\n question: question.question,\n routes: question.routes,\n status: \"skip\",\n });\n continue;\n }\n\n options.onProgress?.({\n id: question.id,\n index,\n kind: \"question-start\",\n total: questions.length,\n });\n // Sequential by design: each question is already two agent sessions, and\n // a serial run keeps progress output ordered and cost attribution obvious.\n // oxlint-disable-next-line no-await-in-loop\n const result = await runQuestion(question, index, context);\n results.push(result);\n if (result.status === \"fail\" || result.status === \"error\") {\n diagnostics.push(\n questionFinding(\n question,\n {\n detail: result.detail,\n missing: result.missing,\n status: result.status,\n },\n options.project,\n anchor\n )\n );\n }\n options.onProgress?.({\n index,\n kind: \"question-end\",\n result,\n total: questions.length,\n });\n }\n\n const counts = {\n error: 0,\n fail: 0,\n pass: 0,\n skip: 0,\n } satisfies Record<QuestionStatus, number>;\n for (const result of results) {\n counts[result.status] += 1;\n }\n const costs = results.flatMap((result) =>\n result.costUsd === undefined ? [] : [result.costUsd]\n );\n\n return {\n agent: kind,\n costUsd:\n costs.length > 0\n ? costs.reduce((total, cost) => total + cost, 0)\n : undefined,\n counts,\n diagnostics,\n durationMs: Math.round(performance.now() - started),\n results,\n };\n};\n",
|
|
9
|
+
"import { readFile } from \"node:fs/promises\";\n\nimport { load } from \"js-yaml\";\nimport { z } from \"zod\";\n\nimport { YAML_SCHEMA } from \"../core/yaml.ts\";\n\n/** Question ids are kebab-case slugs so they read well in reports and CI logs. */\nconst ID_PATTERN = /^[a-z0-9][a-z0-9-]*$/u;\n\nconst questionSchema = z.strictObject({\n expected: z\n .array(z.string().min(1))\n .min(1, \"expected must list at least one fact\"),\n id: z\n .string()\n .regex(ID_PATTERN, \"id must be a kebab-case slug (a-z, 0-9, dashes)\"),\n question: z.string().min(1),\n routes: z\n .union([z.string(), z.array(z.string())])\n .default([])\n .transform((value) => (Array.isArray(value) ? value : [value])),\n severity: z.enum([\"error\", \"warning\"]).default(\"error\"),\n skip: z.boolean().default(false),\n});\n\n/** One author-written eval: a question plus the facts a passing answer states. */\nexport type EvalQuestion = z.infer<typeof questionSchema>;\n\nconst fullSchema = z.strictObject({\n questions: z.array(questionSchema).min(1),\n version: z.literal(1).default(1),\n});\n\n/**\n * The evals file schema. A bare top-level list of questions is accepted as\n * shorthand — `loadEvalsFile` wraps it before validating, rather than a\n * `z.union`, so schema errors name the offending field instead of collapsing\n * into an opaque \"invalid union\" issue.\n */\nexport const evalsFileSchema = fullSchema.superRefine((value, context) => {\n const seen = new Set<string>();\n for (const question of value.questions) {\n if (seen.has(question.id)) {\n context.addIssue({\n code: z.ZodIssueCode.custom,\n message: `duplicate question id \"${question.id}\"`,\n path: [\"questions\"],\n });\n }\n seen.add(question.id);\n }\n});\n\nexport type EvalsFile = z.infer<typeof evalsFileSchema>;\n\n/** A problem loading or validating the evals file, with the path it names. */\nexport class EvalsFileError extends Error {\n readonly path: string;\n\n constructor(path: string, message: string) {\n super(message);\n this.name = \"EvalsFileError\";\n this.path = path;\n }\n}\n\nconst describeIssues = (error: z.ZodError): string =>\n error.issues\n .map((issue) => {\n const at = issue.path.length > 0 ? ` at ${issue.path.join(\".\")}` : \"\";\n return `${issue.message}${at}`;\n })\n .join(\"; \");\n\n/**\n * Read and validate an evals file. Returns the parsed questions plus the raw\n * text, kept so findings can anchor to the line a question is defined on.\n */\nexport const loadEvalsFile = async (\n path: string\n): Promise<{ evals: EvalsFile; raw: string }> => {\n let raw: string;\n try {\n raw = await readFile(path, \"utf-8\");\n } catch {\n throw new EvalsFileError(\n path,\n `No evals file found at ${path}. Run \\`blume eval init\\` to draft one.`\n );\n }\n\n let parsed: unknown;\n try {\n parsed = load(raw, { schema: YAML_SCHEMA });\n } catch (error) {\n const detail = error instanceof Error ? error.message : String(error);\n throw new EvalsFileError(path, `Invalid YAML in ${path}: ${detail}`);\n }\n\n // The bare-list shorthand: a top-level sequence of questions.\n const candidate = Array.isArray(parsed) ? { questions: parsed } : parsed;\n const result = evalsFileSchema.safeParse(candidate);\n if (!result.success) {\n throw new EvalsFileError(\n path,\n `Invalid evals file at ${path}: ${describeIssues(result.error)}`\n );\n }\n return { evals: result.data, raw };\n};\n\n/**\n * The 1-based line where a question's `id:` entry appears in the raw evals\n * file, so a finding with no route hint can still point somewhere editable.\n */\nexport const locateQuestion = (raw: string, id: string): number | undefined => {\n const pattern = new RegExp(`^\\\\s*-?\\\\s*id:\\\\s*[\"']?${id}[\"']?\\\\s*$`, \"u\");\n const lines = raw.split(\"\\n\");\n for (const [index, line] of lines.entries()) {\n if (pattern.test(line)) {\n return index + 1;\n }\n }\n return undefined;\n};\n",
|
|
10
|
+
"import type { BlumeProject } from \"../core/project-graph.ts\";\nimport type { Diagnostic } from \"../core/types.ts\";\nimport { locateQuestion } from \"./schema.ts\";\nimport type { EvalQuestion } from \"./schema.ts\";\n\nconst DOCS_URL = \"https://useblume.dev/docs/cli/evals\";\n\n/** Where a finding should anchor when no route hint matches a page. */\nexport interface EvalsAnchor {\n path: string;\n raw: string;\n}\n\n/** The manifest route a hint names, if any. */\nconst hintedRoute = (question: EvalQuestion, project: BlumeProject) => {\n for (const hint of question.routes) {\n const route = project.manifest.routes.find(\n (candidate) => candidate.path === hint\n );\n if (route) {\n return route;\n }\n }\n};\n\n/**\n * Warnings for route hints that name no manifest route — docs move, and a\n * finding that silently anchors to the evals file instead of the page it\n * used to name is a debugging session; a warning is a one-line fix.\n */\nexport const routeFindings = (\n question: EvalQuestion,\n project: BlumeProject,\n anchor: EvalsAnchor\n): Diagnostic[] => {\n const known = new Set(project.manifest.routes.map((route) => route.path));\n return question.routes\n .filter((hint) => !known.has(hint))\n .map((hint) => ({\n code: \"BLUME_EVAL_ROUTE_UNKNOWN\",\n docsUrl: DOCS_URL,\n file: anchor.path,\n line: locateQuestion(anchor.raw, question.id),\n message: `Question \"${question.id}\" hints at route \"${hint}\", which matches no page.`,\n severity: \"warning\" as const,\n suggestion:\n \"Update the question's `routes` to the page's current route, or remove the hint.\",\n }));\n};\n\n/** What the finding needs to know about how the question went. */\nexport interface QuestionOutcome {\n /** Why the run errored, when it did. */\n detail?: string;\n /** The expected facts the judge found absent or contradicted. */\n missing: string[];\n status: \"error\" | \"fail\";\n}\n\n/**\n * The diagnostic for a failed or errored question. A failure is anchored to\n * the page that should have answered it (via the first matching route hint)\n * or, failing that, to the question's line in the evals file. An errored run —\n * the agent crashed, timed out, or answered in a shape Blume couldn't read —\n * says nothing about the docs, so it always points at the question instead of\n * a page there's nothing to fix in.\n */\nexport const questionFinding = (\n question: EvalQuestion,\n outcome: QuestionOutcome,\n project: BlumeProject,\n anchor: EvalsAnchor\n): Diagnostic => {\n const questionSite = {\n file: anchor.path,\n line: locateQuestion(anchor.raw, question.id),\n };\n\n if (outcome.status === \"error\") {\n return {\n code: \"BLUME_EVAL_QUESTION_ERROR\",\n docsUrl: DOCS_URL,\n message: `The agent run failed for \"${question.question}\"${\n outcome.detail ? ` — ${outcome.detail}` : \"\"\n }, so the docs weren't graded.`,\n severity: question.severity,\n suggestion:\n \"Rerun `blume eval`; if it persists, check the agent CLI installation and the failure detail.\",\n ...questionSite,\n };\n }\n\n const route = hintedRoute(question, project);\n const site = route\n ? { file: route.sourcePath, url: route.path }\n : questionSite;\n\n const missing =\n outcome.missing.length > 0\n ? ` — missing: ${outcome.missing.join(\"; \")}`\n : \"\";\n return {\n code: \"BLUME_EVAL_QUESTION_FAILED\",\n docsUrl: DOCS_URL,\n message: `Docs could not answer: \"${question.question}\"${missing}`,\n severity: question.severity,\n suggestion:\n \"State the missing facts on this page, then rerun `blume eval`.\",\n ...site,\n };\n};\n"
|
|
11
|
+
],
|
|
12
|
+
"mappings": "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",
|
|
13
|
+
"debugId": "C123F57ABFFCB50F64756E2164756E21",
|
|
14
|
+
"names": []
|
|
15
|
+
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
needsPlaygroundProxy,
|
|
4
4
|
resolveAskBackend
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-pv29h0wf.js";
|
|
6
6
|
|
|
7
7
|
// src/core/server-features.ts
|
|
8
8
|
var serverFeatures = (config) => {
|
|
@@ -72,4 +72,4 @@ var checkRequiredSecrets = (config) => {
|
|
|
72
72
|
export { serverFeatures, checkRequiredSecrets };
|
|
73
73
|
|
|
74
74
|
//# debugId=26CFBC953FC234CC64756E2164756E21
|
|
75
|
-
//# sourceMappingURL=chunk-
|
|
75
|
+
//# sourceMappingURL=chunk-364znk6q.js.map
|
|
@@ -37,22 +37,41 @@ var normalizeRoute = (input) => {
|
|
|
37
37
|
return trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
|
|
38
38
|
};
|
|
39
39
|
var isInternalPath = (target) => target.startsWith("/") && !target.startsWith("//");
|
|
40
|
+
var pathPart = (target) => {
|
|
41
|
+
const at = target.search(/[#?]/u);
|
|
42
|
+
return at === -1 ? target : target.slice(0, at);
|
|
43
|
+
};
|
|
44
|
+
var isUnderBase = (base, route) => {
|
|
45
|
+
const path = pathPart(route);
|
|
46
|
+
return path === base || path.startsWith(`${base}/`);
|
|
47
|
+
};
|
|
40
48
|
var withBasePath = (basePath, route) => {
|
|
41
|
-
if (!basePath || !isInternalPath(route)) {
|
|
49
|
+
if (!basePath || !isInternalPath(route) || isUnderBase(basePath, route)) {
|
|
42
50
|
return route;
|
|
43
51
|
}
|
|
44
|
-
|
|
52
|
+
return route === "/" ? basePath : `${basePath}${route}`;
|
|
53
|
+
};
|
|
54
|
+
var mountBasePath = (basePath, route) => {
|
|
55
|
+
if (!basePath) {
|
|
45
56
|
return route;
|
|
46
57
|
}
|
|
47
58
|
return route === "/" ? basePath : `${basePath}${route}`;
|
|
48
59
|
};
|
|
49
60
|
var withComposedBasePath = (deployBase, basePath, route) => {
|
|
50
61
|
const composed = `${deployBase}${basePath}`;
|
|
51
|
-
if (composed && isInternalPath(route) && (
|
|
62
|
+
if (composed && isInternalPath(route) && isUnderBase(composed, route)) {
|
|
52
63
|
return route;
|
|
53
64
|
}
|
|
54
65
|
return withBasePath(deployBase, withBasePath(basePath, route));
|
|
55
66
|
};
|
|
67
|
+
var DOTTED_PATH = /\.[a-z0-9]+$/iu;
|
|
68
|
+
var withAuthoredBasePath = (deployBase, basePath, target, servesPage) => {
|
|
69
|
+
if (!isInternalPath(target)) {
|
|
70
|
+
return target;
|
|
71
|
+
}
|
|
72
|
+
const path = pathPart(target);
|
|
73
|
+
return DOTTED_PATH.test(path) && !servesPage(withBasePath(basePath, path)) ? withBasePath(deployBase, target) : withComposedBasePath(deployBase, basePath, target);
|
|
74
|
+
};
|
|
56
75
|
var stripBasePath = (basePath, route) => {
|
|
57
76
|
if (!basePath) {
|
|
58
77
|
return route;
|
|
@@ -100,7 +119,7 @@ var MCP_TOOLS = [
|
|
|
100
119
|
}
|
|
101
120
|
];
|
|
102
121
|
|
|
103
|
-
export { trimEnd, trimChar, normalizeBasePath, normalizePath, normalizeRoute, isInternalPath, withBasePath, withComposedBasePath, stripBasePath, siteRoot, absoluteUrl2, MCP_TOOLS };
|
|
122
|
+
export { trimEnd, trimChar, normalizeBasePath, normalizePath, normalizeRoute, isInternalPath, withBasePath, mountBasePath, withComposedBasePath, withAuthoredBasePath, stripBasePath, siteRoot, absoluteUrl2, MCP_TOOLS };
|
|
104
123
|
|
|
105
|
-
//# debugId=
|
|
106
|
-
//# sourceMappingURL=chunk-
|
|
124
|
+
//# debugId=23E38A1AF0C2C43564756E2164756E21
|
|
125
|
+
//# sourceMappingURL=chunk-3em5wd2y.js.map
|
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
"sources": ["../src/core/trim.ts", "../src/core/base-path.ts", "../src/core/site-url.ts", "../src/ai/mcp/tools.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
5
|
"/**\n * Single-character trimming, done without regular expressions.\n *\n * The obvious spellings — `/^\\/+/`, `/\\/+$/`, `/^\\/+|\\/+$/g` — take quadratic\n * time on a run of the trimmed character, because a failed match at one start\n * position tells the engine nothing about the next one. Every caller here trims\n * a value that comes from outside Blume (a configured route, a spec URL, a site\n * origin), so the slow path is reachable from user input rather than only from\n * our own literals. These loops are linear and allocation-free.\n */\n\n/** Drop every leading `char` (`\"///a\"` -> `\"a\"` for `\"/\"`). */\nexport const trimStart = (text: string, char: string): string => {\n let start = 0;\n while (start < text.length && text[start] === char) {\n start += 1;\n }\n return text.slice(start);\n};\n\n/** Drop every trailing `char` (`\"a///\"` -> `\"a\"` for `\"/\"`). */\nexport const trimEnd = (text: string, char: string): string => {\n let end = text.length;\n while (end > 0 && text[end - 1] === char) {\n end -= 1;\n }\n return text.slice(0, end);\n};\n\n/** Drop every leading *and* trailing `char` (`\"///a///\"` -> `\"a\"`). */\nexport const trimChar = (text: string, char: string): string =>\n trimEnd(trimStart(text, char), char);\n",
|
|
6
|
-
"/**\n * The site-wide `basePath` — a mount point that prepends a segment to every\n * generated route (`/docs/getting-started`) while staying invisible to the\n * navigation tree (see `core/navigation.ts`, which builds groups from a page's\n * base-less `navPath` and takes URLs from its based `route`). This is distinct\n * from a per-source `prefix` (a namespace that *does* create a sidebar group)\n * and from `deployment.base` (Astro's host-subdirectory base); the two compose,\n * stacking as `{deployment.base}/{basePath}/page`.\n *\n * These helpers run server-side (config, route construction, the link checker,\n * redirects, the markdown link plugin). The client-side counterpart lives in\n * `components/islands/base-path.ts` and serves `deployment.base` via `BASE_URL`.\n */\n\nimport { trimEnd } from \"./trim.ts\";\n\n/**\n * Canonicalize a configured base path to either `\"\"` (none) or `/seg[/seg…]`\n * (leading slash, no trailing slash, collapsed inner slashes). A blank value or\n * bare `/` normalizes to `\"\"`, so an unset/`\"/\"` base is a clean no-op.\n */\nexport const normalizeBasePath = (input?: string): string => {\n if (!input) {\n return \"\";\n }\n // Splitting on \"/\" and dropping the empty parts trims the edges and collapses\n // inner runs in one linear pass; the regex spellings of both are quadratic on\n // a long run of slashes (see `core/trim.ts`).\n const trimmed = input.trim().split(\"/\").filter(Boolean).join(\"/\");\n return trimmed === \"\" ? \"\" : `/${trimmed}`;\n};\n\n/**\n * Normalize a served path for comparison: drop the trailing slash (Astro serves\n * `/docs` and `/docs/` as the same page) and collapse an empty path to `/`.\n */\nexport const normalizePath = (path: string): string => {\n const trimmed = trimEnd(path, \"/\");\n return trimmed === \"\" ? \"/\" : trimmed;\n};\n\n/**\n * Canonicalize a route-ish string (a configured route, a page path, an agent-\n * supplied route) to `/` or `/seg[/seg…]`: trimmed, exactly one leading slash,\n * no trailing slash. The shared spelling of what openapi/references,\n * ai/ask-context, and ai/mcp/server each hand-rolled with slightly different\n * regexes.\n */\nexport const normalizeRoute = (input: string): string => {\n const trimmed = trimEnd(input.trim(), \"/\");\n if (trimmed === \"\") {\n return \"/\";\n }\n return trimmed.startsWith(\"/\") ? trimmed : `/${trimmed}`;\n};\n\n/**\n * Whether a link target is a root-relative internal path (`/x`) — the only\n * shape a base path applies to. Protocol-relative (`//host`), absolute URLs,\n * other schemes (`mailto:`), fragments (`#x`), and relative paths are excluded.\n */\nexport const isInternalPath = (target: string): boolean =>\n target.startsWith(\"/\") && !target.startsWith(\"//\");\n\n/**\n * Whether a rendered link should open in a new tab: an absolute http(s) URL or\n * a protocol-relative one (`//host/path`). Other schemes (`mailto:`, `tel:`)\n * also leave the site but hand off to another application, where a `_blank`\n * target only opens an empty tab beside it. The one predicate behind every\n * chrome link, so a header action and a sidebar featured link treat the same\n * href alike.\n */\nexport const isExternalUrl = (target: string): boolean =>\n /^https?:\\/\\//iu.test(target) || target.startsWith(\"//\");\n\n/**\n * Idempotently prepend `basePath` to a root-relative route. A route already\n * equal to or nested under the base is returned unchanged, so authors who write\n * the base by hand (`/docs/x`) aren't double-prefixed to `/docs/docs/x`.\n */\nexport const withBasePath = (basePath: string, route: string): string => {\n if (!basePath || !isInternalPath(route)) {\n return route;\n }\n
|
|
6
|
+
"/**\n * The site-wide `basePath` — a mount point that prepends a segment to every\n * generated route (`/docs/getting-started`) while staying invisible to the\n * navigation tree (see `core/navigation.ts`, which builds groups from a page's\n * base-less `navPath` and takes URLs from its based `route`). This is distinct\n * from a per-source `prefix` (a namespace that *does* create a sidebar group)\n * and from `deployment.base` (Astro's host-subdirectory base); the two compose,\n * stacking as `{deployment.base}/{basePath}/page`.\n *\n * These helpers run server-side (config, route construction, the link checker,\n * redirects, the markdown link plugin). The client-side counterpart lives in\n * `components/islands/base-path.ts` and serves `deployment.base` via `BASE_URL`.\n */\n\nimport { trimEnd } from \"./trim.ts\";\n\n/**\n * Canonicalize a configured base path to either `\"\"` (none) or `/seg[/seg…]`\n * (leading slash, no trailing slash, collapsed inner slashes). A blank value or\n * bare `/` normalizes to `\"\"`, so an unset/`\"/\"` base is a clean no-op.\n */\nexport const normalizeBasePath = (input?: string): string => {\n if (!input) {\n return \"\";\n }\n // Splitting on \"/\" and dropping the empty parts trims the edges and collapses\n // inner runs in one linear pass; the regex spellings of both are quadratic on\n // a long run of slashes (see `core/trim.ts`).\n const trimmed = input.trim().split(\"/\").filter(Boolean).join(\"/\");\n return trimmed === \"\" ? \"\" : `/${trimmed}`;\n};\n\n/**\n * Normalize a served path for comparison: drop the trailing slash (Astro serves\n * `/docs` and `/docs/` as the same page) and collapse an empty path to `/`.\n */\nexport const normalizePath = (path: string): string => {\n const trimmed = trimEnd(path, \"/\");\n return trimmed === \"\" ? \"/\" : trimmed;\n};\n\n/**\n * Canonicalize a route-ish string (a configured route, a page path, an agent-\n * supplied route) to `/` or `/seg[/seg…]`: trimmed, exactly one leading slash,\n * no trailing slash. The shared spelling of what openapi/references,\n * ai/ask-context, and ai/mcp/server each hand-rolled with slightly different\n * regexes.\n */\nexport const normalizeRoute = (input: string): string => {\n const trimmed = trimEnd(input.trim(), \"/\");\n if (trimmed === \"\") {\n return \"/\";\n }\n return trimmed.startsWith(\"/\") ? trimmed : `/${trimmed}`;\n};\n\n/**\n * Whether a link target is a root-relative internal path (`/x`) — the only\n * shape a base path applies to. Protocol-relative (`//host`), absolute URLs,\n * other schemes (`mailto:`), fragments (`#x`), and relative paths are excluded.\n */\nexport const isInternalPath = (target: string): boolean =>\n target.startsWith(\"/\") && !target.startsWith(\"//\");\n\n/**\n * Whether a rendered link should open in a new tab: an absolute http(s) URL or\n * a protocol-relative one (`//host/path`). Other schemes (`mailto:`, `tel:`)\n * also leave the site but hand off to another application, where a `_blank`\n * target only opens an empty tab beside it. The one predicate behind every\n * chrome link, so a header action and a sidebar featured link treat the same\n * href alike.\n */\nexport const isExternalUrl = (target: string): boolean =>\n /^https?:\\/\\//iu.test(target) || target.startsWith(\"//\");\n\n/**\n * The path part of a root-relative target, before any `?query` or `#fragment`\n * (`/docs#install` -> `/docs`).\n */\nconst pathPart = (target: string): string => {\n const at = target.search(/[#?]/u);\n return at === -1 ? target : target.slice(0, at);\n};\n\n/**\n * Whether `route`'s path already equals or sits under `base`. Only the path\n * part is compared, so a fragment or query (`/docs#install`) doesn't hide a\n * base written by hand.\n */\nconst isUnderBase = (base: string, route: string): boolean => {\n const path = pathPart(route);\n return path === base || path.startsWith(`${base}/`);\n};\n\n/**\n * Idempotently prepend `basePath` to a root-relative route. A route already\n * equal to or nested under the base is returned unchanged, so authors who write\n * the base by hand (`/docs/x`, `/docs#install`) aren't double-prefixed to\n * `/docs/docs/x`.\n */\nexport const withBasePath = (basePath: string, route: string): string => {\n if (!basePath || !isInternalPath(route) || isUnderBase(basePath, route)) {\n return route;\n }\n return route === \"/\" ? basePath : `${basePath}${route}`;\n};\n\n/**\n * Mount a route Blume generates under a base, unconditionally: `basePath` for\n * a content route, `deployment.base` for any generated URL (a sitemap entry,\n * a feed item). {@link withBasePath} leaves a route that already starts with\n * the base alone, which is right for a link an author based by hand but wrong\n * for a generated route: with `basePath: \"/docs\"`, `docs/guide.md` routes to\n * `/docs/guide` before the base and publishes at `/docs/docs/guide`, not on\n * top of the root `guide.md` — and likewise under `deployment.base: \"/docs\"`.\n */\nexport const mountBasePath = (basePath: string, route: string): string => {\n if (!basePath) {\n return route;\n }\n return route === \"/\" ? basePath : `${basePath}${route}`;\n};\n\n/**\n * {@link withBasePath} for the composed `deployment.base` + `basePath` stack\n * (`/base` + `/docs` serves pages at `/base/docs/x`). The hand-written-base\n * promise applies per layer: authors write `basePath` by hand (see\n * `markdown/base-links.ts`), so a `/docs/x` link gains only the deployment base\n * (`/base/docs/x`) rather than being double-prefixed to `/base/docs/docs/x`,\n * and a route already under the full composite is returned unchanged.\n */\nexport const withComposedBasePath = (\n deployBase: string,\n basePath: string,\n route: string\n): string => {\n const composed = `${deployBase}${basePath}`;\n if (composed && isInternalPath(route) && isUnderBase(composed, route)) {\n return route;\n }\n return withBasePath(deployBase, withBasePath(basePath, route));\n};\n\n/**\n * A path whose final segment carries a file extension (`/spec.pdf`,\n * `/logo.svg`) — a public asset, unless a page is served there.\n */\nconst DOTTED_PATH = /\\.[a-z0-9]+$/iu;\n\n/**\n * Base a root-relative link an author wrote as if mounted at root — a content\n * link (`markdown/base-links.ts`, `components/content/base-href.ts`) or a\n * redirect target (`deploy/redirects.ts`) — by what it names. A page gains the\n * composed stack ({@link withComposedBasePath}). A public asset — a path whose\n * final segment carries a file extension, with no page served there (a dotted\n * route like `/releases/v1.2` is still a page) — gains the deployment base\n * alone: Astro serves `public/` under `deployment.base`, but never under\n * `basePath`. `servesPage` answers whether a page is served at a\n * `basePath`-prefixed, fragment-less path. Other targets pass through.\n */\nexport const withAuthoredBasePath = (\n deployBase: string,\n basePath: string,\n target: string,\n servesPage: (route: string) => boolean\n): string => {\n if (!isInternalPath(target)) {\n return target;\n }\n const path = pathPart(target);\n return DOTTED_PATH.test(path) && !servesPage(withBasePath(basePath, path))\n ? withBasePath(deployBase, target)\n : withComposedBasePath(deployBase, basePath, target);\n};\n\n/**\n * Remove `basePath` from the front of a route (`/docs/guide` -> `/guide`,\n * `/docs` -> `/`). A route not under the base is returned unchanged. Inverse of\n * {@link withBasePath}; used to resolve public assets, which live at the site\n * root regardless of the base.\n */\nexport const stripBasePath = (basePath: string, route: string): string => {\n if (!basePath) {\n return route;\n }\n if (route === basePath) {\n return \"/\";\n }\n return route.startsWith(`${basePath}/`)\n ? route.slice(basePath.length)\n : route;\n};\n",
|
|
7
7
|
"import { joinURL } from \"ufo\";\n\nimport { trimEnd } from \"./trim.ts\";\n\n/**\n * Absolute-URL building for the configured `deployment.site`, shared by every\n * emitter that prints site URLs (sitemap, RSS, robots, llms.txt, the MCP and\n * agent-discovery documents). One implementation replaces eight per-file\n * copies that had drifted across three different trailing-slash treatments.\n *\n * Deliberately not `new URL(path, site)`: a root-absolute path would drop the\n * base path of a subpath deployment (`acme.com/docs`). ufo's `joinURL` joins\n * without that footgun; the site is first trimmed with the ReDoS-safe\n * `trimEnd` loop so even a malformed `site` with piled-up trailing slashes\n * joins cleanly.\n */\n\n/** The configured site with any trailing slashes dropped. */\nexport const siteRoot = (site: string): string => trimEnd(site, \"/\");\n\n/** `site` + root-absolute `path` (already carrying any deployment base). */\nexport const absoluteUrl = (site: string, path: string): string => {\n const root = siteRoot(site);\n // joinURL folds a lone \"/\" away entirely; the homepage keeps its slash\n // (`https://example.com/`), matching what every emitter always printed.\n return path === \"/\" ? `${root}/` : joinURL(root, path);\n};\n",
|
|
8
8
|
"/**\n * Static metadata for the MCP tools Blume exposes. Shared by the server (which\n * pairs each entry with a Zod input schema and handler) and the `.well-known`\n * discovery documents, so tool names and descriptions never drift between the\n * live server and its advertised capabilities.\n */\n\n/** A read-only, non-mutating tool hint set (every Blume tool is read-only). */\nconst READ_ONLY = { openWorldHint: false, readOnlyHint: true } as const;\n\nexport interface McpToolMeta {\n annotations: { openWorldHint: boolean; readOnlyHint: boolean };\n description: string;\n name: string;\n title: string;\n}\n\nexport const MCP_TOOLS: McpToolMeta[] = [\n {\n annotations: READ_ONLY,\n description:\n 'Full-text search across the documentation. Returns matching pages with their title, route, content type, and a short excerpt; pass `contentTypes` to search only pages of certain types (e.g. `rfc`, `changelog`), `filters` to require facet values the site declares per type (e.g. `{\"status\": \"enforced\"}`), and `locale` to search one language. On a versioned site results default to the current docs — pass `version` to search an archived version (e.g. `\"v1.0\"`) or `\"all\"` for every version. Use this first to discover relevant pages, then `get_page` to read one in full.',\n name: \"search_docs\",\n title: \"Search documentation\",\n },\n {\n annotations: READ_ONLY,\n description:\n \"Fetch a single documentation page as agent-optimized Markdown (frontmatter included, components downleveled to plain Markdown). Pass a route from `search_docs` or `list_pages`, e.g. `/guides/install`.\",\n name: \"get_page\",\n title: \"Get page Markdown\",\n },\n {\n annotations: READ_ONLY,\n description:\n 'List every documentation page with its route, title, description, content type, and any declared facet values; pass `contentTypes`, `filters`, and/or `locale` to narrow the list. On a versioned site the list defaults to the current docs — pass `version` for an archived version or `\"all\"`. Useful for enumerating the docs, discovering the types and facets in use, or finding a page when search is too narrow.',\n name: \"list_pages\",\n title: \"List pages\",\n },\n {\n annotations: READ_ONLY,\n description:\n \"Return the documentation navigation tree (header tabs and the sidebar hierarchy), reflecting how the docs are organized for readers. Pass `locale` for a language's tree and, on a versioned site, `version` for an archived snapshot's tree.\",\n name: \"get_navigation\",\n title: \"Get navigation\",\n },\n];\n"
|
|
9
9
|
],
|
|
10
|
-
"mappings": ";;;AAYO,IAAM,YAAY,CAAC,MAAc,SAAyB;AAAA,EAC/D,IAAI,QAAQ;AAAA,EACZ,OAAO,QAAQ,KAAK,UAAU,KAAK,WAAW,MAAM;AAAA,IAClD,SAAS;AAAA,EACX;AAAA,EACA,OAAO,KAAK,MAAM,KAAK;AAAA;AAIlB,IAAM,UAAU,CAAC,MAAc,SAAyB;AAAA,EAC7D,IAAI,MAAM,KAAK;AAAA,EACf,OAAO,MAAM,KAAK,KAAK,MAAM,OAAO,MAAM;AAAA,IACxC,OAAO;AAAA,EACT;AAAA,EACA,OAAO,KAAK,MAAM,GAAG,GAAG;AAAA;AAInB,IAAM,WAAW,CAAC,MAAc,SACrC,QAAQ,UAAU,MAAM,IAAI,GAAG,IAAI;;;ACV9B,IAAM,oBAAoB,CAAC,UAA2B;AAAA,EAC3D,IAAI,CAAC,OAAO;AAAA,IACV,OAAO;AAAA,EACT;AAAA,EAIA,MAAM,UAAU,MAAM,KAAK,EAAE,MAAM,GAAG,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG;AAAA,EAChE,OAAO,YAAY,KAAK,KAAK,IAAI;AAAA;AAO5B,IAAM,gBAAgB,CAAC,SAAyB;AAAA,EACrD,MAAM,UAAU,QAAQ,MAAM,GAAG;AAAA,EACjC,OAAO,YAAY,KAAK,MAAM;AAAA;AAUzB,IAAM,iBAAiB,CAAC,UAA0B;AAAA,EACvD,MAAM,UAAU,QAAQ,MAAM,KAAK,GAAG,GAAG;AAAA,EACzC,IAAI,YAAY,IAAI;AAAA,IAClB,OAAO;AAAA,EACT;AAAA,EACA,OAAO,QAAQ,WAAW,GAAG,IAAI,UAAU,IAAI;AAAA;AAQ1C,IAAM,iBAAiB,CAAC,WAC7B,OAAO,WAAW,GAAG,KAAK,CAAC,OAAO,WAAW,IAAI;
|
|
11
|
-
"debugId": "
|
|
10
|
+
"mappings": "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",
|
|
11
|
+
"debugId": "23E38A1AF0C2C43564756E2164756E21",
|
|
12
12
|
"names": []
|
|
13
13
|
}
|
|
@@ -1,50 +1,51 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
commandMeta,
|
|
4
|
-
|
|
4
|
+
BlumeError,
|
|
5
|
+
logger,
|
|
6
|
+
reportDiagnostics
|
|
5
7
|
} from "./index.js";
|
|
6
8
|
import {
|
|
7
9
|
deployPlatform
|
|
8
|
-
} from "./chunk-
|
|
9
|
-
import"./chunk-
|
|
10
|
-
import"./chunk-
|
|
10
|
+
} from "./chunk-pv29h0wf.js";
|
|
11
|
+
import"./chunk-3em5wd2y.js";
|
|
12
|
+
import"./chunk-j85vccga.js";
|
|
11
13
|
import {
|
|
12
14
|
publishBuildProject,
|
|
13
15
|
ogCacheDir,
|
|
14
16
|
pruneCardCache,
|
|
15
17
|
cardCacheTally
|
|
16
|
-
} from "./chunk-
|
|
17
|
-
import"./chunk-
|
|
18
|
+
} from "./chunk-c8chx29p.js";
|
|
19
|
+
import"./chunk-yfyb25rh.js";
|
|
18
20
|
import {
|
|
19
21
|
deployOutputDir,
|
|
20
22
|
deployStaticDir,
|
|
21
23
|
surfaceAdapterOutput
|
|
22
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-5m5nmvyq.js";
|
|
23
25
|
import {
|
|
24
26
|
ensureGitignore
|
|
25
27
|
} from "./chunk-yzhm0j9q.js";
|
|
26
|
-
import"./chunk-
|
|
28
|
+
import"./chunk-8ktnccpt.js";
|
|
27
29
|
import {
|
|
28
30
|
removedBuildFlags,
|
|
29
31
|
flagList,
|
|
30
32
|
removedBuildFlagsAdvice
|
|
31
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-pehfxfta.js";
|
|
32
34
|
import {
|
|
33
35
|
refuseIfDevRunning
|
|
34
|
-
} from "./chunk-
|
|
35
|
-
import"./chunk-2hn4b8z7.js";
|
|
36
|
+
} from "./chunk-akbpwfxc.js";
|
|
36
37
|
import {
|
|
37
38
|
refuseIfEjected
|
|
38
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-ey84smr6.js";
|
|
39
40
|
import"./chunk-jq5n4avg.js";
|
|
40
|
-
import"./chunk-
|
|
41
|
-
import"./chunk-
|
|
41
|
+
import"./chunk-r20tn01b.js";
|
|
42
|
+
import"./chunk-b07cmahc.js";
|
|
42
43
|
import {
|
|
43
44
|
prepareProject
|
|
44
|
-
} from "./chunk-
|
|
45
|
+
} from "./chunk-tzmab476.js";
|
|
45
46
|
import {
|
|
46
47
|
serverFeatures
|
|
47
|
-
} from "./chunk-
|
|
48
|
+
} from "./chunk-364znk6q.js";
|
|
48
49
|
|
|
49
50
|
// src/cli/commands/build.ts
|
|
50
51
|
import { existsSync } from "node:fs";
|
|
@@ -52,6 +53,38 @@ import { readdir, stat } from "node:fs/promises";
|
|
|
52
53
|
import { build } from "astro";
|
|
53
54
|
import { defineCommand } from "citty";
|
|
54
55
|
import { join } from "pathe";
|
|
56
|
+
|
|
57
|
+
// src/cli/build-failure.ts
|
|
58
|
+
import { z } from "zod";
|
|
59
|
+
var buildErrorSchema = z.looseObject({
|
|
60
|
+
errors: z.array(z.instanceof(Error)).optional(),
|
|
61
|
+
id: z.string().optional(),
|
|
62
|
+
loc: z.looseObject({
|
|
63
|
+
column: z.number().optional(),
|
|
64
|
+
file: z.string().optional(),
|
|
65
|
+
line: z.number().optional()
|
|
66
|
+
}).optional()
|
|
67
|
+
});
|
|
68
|
+
var failureDiagnostic = (error) => {
|
|
69
|
+
const parsed = buildErrorSchema.safeParse(error);
|
|
70
|
+
const { id, loc } = parsed.success ? parsed.data : {};
|
|
71
|
+
const name = error.name === "Error" ? "" : `${error.name}: `;
|
|
72
|
+
return {
|
|
73
|
+
code: "BLUME_BUILD_FAILED",
|
|
74
|
+
column: loc?.column,
|
|
75
|
+
file: loc?.file ?? id,
|
|
76
|
+
line: loc?.line,
|
|
77
|
+
message: `${name}${error.message}`,
|
|
78
|
+
severity: "error"
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
var astroBuildDiagnostics = (error) => {
|
|
82
|
+
const parsed = buildErrorSchema.safeParse(error);
|
|
83
|
+
const failures = parsed.success ? parsed.data.errors ?? [] : [];
|
|
84
|
+
return (failures.length > 0 ? failures : [error]).map(failureDiagnostic);
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
// src/cli/commands/build.ts
|
|
55
88
|
var BUDGET_JS = "budget-js";
|
|
56
89
|
var BUDGET_CSS = "budget-css";
|
|
57
90
|
var validateBudgetFlags = (args) => {
|
|
@@ -221,10 +254,18 @@ var buildCommand = defineCommand({
|
|
|
221
254
|
if (!runtimeDir) {
|
|
222
255
|
publishBuildProject(project);
|
|
223
256
|
}
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
257
|
+
try {
|
|
258
|
+
await build({
|
|
259
|
+
logLevel: "info",
|
|
260
|
+
root: project.context.outDir
|
|
261
|
+
});
|
|
262
|
+
} catch (error) {
|
|
263
|
+
if (error instanceof BlumeError || !(error instanceof Error)) {
|
|
264
|
+
throw error;
|
|
265
|
+
}
|
|
266
|
+
reportDiagnostics(astroBuildDiagnostics(error), root);
|
|
267
|
+
process.exit(1);
|
|
268
|
+
}
|
|
228
269
|
await reportCardCache(project, !runtimeDir);
|
|
229
270
|
const { deployment } = project.config;
|
|
230
271
|
const platform = deployPlatform(deployment);
|
|
@@ -257,5 +298,5 @@ export {
|
|
|
257
298
|
runClientAssetChecks
|
|
258
299
|
};
|
|
259
300
|
|
|
260
|
-
//# debugId=
|
|
261
|
-
//# sourceMappingURL=chunk-
|
|
301
|
+
//# debugId=D6CABD020883D7E964756E2164756E21
|
|
302
|
+
//# sourceMappingURL=chunk-5f86nr5m.js.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/cli/commands/build.ts", "../src/cli/build-failure.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import { existsSync } from \"node:fs\";\nimport { readdir, stat } from \"node:fs/promises\";\n\nimport { build } from \"astro\";\nimport { defineCommand } from \"citty\";\nimport { join } from \"pathe\";\n\nimport { publishBuildProject } from \"../../astro/integration.ts\";\nimport { BlumeError } from \"../../core/diagnostics.ts\";\nimport { ensureGitignore } from \"../../core/gitignore.ts\";\nimport type { BlumeProject } from \"../../core/project-graph.ts\";\nimport { serverFeatures } from \"../../core/server-features.ts\";\nimport {\n deployOutputDir,\n deployStaticDir,\n surfaceAdapterOutput,\n} from \"../../deploy/adapter-output.ts\";\nimport { deployPlatform } from \"../../deploy/platforms/index.ts\";\nimport { cardCacheTally, ogCacheDir, pruneCardCache } from \"../../og/cache.ts\";\nimport {\n flagList,\n removedBuildFlags,\n removedBuildFlagsAdvice,\n} from \"../../upgrade/upgrade.ts\";\nimport { astroBuildDiagnostics } from \"../build-failure.ts\";\nimport { commandMeta } from \"../command-meta.ts\";\nimport { refuseIfDevRunning } from \"../dev-lock.ts\";\nimport { refuseIfEjected } from \"../eject-scripts.ts\";\nimport { logger, reportDiagnostics } from \"../log.ts\";\nimport { prepareProject } from \"../prepare.ts\";\n\nconst BUDGET_JS = \"budget-js\";\nconst BUDGET_CSS = \"budget-css\";\n\ninterface BudgetArgs {\n \"budget-css\"?: string;\n \"budget-js\"?: string;\n}\n\n/**\n * Reject a non-numeric performance budget. `Number(\"250kb\")` is `NaN` and\n * `total > NaN` is always false, so a typo'd flag would silently pass the gate;\n * fail up front instead.\n */\nconst validateBudgetFlags = (args: BudgetArgs): void => {\n for (const flag of [BUDGET_JS, BUDGET_CSS] as const) {\n const value = args[flag];\n const parsed = Number(value);\n // Equivalent to `!(parsed > 0)` but without the inverted check: this must\n // also reject `NaN` (a typo'd flag like \"250kb\"), which `parsed <= 0` alone\n // would let through since `NaN <= 0` is false.\n if (value !== undefined && (Number.isNaN(parsed) || parsed <= 0)) {\n logger.error(\n `Invalid --${flag} \"${value}\" (expected a positive number of kB).`\n );\n process.exit(1);\n }\n }\n};\n\n/**\n * Report how many OG cards the build read back from the on-disk cache against\n * how many it rendered (the endpoint tallies both), so a warm rebuild shows\n * where the time went. With `prune`, also drop the cached cards this build\n * never asked for — renamed pages, edited descriptions, cards from an earlier\n * Blume version — so a persisted cache holds exactly the current site's cards.\n */\nconst reportCardCache = async (\n project: BlumeProject,\n prune: boolean\n): Promise<void> => {\n const cards = cardCacheTally();\n if (!cards) {\n return;\n }\n logger.info(\n `OG cards: ${cards.hits} reused from the cache, ${cards.misses} rendered`\n );\n if (prune) {\n await pruneCardCache(ogCacheDir(project.context));\n }\n};\n\nconst formatBytes = (bytes: number): string => {\n if (bytes < 1024) {\n return `${bytes} B`;\n }\n const digits = bytes < 1024 * 100 ? 1 : 0;\n return `${(bytes / 1024).toFixed(digits)} kB`;\n};\n\n/** Sizes of `dist/_astro/*.<ext>`, largest first (empty when none exist). */\nconst astroAssets = async (\n distDir: string,\n ext: string\n): Promise<{ name: string; size: number }[]> => {\n const astroDir = join(distDir, \"_astro\");\n if (!existsSync(astroDir)) {\n return [];\n }\n const entries = await readdir(astroDir);\n const files = entries.filter((name) => name.endsWith(`.${ext}`));\n const sized = await Promise.all(\n files.map(async (name) => {\n const info = await stat(join(astroDir, name));\n return { name, size: info.size };\n })\n );\n return sized.toSorted((a, b) => b.size - a.size);\n};\n\nconst totalSize = (assets: { size: number }[]): number =>\n assets.reduce((sum, asset) => sum + asset.size, 0);\n\n/**\n * Print the client JavaScript Astro shipped, largest first, plus the total. A\n * dependency-free bundle report — the interactive weight of a docs site is its\n * `_astro/*.js`, so this surfaces regressions without a visualizer.\n */\nconst reportBundleSizes = async (distDir: string): Promise<void> => {\n const sized = await astroAssets(distDir, \"js\");\n if (sized.length === 0) {\n logger.info(\"No client JavaScript emitted — the site ships zero JS.\");\n return;\n }\n const rows = sized\n .slice(0, 15)\n .map((file) => ` ${formatBytes(file.size).padStart(8)} ${file.name}`);\n logger.box(\n [\n `Client JavaScript — ${sized.length} file(s), ${formatBytes(totalSize(sized))} total`,\n \"\",\n ...rows,\n sized.length > 15 ? ` … and ${sized.length - 15} more` : null,\n ]\n .filter((line) => line !== null)\n .join(\"\\n\")\n );\n};\n\n/**\n * Enforce a performance budget on the built client assets: fail the build when\n * total `_astro/*.js` (or `*.css`) exceeds the given kB cap. Budgets that would\n * otherwise be \"documented, not measured\" become a real CI gate. Returns whether\n * every budget passed.\n */\nconst enforceBudget = async (\n distDir: string,\n args: BudgetArgs\n): Promise<\"fail\" | \"pass\" | \"skip\"> => {\n const checks: { ext: string; limitKb: number; name: string }[] = [\n ...(args[BUDGET_JS]\n ? [{ ext: \"js\", limitKb: Number(args[BUDGET_JS]), name: \"JavaScript\" }]\n : []),\n ...(args[BUDGET_CSS]\n ? [{ ext: \"css\", limitKb: Number(args[BUDGET_CSS]), name: \"CSS\" }]\n : []),\n ];\n if (checks.length === 0) {\n return \"skip\";\n }\n let passed = true;\n for (const check of checks) {\n // oxlint-disable-next-line no-await-in-loop -- a couple of sequential reads\n const total = totalSize(await astroAssets(distDir, check.ext));\n const limit = check.limitKb * 1024;\n if (total > limit) {\n passed = false;\n logger.error(\n `${check.name} budget exceeded: ${formatBytes(total)} > ${check.limitKb} kB`\n );\n } else {\n logger.success(\n `${check.name} budget: ${formatBytes(total)} / ${check.limitKb} kB`\n );\n }\n }\n return passed ? \"pass\" : \"fail\";\n};\n\n/**\n * Run the optional bundle report (`--analyze`) and performance-budget gate\n * against the directory whose `_astro/` client assets the deploy serves.\n * Shared by real and isolated builds — an isolated CI run passing\n * `--budget-js` must still fail on an exceeded budget rather than silently\n * skipping the check. Exits non-zero when a budget is exceeded.\n */\nexport const runClientAssetChecks = async (\n staticDir: string,\n args: { analyze?: boolean } & BudgetArgs\n): Promise<void> => {\n if (args.analyze) {\n await reportBundleSizes(staticDir);\n }\n if ((await enforceBudget(staticDir, args)) === \"fail\") {\n process.exit(1);\n }\n};\n\n/**\n * Print the build summary box and run the optional bundle report / budget\n * gate against the served static dir. The deploy artifacts themselves\n * (search index, llms.txt, sitemap, robots, redirect and header files, …)\n * were written by the integration's `astro:build:done` hook during\n * `build()` — see `deploy/artifacts.ts`. Exits non-zero if a budget is\n * exceeded.\n */\nconst reportBuild = async (\n project: BlumeProject,\n distDir: string,\n args: { analyze?: boolean } & BudgetArgs\n): Promise<void> => {\n const { config } = project;\n const features = serverFeatures(config);\n // The sitemap needs both the flag and a `site` (absolute URLs) — only the\n // latter deserves the remediation hint.\n const sitemapNote = config.seo.sitemap\n ? \"no (set deployment.site)\"\n : \"no (seo.sitemap is false)\";\n const rows: [label: string, value: string | number][] = [\n [\"Output\", config.deployment.options.output],\n [\"Adapter\", config.deployment.kind],\n [\"Site\", config.deployment.options.site ?? \"not set\"],\n [\"Search\", config.search.provider.kind],\n [\"Redirects\", config.redirects.length],\n [\n \"Sitemap\",\n config.deployment.options.site && config.seo.sitemap\n ? \"yes\"\n : sitemapNote,\n ],\n [\"Robots\", config.seo.robots ? \"yes\" : \"no\"],\n [\"Agent JSON\", config.agents.agentReadability ? \"yes\" : \"no\"],\n [\"LLM files\", config.agents.llmsTxt.enabled ? \"yes\" : \"no\"],\n [\"Server features\", features.length > 0 ? features.join(\", \") : \"none\"],\n ];\n // One label column for every row, sized by the longest label.\n const labelWidth = Math.max(...rows.map(([label]) => label.length)) + 2;\n logger.box(\n rows\n .map(([label, value]) => `${label.padEnd(labelWidth)}${value}`)\n .join(\"\\n\")\n );\n\n await runClientAssetChecks(distDir, args);\n\n // Only reachable with --no-strict (strict aborts earlier): repeat the missing\n // count next to the success banner so it can't scroll away unseen.\n if (project.droppedPages > 0) {\n logger.warn(\n `${project.droppedPages} page(s) failed frontmatter validation and are missing from this build.`\n );\n }\n logger.success(`Built to ${distDir}`);\n};\n\nexport const buildCommand = defineCommand({\n args: {\n analyze: {\n description: \"Report client JavaScript bundle sizes after the build.\",\n type: \"boolean\",\n },\n [BUDGET_CSS]: {\n description: \"Fail if total client CSS exceeds this many kB.\",\n type: \"string\",\n },\n [BUDGET_JS]: {\n description: \"Fail if total client JavaScript exceeds this many kB.\",\n type: \"string\",\n },\n isolated: {\n description:\n \"Build into an isolated .blume-verify runtime (and its own dist) so a running dev server and the real dist/ are untouched. For verifying changes while `blume dev` runs.\",\n type: \"boolean\",\n },\n preview: {\n description: \"Include drafts and unpublished CMS content.\",\n type: \"boolean\",\n },\n strict: {\n default: true,\n description:\n \"Fail on error diagnostics (default; pass --no-strict to build anyway, dropping pages that fail validation).\",\n type: \"boolean\",\n },\n },\n meta: commandMeta.build,\n async run({ args, rawArgs }) {\n const root = process.cwd();\n\n // citty accepts unknown flags, so a Blume 1 `--adapter vercel --output\n // server` would otherwise build a static site without a word.\n const removed = removedBuildFlags(rawArgs);\n if (removed.length > 0) {\n logger.error(\n `blume build no longer takes ${flagList(removed)}. ${removedBuildFlagsAdvice(removed)}`\n );\n process.exit(1);\n }\n await refuseIfEjected(root, \"build\");\n\n // `--isolated` (or BLUME_RUNTIME_DIR) relocates the whole runtime to a\n // sibling dir so this build never touches a live dev server's `.blume/` or\n // the user's real `dist/`. A non-default runtime dir has no dev lock, so the\n // refusal below lets it proceed; a plain build still refuses.\n const runtimeDir = args.isolated\n ? \".blume-verify\"\n : process.env.BLUME_RUNTIME_DIR;\n refuseIfDevRunning(root, \"building\", { isolatedHint: true, runtimeDir });\n if (args.isolated) {\n await ensureGitignore(root, [\".blume-verify/\"]);\n }\n\n validateBudgetFlags(args);\n\n const project = await prepareProject({\n mode: \"build\",\n preview: args.preview,\n root,\n runtimeDir,\n strict: args.strict,\n });\n\n logger.start(\n `Building ${project.graph.pages.length} page(s) (${project.config.deployment.options.output} output)`\n );\n\n // Hand the scanned project to the integration: its `astro:build:done`\n // hook writes the deploy artifacts (search index, llms.txt, sitemap, …)\n // into Astro's client output during the build. An isolated build is a\n // throwaway verify that only needs to confirm the site compiles and\n // renders, so it publishes nothing — no network post-steps (a hosted\n // search sync would push), no deploy artifacts.\n if (!runtimeDir) {\n publishBuildProject(project);\n }\n\n try {\n await build({\n logLevel: \"info\",\n root: project.context.outDir,\n });\n } catch (error) {\n // Astro rejects when the site fails to compile or render (MDX that\n // doesn't parse, a component that throws): report that as a build error\n // at the file it names, not as an internal error blaming Blume. A\n // BlumeError keeps its own diagnostic.\n if (error instanceof BlumeError || !(error instanceof Error)) {\n throw error;\n }\n reportDiagnostics(astroBuildDiagnostics(error), root);\n process.exit(1);\n }\n\n // A real build also prunes the cache; an isolated verify must not evict\n // cards a live dev server is still serving.\n await reportCardCache(project, !runtimeDir);\n\n // Everything the deploy target does differently after `astro build` comes\n // off its platform (see `deploy/platforms/*`): a server build's post-build\n // step (Vercel's function-bundle audit and negotiation routes, Cloudflare's\n // wrapper Worker), and where its bundle and static assets landed.\n const { deployment } = project.config;\n const platform = deployPlatform(deployment);\n const server = deployment.options.output === \"server\";\n const finalize = async (isolated: boolean): Promise<void> => {\n if (\n server &&\n platform.finalizeBuild &&\n !(await platform.finalizeBuild({ isolated, log: logger, project }))\n ) {\n process.exit(1);\n }\n };\n\n // The bundle report and budget gate still run for an isolated build —\n // `blume build --isolated --budget-js 100` exiting 0 without measuring\n // anything would be a silent false pass in CI. An isolated build never\n // surfaces the adapter bundle to the project root, so its output dirs\n // resolve under the relocated runtime.\n if (runtimeDir) {\n await finalize(true);\n await runClientAssetChecks(\n deployStaticDir(project.config, project.context),\n args\n );\n logger.success(\n `Isolated build OK — output at ${deployOutputDir(project.config, project.context)} (not published).`\n );\n return;\n }\n\n // A server adapter's deploy bundle is a build artifact — keep it out of\n // version control (Vercel's own CLI ignores `.vercel/` for the same reason).\n // Ignoring it is independent of whether the bundle had to be moved below:\n // Vercel writes straight to the project root, Netlify does not.\n const { ignoreDir } = platform.hiddenRuntime;\n if (server && ignoreDir) {\n await ensureGitignore(root, [ignoreDir]);\n }\n\n // Netlify writes its deploy bundle relative to the Astro root — which Blume\n // points at the hidden `.blume` runtime — so the bundle lands where the\n // deploy platform never looks. Surface it up to the project root before\n // publishing artifacts into the served static dir.\n const surfaced = await surfaceAdapterOutput(\n project.config,\n project.context\n );\n if (surfaced.moved) {\n logger.success(`Surfaced ${deployment.kind} output to ${surfaced.to}`);\n }\n\n await finalize(false);\n\n await reportBuild(\n project,\n deployStaticDir(project.config, project.context),\n args\n );\n },\n});\n",
|
|
6
|
+
"import { z } from \"zod\";\n\nimport type { Diagnostic } from \"../core/types.ts\";\n\n/**\n * The fields of an `astro build` rejection the report reads. Rolldown bundles\n * every plugin failure (an MDX compile error, say) into one error whose\n * `errors` holds each; a failure carries `loc` where the compiler pinned it,\n * or only `id`, the module that failed.\n */\nconst buildErrorSchema = z.looseObject({\n errors: z.array(z.instanceof(Error)).optional(),\n id: z.string().optional(),\n loc: z\n .looseObject({\n column: z.number().optional(),\n file: z.string().optional(),\n line: z.number().optional(),\n })\n .optional(),\n});\n\n/** One failure as a diagnostic at the file (and position) it names. */\nconst failureDiagnostic = (error: Error): Diagnostic => {\n const parsed = buildErrorSchema.safeParse(error);\n const { id, loc } = parsed.success ? parsed.data : {};\n // A named error (`MDXError`, `CompilerError`) says which step failed.\n const name = error.name === \"Error\" ? \"\" : `${error.name}: `;\n return {\n code: \"BLUME_BUILD_FAILED\",\n column: loc?.column,\n file: loc?.file ?? id,\n line: loc?.line,\n message: `${name}${error.message}`,\n severity: \"error\",\n };\n};\n\n/**\n * What `astro build` rejected with, as build diagnostics: one per failure\n * Rolldown collected, else the error itself. A page Blume's own checks pass\n * can still fail Astro's compile (MDX that doesn't parse) or render, and that\n * is a problem in the site, reported at its file, rather than an internal\n * error blaming Blume.\n */\nexport const astroBuildDiagnostics = (error: Error): Diagnostic[] => {\n const parsed = buildErrorSchema.safeParse(error);\n const failures = parsed.success ? (parsed.data.errors ?? []) : [];\n return (failures.length > 0 ? failures : [error]).map(failureDiagnostic);\n};\n"
|
|
7
|
+
],
|
|
8
|
+
"mappings": "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",
|
|
9
|
+
"debugId": "D6CABD020883D7E964756E2164756E21",
|
|
10
|
+
"names": []
|
|
11
|
+
}
|