blume 1.7.2 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +19 -0
- package/CHANGELOG.md +227 -0
- package/README.md +34 -21
- package/dist/cli/chunk-11j0384y.js +148 -0
- package/dist/cli/chunk-11j0384y.js.map +10 -0
- package/dist/cli/{chunk-xhtpx3ff.js → chunk-1w8dp3qb.js} +17 -16
- package/dist/cli/{chunk-xhtpx3ff.js.map → chunk-1w8dp3qb.js.map} +3 -3
- package/dist/cli/chunk-2q1dwty4.js +75 -0
- package/dist/cli/chunk-2q1dwty4.js.map +11 -0
- package/dist/cli/chunk-41za066z.js +122 -0
- package/dist/cli/chunk-41za066z.js.map +11 -0
- package/dist/cli/chunk-5a2z0198.js +133 -0
- package/dist/cli/chunk-5a2z0198.js.map +10 -0
- package/dist/cli/{chunk-9he6crym.js → chunk-6k8vp3ta.js} +25 -13
- package/dist/cli/{chunk-9he6crym.js.map → chunk-6k8vp3ta.js.map} +4 -4
- package/dist/cli/{chunk-mt76t7dj.js → chunk-79njf86q.js} +133 -54
- package/dist/cli/chunk-79njf86q.js.map +11 -0
- package/dist/cli/{chunk-3w7b2vcx.js → chunk-7ez8ny0t.js} +2 -2
- package/dist/cli/{chunk-688e0dde.js → chunk-88cpgt6h.js} +1 -1
- package/dist/cli/chunk-a9kptbw5.js +361 -0
- package/dist/cli/chunk-a9kptbw5.js.map +14 -0
- package/dist/cli/chunk-abh8yjkn.js +31 -0
- package/dist/cli/chunk-abh8yjkn.js.map +10 -0
- package/dist/cli/chunk-b5aj94ah.js +91 -0
- package/dist/cli/chunk-b5aj94ah.js.map +10 -0
- package/dist/cli/{chunk-hs3gbh8p.js → chunk-bctazmbk.js} +9 -5
- package/dist/cli/chunk-bctazmbk.js.map +10 -0
- package/dist/cli/chunk-beat36xx.js +279 -0
- package/dist/cli/chunk-beat36xx.js.map +10 -0
- package/dist/cli/chunk-bnbmcwfb.js +145 -0
- package/dist/cli/chunk-bnbmcwfb.js.map +11 -0
- package/dist/cli/{chunk-9bkjd11x.js → chunk-bw22s759.js} +15 -5
- package/dist/cli/{chunk-9bkjd11x.js.map → chunk-bw22s759.js.map} +4 -4
- package/dist/cli/chunk-by2290sx.js +39 -0
- package/dist/cli/chunk-by2290sx.js.map +10 -0
- package/dist/cli/chunk-d1tadaw7.js +79 -0
- package/dist/cli/chunk-d1tadaw7.js.map +10 -0
- package/dist/cli/{chunk-t3tj0dgr.js → chunk-d80hr03s.js} +24 -19
- package/dist/cli/chunk-d80hr03s.js.map +15 -0
- package/dist/cli/chunk-ernrthtr.js +97 -0
- package/dist/cli/chunk-ernrthtr.js.map +10 -0
- package/dist/cli/chunk-f2972sbt.js +374 -0
- package/dist/cli/chunk-f2972sbt.js.map +10 -0
- package/dist/cli/{chunk-exeeb35e.js → chunk-f7t03s3g.js} +2 -2
- package/dist/cli/{chunk-2z47ypj8.js → chunk-fa25z98p.js} +16 -3
- package/dist/cli/chunk-fa25z98p.js.map +11 -0
- package/dist/cli/{chunk-12dxjqk7.js → chunk-fh5hj5jt.js} +44 -21
- package/dist/cli/chunk-fh5hj5jt.js.map +10 -0
- package/dist/cli/{chunk-8cd8tj54.js → chunk-j8mw0za6.js} +86 -57
- package/dist/cli/chunk-j8mw0za6.js.map +35 -0
- package/dist/cli/chunk-jts8mvcz.js +106 -0
- package/dist/cli/{chunk-2mzebbbz.js.map → chunk-jts8mvcz.js.map} +6 -4
- package/dist/cli/{chunk-ejjx8znq.js → chunk-mnqj32sj.js} +505 -536
- package/dist/cli/chunk-mnqj32sj.js.map +12 -0
- package/dist/cli/{chunk-196vjxp9.js → chunk-mwt1k8n7.js} +100 -372
- package/dist/cli/chunk-mwt1k8n7.js.map +10 -0
- package/dist/cli/chunk-nk3ts2xk.js +51 -0
- package/dist/cli/chunk-nk3ts2xk.js.map +10 -0
- package/dist/cli/{chunk-n9sra6sy.js → chunk-pat2zzwc.js} +10 -14
- package/dist/cli/{chunk-n9sra6sy.js.map → chunk-pat2zzwc.js.map} +2 -2
- package/dist/cli/chunk-pnnvybbk.js +176 -0
- package/dist/cli/chunk-pnnvybbk.js.map +11 -0
- package/dist/cli/{chunk-cvky9gb2.js → chunk-sqn5t4q0.js} +81 -87
- package/dist/cli/chunk-sqn5t4q0.js.map +10 -0
- package/dist/cli/{chunk-eevwt1sc.js → chunk-tzne8qfq.js} +15 -15
- package/dist/cli/{chunk-eevwt1sc.js.map → chunk-tzne8qfq.js.map} +1 -1
- package/dist/cli/chunk-xaz13gwg.js +12449 -0
- package/dist/cli/chunk-xaz13gwg.js.map +182 -0
- package/dist/cli/chunk-y3e45rc8.js +102 -0
- package/dist/cli/chunk-y3e45rc8.js.map +10 -0
- package/dist/cli/chunk-z01ze5c1.js +261 -0
- package/dist/cli/chunk-z01ze5c1.js.map +10 -0
- package/dist/cli/{chunk-5n7t497w.js → chunk-z1f5arsg.js} +247 -755
- package/dist/cli/chunk-z1f5arsg.js.map +36 -0
- package/dist/cli/{chunk-hdm2dkd2.js → chunk-zg2gtj10.js} +1086 -2596
- package/dist/cli/chunk-zg2gtj10.js.map +35 -0
- package/dist/cli/{chunk-ppfvdcd4.js → chunk-zxccj738.js} +1 -1
- package/dist/cli/index.js +214 -57
- package/dist/cli/index.js.map +8 -7
- package/dist/types/ai/agent-readability.d.ts +52 -0
- package/dist/types/ai/ai-catalog.d.ts +42 -0
- package/dist/types/ai/api/paths.d.ts +17 -0
- package/dist/types/ai/api-catalog.d.ts +18 -0
- package/dist/types/ai/ask.d.ts +368 -0
- package/dist/types/ai/changelog-markdown.d.ts +2 -0
- package/dist/types/ai/component-markdown.d.ts +2 -2
- package/dist/types/ai/index.d.ts +24 -0
- package/dist/types/ai/link-headers.d.ts +24 -0
- package/dist/types/ai/llms.d.ts +25 -0
- package/dist/types/ai/markdown.d.ts +45 -0
- package/dist/types/ai/mcp/discovery.d.ts +68 -0
- package/dist/types/ai/mcp/tools.d.ts +16 -0
- package/dist/types/ai/openapi-components.d.ts +43 -0
- package/dist/types/ai/relative-links.d.ts +26 -0
- package/dist/types/ai/serializers.d.ts +15 -0
- package/dist/types/ai/skills.d.ts +42 -0
- package/dist/types/ai/tar.d.ts +25 -0
- package/dist/types/ai/visibility.d.ts +17 -0
- package/dist/types/ai/web-bot-auth.d.ts +16 -0
- package/dist/types/analytics/adobe.d.ts +35 -0
- package/dist/types/analytics/amplitude.d.ts +50 -0
- package/dist/types/analytics/clarity.d.ts +31 -0
- package/dist/types/analytics/clearbit.d.ts +29 -0
- package/dist/types/analytics/cloudflare.d.ts +41 -0
- package/dist/types/analytics/fathom.d.ts +41 -0
- package/dist/types/analytics/google-analytics.d.ts +44 -0
- package/dist/types/analytics/google-tag-manager.d.ts +40 -0
- package/dist/types/analytics/head.d.ts +30 -0
- package/dist/types/analytics/heap.d.ts +40 -0
- package/dist/types/analytics/hightouch.d.ts +44 -0
- package/dist/types/analytics/hotjar.d.ts +33 -0
- package/dist/types/analytics/index.d.ts +61 -0
- package/dist/types/analytics/inline.d.ts +17 -0
- package/dist/types/analytics/logrocket.d.ts +44 -0
- package/dist/types/analytics/mixpanel.d.ts +67 -0
- package/dist/types/analytics/pirsch.d.ts +42 -0
- package/dist/types/analytics/plausible.d.ts +56 -0
- package/dist/types/analytics/posthog.d.ts +45 -0
- package/dist/types/analytics/schema.d.ts +320 -0
- package/dist/types/analytics/script.d.ts +46 -0
- package/dist/types/analytics/segment.d.ts +50 -0
- package/dist/types/analytics/vercel.d.ts +48 -0
- package/dist/types/astro/integration.d.ts +76 -0
- package/dist/types/astro/markdown-negotiation.d.ts +23 -0
- package/dist/types/astro/module-types.d.ts +14 -0
- package/dist/types/astro/pages.d.ts +44 -0
- package/dist/types/cli/env.d.ts +12 -0
- package/dist/types/cli/init/scaffold.d.ts +154 -0
- package/dist/types/components/layout/nav-utils.d.ts +11 -0
- package/dist/types/core/adapter.d.ts +47 -0
- package/dist/types/core/api-name.d.ts +7 -0
- package/dist/types/core/changelog-index.d.ts +13 -0
- package/dist/types/core/config-input.d.ts +209 -505
- package/dist/types/core/config.d.ts +60 -34
- package/dist/types/core/content-assets.d.ts +76 -0
- package/dist/types/core/custom-pages.d.ts +33 -0
- package/dist/types/core/data.d.ts +28 -11
- package/dist/types/core/define-components.d.ts +12 -9
- package/dist/types/core/deployment-env.d.ts +6 -11
- package/dist/types/core/frontmatter.d.ts +10 -0
- package/dist/types/core/graph.d.ts +18 -0
- package/dist/types/core/heading-markers.d.ts +54 -0
- package/dist/types/core/i18n-ui.d.ts +6 -2
- package/dist/types/core/i18n.d.ts +87 -0
- package/dist/types/core/includes.d.ts +138 -0
- package/dist/types/core/last-modified.d.ts +47 -0
- package/dist/types/core/links.d.ts +95 -0
- package/dist/types/core/locale-links.d.ts +60 -0
- package/dist/types/core/manifest.d.ts +17 -0
- package/dist/types/core/meta.d.ts +38 -0
- package/dist/types/core/nav-diagnostics.d.ts +26 -0
- package/dist/types/core/navigation.d.ts +6 -0
- package/dist/types/core/node-require.d.ts +19 -0
- package/dist/types/core/package-json.d.ts +13 -0
- package/dist/types/core/probe.d.ts +42 -0
- package/dist/types/core/project-graph.d.ts +51 -0
- package/dist/types/core/project.d.ts +2 -0
- package/dist/types/core/safe-href.d.ts +2 -0
- package/dist/types/core/safe-links.d.ts +26 -0
- package/dist/types/core/schema.d.ts +2291 -441
- package/dist/types/core/site-url.d.ts +16 -0
- package/dist/types/core/sources/assets.d.ts +36 -0
- package/dist/types/core/sources/cache.d.ts +37 -0
- package/dist/types/core/sources/collection.d.ts +28 -0
- package/dist/types/core/sources/contentful-rich-text.d.ts +31 -0
- package/dist/types/core/sources/contentful.d.ts +40 -0
- package/dist/types/core/sources/filesystem.d.ts +24 -0
- package/dist/types/core/sources/github-releases.d.ts +31 -0
- package/dist/types/core/sources/json.d.ts +30 -0
- package/dist/types/core/sources/lexical.d.ts +19 -0
- package/dist/types/core/sources/lower.d.ts +75 -0
- package/dist/types/core/sources/mdx-remote.d.ts +28 -0
- package/dist/types/core/sources/normalize.d.ts +147 -0
- package/dist/types/core/sources/notion.d.ts +131 -0
- package/dist/types/core/sources/obsidian.d.ts +46 -0
- package/dist/types/core/sources/payload.d.ts +39 -0
- package/dist/types/core/sources/portable-text.d.ts +42 -0
- package/dist/types/core/sources/read.d.ts +23 -0
- package/dist/types/core/sources/remote.d.ts +74 -0
- package/dist/types/core/sources/resolve.d.ts +19 -0
- package/dist/types/core/sources/sanity.d.ts +43 -0
- package/dist/types/core/sources/strapi-blocks.d.ts +12 -0
- package/dist/types/core/sources/strapi.d.ts +33 -0
- package/dist/types/core/sources/types.d.ts +7 -0
- package/dist/types/core/sources/watch.d.ts +45 -0
- package/dist/types/core/text-width.d.ts +11 -0
- package/dist/types/core/types.d.ts +20 -1
- package/dist/types/core/unrecognized-keys.d.ts +7 -0
- package/dist/types/core/versions.d.ts +72 -0
- package/dist/types/core/yaml.d.ts +9 -0
- package/dist/types/deploy/adapter-output.d.ts +45 -0
- package/dist/types/deploy/adapters/cloudflare.d.ts +40 -0
- package/dist/types/deploy/adapters/index.d.ts +29 -0
- package/dist/types/deploy/adapters/netlify.d.ts +37 -0
- package/dist/types/deploy/adapters/node.d.ts +37 -0
- package/dist/types/deploy/adapters/registry.d.ts +133 -0
- package/dist/types/deploy/adapters/types.d.ts +71 -0
- package/dist/types/deploy/adapters/vercel.d.ts +38 -0
- package/dist/types/deploy/artifacts.d.ts +65 -0
- package/dist/types/deploy/cloudflare-negotiation.d.ts +196 -0
- package/dist/types/deploy/function-bundle.d.ts +80 -0
- package/dist/types/deploy/headers.d.ts +50 -0
- package/dist/types/deploy/node-headers.d.ts +42 -0
- package/dist/types/deploy/platforms/cloudflare.d.ts +40 -0
- package/dist/types/deploy/platforms/index.d.ts +18 -0
- package/dist/types/deploy/platforms/netlify.d.ts +13 -0
- package/dist/types/deploy/platforms/node.d.ts +11 -0
- package/dist/types/deploy/platforms/paths.d.ts +27 -0
- package/dist/types/deploy/platforms/static.d.ts +10 -0
- package/dist/types/deploy/platforms/types.d.ts +104 -0
- package/dist/types/deploy/platforms/vercel.d.ts +32 -0
- package/dist/types/deploy/redirects.d.ts +53 -0
- package/dist/types/deploy/robots.d.ts +8 -0
- package/dist/types/deploy/rss.d.ts +31 -0
- package/dist/types/deploy/sitemap.d.ts +21 -0
- package/dist/types/deploy/vercel-negotiation.d.ts +109 -0
- package/dist/types/markdown/code-title.d.ts +32 -0
- package/dist/types/markdown/fence-meta.d.ts +23 -0
- package/dist/types/markdown/themes.d.ts +3 -3
- package/dist/types/openapi/asyncapi.d.ts +129 -0
- package/dist/types/openapi/graphql-build.d.ts +8 -0
- package/dist/types/openapi/graphql.d.ts +122 -0
- package/dist/types/openapi/model.d.ts +158 -0
- package/dist/types/openapi/parse.d.ts +57 -0
- package/dist/types/openapi/references.d.ts +37 -25
- package/dist/types/openapi/render-mdx.d.ts +33 -0
- package/dist/types/openapi/sentence.d.ts +7 -0
- package/dist/types/openapi/signature.d.ts +10 -0
- package/dist/types/openapi/source.d.ts +22 -0
- package/dist/types/openapi/spec-dependency-error.d.ts +10 -0
- package/dist/types/reference/asyncapi.d.ts +166 -0
- package/dist/types/reference/graphql.d.ts +181 -0
- package/dist/types/reference/index.d.ts +32 -0
- package/dist/types/reference/openapi.d.ts +165 -0
- package/dist/types/reference/options.d.ts +157 -0
- package/dist/types/reference/scalar.d.ts +136 -0
- package/dist/types/reference/schema.d.ts +630 -0
- package/dist/types/search/adapters/algolia.d.ts +32 -0
- package/dist/types/search/adapters/flexsearch.d.ts +12 -0
- package/dist/types/search/adapters/index.d.ts +31 -0
- package/dist/types/search/adapters/mixedbread.d.ts +22 -0
- package/dist/types/search/adapters/orama-cloud.d.ts +33 -0
- package/dist/types/search/adapters/orama.d.ts +13 -0
- package/dist/types/search/adapters/pagefind.d.ts +12 -0
- package/dist/types/search/adapters/registry.d.ts +228 -0
- package/dist/types/search/adapters/types.d.ts +34 -0
- package/dist/types/search/adapters/typesense.d.ts +42 -0
- package/dist/types/search/build.d.ts +23 -0
- package/dist/types/search/documents.d.ts +90 -0
- package/dist/types/search/facets.d.ts +3 -0
- package/dist/types/search/sync/algolia.d.ts +14 -0
- package/dist/types/search/sync/index.d.ts +14 -0
- package/dist/types/search/sync/orama-cloud.d.ts +10 -0
- package/dist/types/search/sync/typesense.d.ts +14 -0
- package/dist/types/sources/contentful.d.ts +68 -0
- package/dist/types/sources/custom.d.ts +20 -0
- package/dist/types/sources/filesystem.d.ts +42 -0
- package/dist/types/sources/github-releases.d.ts +46 -0
- package/dist/types/sources/index.d.ts +48 -0
- package/dist/types/sources/mdx-remote.d.ts +63 -0
- package/dist/types/sources/notion.d.ts +65 -0
- package/dist/types/sources/obsidian.d.ts +34 -0
- package/dist/types/sources/payload.d.ts +68 -0
- package/dist/types/sources/registry.d.ts +1414 -0
- package/dist/types/sources/sanity.d.ts +69 -0
- package/dist/types/sources/shared.d.ts +46 -0
- package/dist/types/sources/strapi.d.ts +66 -0
- package/dist/types/theme/icon-kind.d.ts +11 -0
- package/dist/types/theme/icons.d.ts +20 -0
- package/docs/01-quickstart.mdx +18 -18
- package/docs/02-deployment.mdx +50 -26
- package/docs/03-upgrading.mdx +351 -0
- package/docs/04-migrating.mdx +58 -0
- package/docs/08-faq.mdx +3 -3
- package/docs/advanced/blog.mdx +13 -6
- package/docs/advanced/changelog.mdx +23 -35
- package/docs/advanced/custom-pages.mdx +20 -8
- package/docs/advanced/meta.ts +1 -8
- package/docs/advanced/skills.mdx +8 -0
- package/docs/cli/audit.mdx +646 -0
- package/docs/cli/doctor.mdx +29 -0
- package/docs/{reference/eval.mdx → cli/evals.mdx} +9 -8
- package/docs/cli/index.mdx +105 -0
- package/docs/cli/meta.ts +7 -0
- package/docs/{reference → cli}/translate.mdx +1 -1
- package/docs/cli/validate.mdx +41 -0
- package/docs/cli/version.mdx +40 -0
- package/docs/configuration/analytics.mdx +350 -59
- package/docs/configuration/ask-ai.mdx +176 -61
- package/docs/configuration/customization.mdx +15 -9
- package/docs/configuration/index.mdx +52 -31
- package/docs/configuration/search.mdx +75 -54
- package/docs/configuration/theming.mdx +24 -15
- package/docs/content/components.mdx +21 -5
- package/docs/{reference → content}/frontmatter.mdx +37 -1
- package/docs/content/i18n.mdx +8 -6
- package/docs/content/includes.mdx +2 -4
- package/docs/content/index.mdx +1 -1
- package/docs/content/islands.mdx +10 -5
- package/docs/content/meta.mdx +1 -1
- package/docs/content/meta.ts +1 -0
- package/docs/content/navigation.mdx +12 -7
- package/docs/content/sources.mdx +145 -50
- package/docs/content/syntax.mdx +26 -12
- package/docs/content/versioning.mdx +3 -3
- package/docs/discoverability/agent-discovery.mdx +91 -10
- package/docs/discoverability/index.mdx +5 -5
- package/docs/discoverability/json-api.mdx +4 -4
- package/docs/discoverability/llms-txt.mdx +6 -6
- package/docs/discoverability/markdown.mdx +4 -4
- package/docs/discoverability/mcp.mdx +11 -11
- package/docs/discoverability/sitemap-and-robots.mdx +3 -3
- package/docs/index.mdx +2 -2
- package/docs/references/asyncapi.mdx +59 -0
- package/docs/{advanced → references}/graphql.mdx +45 -32
- package/docs/{reference → references}/meta.ts +2 -2
- package/docs/references/openapi.mdx +171 -0
- package/docs/references/scalar.mdx +64 -0
- package/package.json +42 -8
- package/skills/blume/SKILL.md +21 -8
- package/skills/blume-migrate/SKILL.md +22 -21
- package/skills/blume-migrate/assets/oxfmt@0.67.0.patch +49 -0
- package/skills/blume-migrate/references/docusaurus.md +5 -4
- package/skills/blume-migrate/references/fumadocs.md +4 -4
- package/skills/blume-migrate/references/mintlify.md +23 -8
- package/skills/blume-migrate/references/monorepo.md +6 -6
- package/skills/blume-migrate/references/starlight.md +4 -4
- package/src/ai/agent-readability.ts +26 -22
- package/src/ai/ai-catalog.ts +259 -0
- package/src/ai/api/handlers.ts +46 -11
- package/src/ai/api-catalog.ts +8 -8
- package/src/ai/ask-data.ts +1 -1
- package/src/ai/ask.ts +624 -100
- package/src/ai/changelog-markdown.ts +91 -0
- package/src/ai/component-markdown.ts +328 -12
- package/src/ai/index.ts +45 -0
- package/src/ai/link-headers.ts +19 -6
- package/src/ai/llms.ts +26 -15
- package/src/ai/markdown.ts +35 -5
- package/src/ai/mcp/data.ts +9 -5
- package/src/ai/mcp/discovery.ts +1 -1
- package/src/ai/openapi-components.ts +4 -1
- package/src/ai/relative-links.ts +170 -0
- package/src/ai/serializers.ts +2 -2
- package/src/ai/skills.ts +1 -1
- package/src/ai/web-bot-auth.ts +2 -2
- package/src/analytics/adobe.ts +46 -0
- package/src/analytics/amplitude.ts +79 -0
- package/src/analytics/clarity.ts +46 -0
- package/src/analytics/clearbit.ts +47 -0
- package/src/analytics/cloudflare.ts +67 -0
- package/src/analytics/fathom.ts +64 -0
- package/src/analytics/google-analytics.ts +84 -0
- package/src/analytics/google-tag-manager.ts +61 -0
- package/src/analytics/head.ts +130 -0
- package/src/analytics/heap.ts +65 -0
- package/src/analytics/hightouch.ts +77 -0
- package/src/analytics/hotjar.ts +47 -0
- package/src/analytics/index.ts +71 -0
- package/src/analytics/inline.ts +21 -0
- package/src/analytics/logrocket.ts +71 -0
- package/src/analytics/mixpanel.ts +92 -0
- package/src/analytics/pirsch.ts +66 -0
- package/src/analytics/plausible.ts +83 -0
- package/src/analytics/posthog.ts +78 -0
- package/src/analytics/schema.ts +60 -0
- package/src/analytics/script.ts +60 -0
- package/src/analytics/segment.ts +85 -0
- package/src/analytics/vercel.ts +50 -0
- package/src/astro/adapter-root.ts +7 -9
- package/src/astro/component-slots.ts +131 -91
- package/src/astro/generate.ts +114 -345
- package/src/astro/integration.ts +2 -6
- package/src/astro/pages.ts +13 -101
- package/src/astro/render-deps.ts +379 -0
- package/src/astro/runtime-deps.ts +201 -0
- package/src/astro/templates.ts +554 -541
- package/src/audit/agent.ts +24 -0
- package/src/audit/catalog.ts +2 -2
- package/src/audit/checks/assets.ts +2 -2
- package/src/audit/checks/dns-aid.ts +1 -1
- package/src/audit/checks/duplicates.ts +3 -1
- package/src/audit/checks/i18n.ts +1 -1
- package/src/audit/checks/indexability.ts +7 -7
- package/src/audit/checks/links.ts +2 -2
- package/src/audit/checks/llms.ts +6 -6
- package/src/audit/checks/network.ts +3 -3
- package/src/audit/checks/og-image.ts +2 -2
- package/src/audit/checks/robots.ts +1 -1
- package/src/audit/checks/sitemap.ts +2 -2
- package/src/audit/checks/social.ts +1 -1
- package/src/audit/run.ts +4 -3
- package/src/audit/terms.ts +31 -0
- package/src/audit/url.ts +13 -13
- package/src/cli/command-meta.ts +10 -0
- package/src/cli/commands/audit.ts +39 -20
- package/src/cli/commands/build.ts +71 -314
- package/src/cli/commands/check.ts +1 -0
- package/src/cli/commands/dev.ts +40 -1
- package/src/cli/commands/doctor.ts +90 -14
- package/src/cli/commands/eject.ts +44 -7
- package/src/cli/commands/eval.ts +2 -2
- package/src/cli/commands/init.ts +161 -41
- package/src/cli/commands/migrate.ts +121 -0
- package/src/cli/commands/preview.ts +7 -1
- package/src/cli/commands/translate.ts +2 -2
- package/src/cli/commands/upgrade.ts +141 -0
- package/src/cli/commands/version.ts +57 -44
- package/src/cli/eject-scripts.ts +121 -6
- package/src/cli/index.ts +11 -1
- package/src/cli/init/install.ts +70 -0
- package/src/cli/init/questions.ts +7 -0
- package/src/cli/init/scaffold.ts +459 -75
- package/src/cli/lazy-command.ts +37 -1
- package/src/cli/prepare.ts +40 -6
- package/src/cli/required-secrets.ts +38 -11
- package/src/cli/unknown-flags.ts +266 -0
- package/src/cli/yarn-pnp.ts +52 -0
- package/src/components/content/AccordionItem.astro +7 -1
- package/src/components/content/Card.astro +4 -3
- package/src/components/content/ColorItem.astro +22 -4
- package/src/components/content/GithubInfo.astro +2 -2
- package/src/components/content/Prompt.astro +25 -25
- package/src/components/content/Tabs.astro +3 -1
- package/src/components/content/Tile.astro +2 -3
- package/src/components/content/Tooltip.astro +57 -9
- package/src/components/content/content-strings.ts +34 -0
- package/src/components/content/diff.ts +1 -1
- package/src/components/content/mermaid-element.ts +13 -2
- package/src/components/content/prompt-markdown.ts +292 -0
- package/src/components/content/tooltip-id.ts +41 -0
- package/src/components/islands/hooks.ts +75 -3
- package/src/components/layout/Analytics.astro +21 -79
- package/src/components/layout/Banner.astro +3 -1
- package/src/components/layout/DiscoveryLinks.astro +69 -0
- package/src/components/layout/Header.astro +83 -20
- package/src/components/layout/LanguageSwitcher.astro +4 -1
- package/src/components/layout/Logo.astro +23 -2
- package/src/components/layout/NavSelector.astro +13 -2
- package/src/components/layout/NavTree.astro +12 -3
- package/src/components/layout/NavTreeScript.astro +17 -3
- package/src/components/layout/PageActions.astro +3 -3
- package/src/components/layout/PageFeedback.astro +11 -1
- package/src/components/layout/PageLayout.astro +52 -5
- package/src/components/layout/ReferenceLayout.astro +21 -12
- package/src/components/layout/RootLayout.astro +69 -43
- package/src/components/layout/Search.astro +30 -6
- package/src/components/layout/WebMcp.astro +1 -1
- package/src/components/layout/analytics-client.ts +101 -15
- package/src/components/layout/drawer-inert.ts +113 -15
- package/src/components/layout/dropdown-clamp.ts +105 -0
- package/src/components/layout/head-scripts.ts +15 -6
- package/src/components/layout/nav-utils.ts +17 -0
- package/src/components/layout/search/algolia.ts +8 -8
- package/src/components/layout/search/orama-cloud.ts +9 -7
- package/src/components/layout/search/typesense.ts +11 -17
- package/src/components/openapi/MessageComposer.astro +2 -2
- package/src/components/openapi/Playground.astro +2 -2
- package/src/components/openapi/playground-client.ts +79 -10
- package/src/core/changelog-index.ts +24 -0
- package/src/core/component-overrides.ts +399 -154
- package/src/core/config-input.ts +212 -543
- package/src/core/config.ts +130 -41
- package/src/core/custom-pages.ts +105 -0
- package/src/core/data.ts +32 -11
- package/src/core/define-components.ts +12 -9
- package/src/core/deployment-env.ts +18 -74
- package/src/core/diagnostics.ts +14 -7
- package/src/core/graph.ts +69 -25
- package/src/core/i18n-ui.ts +6 -2
- package/src/core/i18n.ts +17 -0
- package/src/core/includes.ts +156 -38
- package/src/core/last-modified.ts +6 -11
- package/src/core/links.ts +166 -2
- package/src/core/manifest.ts +10 -3
- package/src/core/navigation.ts +137 -19
- package/src/core/new-tab.ts +35 -0
- package/src/core/node-require.ts +21 -0
- package/src/core/project-graph.ts +42 -26
- package/src/core/project.ts +9 -4
- package/src/core/request-body.ts +61 -0
- package/src/core/safe-href.ts +28 -0
- package/src/core/safe-links.ts +68 -0
- package/src/core/schema.ts +531 -721
- package/src/core/server-features.ts +8 -9
- package/src/core/sources/assets.ts +47 -11
- package/src/core/sources/collection.ts +67 -0
- package/src/core/sources/contentful-rich-text.ts +285 -0
- package/src/core/sources/contentful.ts +173 -0
- package/src/core/sources/github-releases.ts +51 -1
- package/src/core/sources/json.ts +71 -0
- package/src/core/sources/lexical.ts +195 -0
- package/src/core/sources/lower.ts +226 -0
- package/src/core/sources/normalize.ts +52 -2
- package/src/core/sources/notion.ts +39 -28
- package/src/core/sources/payload.ts +135 -0
- package/src/core/sources/portable-text.ts +11 -16
- package/src/core/sources/remote.ts +226 -0
- package/src/core/sources/resolve.ts +104 -166
- package/src/core/sources/sanity.ts +16 -49
- package/src/core/sources/strapi-blocks.ts +124 -0
- package/src/core/sources/strapi.ts +191 -0
- package/src/core/sources/types.ts +12 -1
- package/src/core/types.ts +20 -1
- package/src/core/ui-packs/ar.ts +6 -2
- package/src/core/ui-packs/bg.ts +6 -2
- package/src/core/ui-packs/bn.ts +6 -2
- package/src/core/ui-packs/ca.ts +3 -1
- package/src/core/ui-packs/cs.ts +6 -2
- package/src/core/ui-packs/da.ts +6 -2
- package/src/core/ui-packs/de.ts +6 -2
- package/src/core/ui-packs/el.ts +3 -1
- package/src/core/ui-packs/es.ts +3 -1
- package/src/core/ui-packs/fa.ts +6 -2
- package/src/core/ui-packs/fi.ts +6 -2
- package/src/core/ui-packs/fr.ts +3 -1
- package/src/core/ui-packs/he.ts +6 -2
- package/src/core/ui-packs/hi.ts +6 -2
- package/src/core/ui-packs/hr.ts +6 -2
- package/src/core/ui-packs/hu.ts +6 -2
- package/src/core/ui-packs/id.ts +6 -2
- package/src/core/ui-packs/it.ts +3 -1
- package/src/core/ui-packs/ja.ts +3 -1
- package/src/core/ui-packs/ko.ts +3 -1
- package/src/core/ui-packs/nl.ts +6 -2
- package/src/core/ui-packs/no.ts +6 -2
- package/src/core/ui-packs/pl.ts +6 -2
- package/src/core/ui-packs/pt-br.ts +3 -1
- package/src/core/ui-packs/pt.ts +3 -1
- package/src/core/ui-packs/ro.ts +6 -2
- package/src/core/ui-packs/ru.ts +6 -2
- package/src/core/ui-packs/sk.ts +6 -2
- package/src/core/ui-packs/sr.ts +6 -2
- package/src/core/ui-packs/sv.ts +6 -2
- package/src/core/ui-packs/th.ts +3 -1
- package/src/core/ui-packs/tr.ts +6 -2
- package/src/core/ui-packs/uk.ts +6 -2
- package/src/core/ui-packs/vi.ts +3 -1
- package/src/core/ui-packs/zh-tw.ts +3 -1
- package/src/core/ui-packs/zh.ts +3 -1
- package/src/core/unrecognized-keys.ts +10 -0
- package/src/core/version-cut.ts +116 -8
- package/src/deploy/adapter-output.ts +57 -97
- package/src/deploy/adapters/cloudflare.ts +39 -0
- package/src/deploy/adapters/index.ts +41 -0
- package/src/deploy/adapters/netlify.ts +34 -0
- package/src/deploy/adapters/node.ts +34 -0
- package/src/deploy/adapters/registry.ts +127 -0
- package/src/deploy/adapters/types.ts +92 -0
- package/src/deploy/adapters/vercel.ts +35 -0
- package/src/deploy/artifacts.ts +67 -28
- package/src/deploy/cloudflare-negotiation.ts +179 -100
- package/src/deploy/function-bundle.ts +18 -3
- package/src/deploy/headers.ts +129 -22
- package/src/deploy/node-headers.ts +198 -0
- package/src/deploy/platforms/cloudflare.ts +312 -0
- package/src/deploy/platforms/index.ts +67 -0
- package/src/deploy/platforms/netlify.ts +52 -0
- package/src/deploy/platforms/node.ts +40 -0
- package/src/deploy/platforms/paths.ts +42 -0
- package/src/deploy/platforms/static.ts +29 -0
- package/src/deploy/platforms/types.ts +112 -0
- package/src/deploy/platforms/vercel.ts +193 -0
- package/src/deploy/redirects.ts +30 -18
- package/src/deploy/robots.ts +3 -3
- package/src/deploy/rss.ts +2 -2
- package/src/deploy/sitemap.ts +2 -2
- package/src/deploy/vercel-negotiation.ts +27 -4
- package/src/eval/agents.ts +32 -1
- package/src/eval/findings.ts +19 -11
- package/src/eval/report.ts +10 -2
- package/src/markdown/external-links.ts +65 -0
- package/src/markdown/include.ts +45 -27
- package/src/markdown/index.ts +34 -9
- package/src/markdown/inline-code.ts +12 -6
- package/src/markdown/relative-links.ts +324 -0
- package/src/markdown/themes.ts +3 -3
- package/src/migrate/migrate.ts +149 -0
- package/src/openapi/parse.ts +64 -16
- package/src/openapi/proxy.ts +62 -10
- package/src/openapi/references.ts +147 -147
- package/src/openapi/render-mdx.ts +32 -10
- package/src/openapi/scalar.ts +15 -13
- package/src/openapi/sentence.ts +14 -0
- package/src/openapi/source.ts +37 -21
- package/src/openapi/spec-dependency-error.ts +15 -0
- package/src/reference/asyncapi.ts +83 -0
- package/src/reference/graphql.ts +89 -0
- package/src/reference/index.ts +40 -0
- package/src/reference/openapi.ts +83 -0
- package/src/reference/options.ts +201 -0
- package/src/reference/scalar.ts +136 -0
- package/src/reference/schema.ts +88 -0
- package/src/registry/eject.ts +97 -42
- package/src/search/adapters/algolia.ts +46 -0
- package/src/search/adapters/flexsearch.ts +29 -0
- package/src/search/adapters/index.ts +39 -0
- package/src/search/adapters/mixedbread.ts +39 -0
- package/src/search/adapters/orama-cloud.ts +51 -0
- package/src/search/adapters/orama.ts +24 -0
- package/src/search/adapters/pagefind.ts +27 -0
- package/src/search/adapters/registry.ts +131 -0
- package/src/search/adapters/types.ts +46 -0
- package/src/search/adapters/typesense.ts +57 -0
- package/src/search/build.ts +33 -7
- package/src/search/documents.ts +6 -0
- package/src/search/sync/algolia.ts +12 -11
- package/src/search/sync/index.ts +35 -20
- package/src/search/sync/orama-cloud.ts +12 -9
- package/src/search/sync/typesense.ts +15 -13
- package/src/sources/contentful.ts +63 -0
- package/src/sources/custom.ts +38 -0
- package/src/sources/filesystem.ts +51 -0
- package/src/sources/github-releases.ts +52 -0
- package/src/sources/index.ts +60 -0
- package/src/sources/mdx-remote.ts +76 -0
- package/src/sources/notion.ts +63 -0
- package/src/sources/obsidian.ts +38 -0
- package/src/sources/payload.ts +60 -0
- package/src/sources/registry.ts +182 -0
- package/src/sources/sanity.ts +66 -0
- package/src/sources/shared.ts +52 -0
- package/src/sources/strapi.ts +58 -0
- package/src/theme/entry.ts +47 -2
- package/src/translate/report.ts +40 -7
- package/src/upgrade/upgrade.ts +499 -0
- package/dist/cli/chunk-12dxjqk7.js.map +0 -10
- package/dist/cli/chunk-196vjxp9.js.map +0 -13
- package/dist/cli/chunk-2mzebbbz.js +0 -69
- package/dist/cli/chunk-2z47ypj8.js.map +0 -11
- package/dist/cli/chunk-30e87n55.js +0 -108
- package/dist/cli/chunk-30e87n55.js.map +0 -10
- package/dist/cli/chunk-450a7rcr.js +0 -185
- package/dist/cli/chunk-450a7rcr.js.map +0 -11
- package/dist/cli/chunk-5n7t497w.js.map +0 -40
- package/dist/cli/chunk-61j18dwk.js +0 -5342
- package/dist/cli/chunk-61j18dwk.js.map +0 -58
- package/dist/cli/chunk-88by27n5.js +0 -17
- package/dist/cli/chunk-88by27n5.js.map +0 -10
- package/dist/cli/chunk-8cd8tj54.js.map +0 -34
- package/dist/cli/chunk-aztttvb3.js +0 -381
- package/dist/cli/chunk-aztttvb3.js.map +0 -12
- package/dist/cli/chunk-cvky9gb2.js.map +0 -11
- package/dist/cli/chunk-ejjx8znq.js.map +0 -15
- package/dist/cli/chunk-fmceyezb.js +0 -1007
- package/dist/cli/chunk-fmceyezb.js.map +0 -13
- package/dist/cli/chunk-hdm2dkd2.js.map +0 -48
- package/dist/cli/chunk-hs3gbh8p.js.map +0 -10
- package/dist/cli/chunk-jbj4qhfw.js +0 -30
- package/dist/cli/chunk-jbj4qhfw.js.map +0 -10
- package/dist/cli/chunk-mqb2ka8m.js +0 -68
- package/dist/cli/chunk-mqb2ka8m.js.map +0 -10
- package/dist/cli/chunk-mt76t7dj.js.map +0 -11
- package/dist/cli/chunk-q4rae3bg.js +0 -60
- package/dist/cli/chunk-q4rae3bg.js.map +0 -10
- package/dist/cli/chunk-ra1v2nc2.js +0 -35
- package/dist/cli/chunk-ra1v2nc2.js.map +0 -10
- package/dist/cli/chunk-t3tj0dgr.js.map +0 -15
- package/dist/cli/chunk-tqa1s0k8.js +0 -69
- package/dist/cli/chunk-tqa1s0k8.js.map +0 -11
- package/dist/cli/chunk-vh9w1sgp.js +0 -73
- package/dist/cli/chunk-vh9w1sgp.js.map +0 -10
- package/dist/cli/chunk-vkrsvbr5.js +0 -107
- package/dist/cli/chunk-vkrsvbr5.js.map +0 -11
- package/dist/cli/chunk-vrfp10qk.js +0 -81
- package/dist/cli/chunk-vrfp10qk.js.map +0 -10
- package/dist/cli/chunk-wjt80jps.js +0 -1049
- package/dist/cli/chunk-wjt80jps.js.map +0 -24
- package/docs/advanced/api-reference.mdx +0 -240
- package/docs/reference/cli.mdx +0 -197
- package/skills/blume-migrate/assets/oxfmt@0.55.0.patch +0 -20
- package/src/components/content/changelog-element.ts +0 -69
- package/src/search/providers.ts +0 -91
- /package/dist/cli/{chunk-3w7b2vcx.js.map → chunk-7ez8ny0t.js.map} +0 -0
- /package/dist/cli/{chunk-688e0dde.js.map → chunk-88cpgt6h.js.map} +0 -0
- /package/dist/cli/{chunk-exeeb35e.js.map → chunk-f7t03s3g.js.map} +0 -0
- /package/dist/cli/{chunk-ppfvdcd4.js.map → chunk-zxccj738.js.map} +0 -0
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/cli/commands/preview.ts"],
|
|
4
|
-
"sourcesContent": [
|
|
5
|
-
"import { existsSync } from \"node:fs\";\n\nimport { preview } from \"astro\";\nimport { defineCommand } from \"citty\";\nimport { join } from \"pathe\";\n\nimport { loadConfig } from \"../../core/config.ts\";\nimport { resolveProjectContext } from \"../../core/project.ts\";\nimport { parsePort } from \"../args.ts\";\nimport { commandMeta } from \"../command-meta.ts\";\nimport { normalizeHost } from \"../host-args.ts\";\nimport { logger } from \"../log.ts\";\n\nexport const previewCommand = defineCommand({\n args: {\n host: { description: \"Network host to bind.\", type: \"string\" },\n port: { description: \"Port to listen on.\", type: \"string\" },\n },\n meta: commandMeta.preview,\n async run({ args }) {\n const root = process.cwd();\n const { config } = await loadConfig(root);\n const context = resolveProjectContext(root, config);\n\n if (!existsSync(join(context.outDir, \"astro.config.mjs\"))) {\n logger.error(\"No build found. Run `blume build` first.\");\n process.exit(1);\n }\n\n await preview({\n logLevel: \"info\",\n root: context.outDir,\n server: {\n // `normalizeHost` maps a bare `--host` (citty parses it as \"\") to\n // `true` so Vite binds all interfaces instead of the hostname \"\".\n host: normalizeHost(args.host),\n port: parsePort(args.port),\n },\n });\n },\n});\n"
|
|
6
|
-
],
|
|
7
|
-
"mappings": ";;;;;;;;;;;;;;;AAAA;AAEA;AACA;AACA;AASO,IAAM,iBAAiB,cAAc;AAAA,EAC1C,MAAM;AAAA,IACJ,MAAM,EAAE,aAAa,yBAAyB,MAAM,SAAS;AAAA,IAC7D,MAAM,EAAE,aAAa,sBAAsB,MAAM,SAAS;AAAA,EAC5D;AAAA,EACA,MAAM,YAAY;AAAA,OACZ,IAAG,GAAG,QAAQ;AAAA,IAClB,MAAM,OAAO,QAAQ,IAAI;AAAA,IACzB,QAAQ,WAAW,MAAM,WAAW,IAAI;AAAA,IACxC,MAAM,UAAU,sBAAsB,MAAM,MAAM;AAAA,IAElD,IAAI,CAAC,WAAW,KAAK,QAAQ,QAAQ,kBAAkB,CAAC,GAAG;AAAA,MACzD,OAAO,MAAM,0CAA0C;AAAA,MACvD,QAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,IAEA,MAAM,QAAQ;AAAA,MACZ,UAAU;AAAA,MACV,MAAM,QAAQ;AAAA,MACd,QAAQ;AAAA,QAGN,MAAM,cAAc,KAAK,IAAI;AAAA,QAC7B,MAAM,UAAU,KAAK,IAAI;AAAA,MAC3B;AAAA,IACF,CAAC;AAAA;AAEL,CAAC;",
|
|
8
|
-
"debugId": "F86008553E8CAFA164756E2164756E21",
|
|
9
|
-
"names": []
|
|
10
|
-
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
searchProviderMeta
|
|
4
|
-
} from "./chunk-q4rae3bg.js";
|
|
5
|
-
import {
|
|
6
|
-
needsPlaygroundProxy
|
|
7
|
-
} from "./chunk-61j18dwk.js";
|
|
8
|
-
|
|
9
|
-
// src/core/server-features.ts
|
|
10
|
-
var serverFeatures = (config) => {
|
|
11
|
-
const features = [];
|
|
12
|
-
if (config.ai.ask?.enabled && !config.ai.ask.endpoint) {
|
|
13
|
-
features.push("Ask AI");
|
|
14
|
-
}
|
|
15
|
-
if (config.ai.mcp.enabled) {
|
|
16
|
-
features.push("MCP server");
|
|
17
|
-
}
|
|
18
|
-
if (needsPlaygroundProxy(config)) {
|
|
19
|
-
features.push("API playground proxy");
|
|
20
|
-
}
|
|
21
|
-
if (searchProviderMeta(config.search.provider).requiresServer) {
|
|
22
|
-
features.push(`Search (${config.search.provider})`);
|
|
23
|
-
}
|
|
24
|
-
return features;
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
export { serverFeatures };
|
|
28
|
-
|
|
29
|
-
//# debugId=0DFA9D31AEDBECCC64756E2164756E21
|
|
30
|
-
//# sourceMappingURL=chunk-jbj4qhfw.js.map
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/core/server-features.ts"],
|
|
4
|
-
"sourcesContent": [
|
|
5
|
-
"import { needsPlaygroundProxy } from \"../openapi/references.ts\";\nimport { searchProviderMeta } from \"../search/providers.ts\";\nimport type { ResolvedConfig } from \"./schema.ts\";\n\n/**\n * List the enabled features that require Astro server output. Static builds\n * fail clearly when any of these are enabled.\n */\nexport const serverFeatures = (config: ResolvedConfig): string[] => {\n const features: string[] = [];\n if (config.ai.ask?.enabled && !config.ai.ask.endpoint) {\n features.push(\"Ask AI\");\n }\n // The hosted MCP server is a live JSON-RPC endpoint, so it needs a runtime.\n if (config.ai.mcp.enabled) {\n features.push(\"MCP server\");\n }\n // The built-in playground proxy (`playground.proxy: true` on the OpenAPI or\n // GraphQL block) is a live fetch endpoint at `/_api-proxy`; an external\n // proxy URL (string) or a proxy-less playground stays fully static.\n if (needsPlaygroundProxy(config)) {\n features.push(\"API playground proxy\");\n }\n // Mixedbread (and any future provider) that proxies queries through a secret\n // server endpoint can't run on a static build.\n if (searchProviderMeta(config.search.provider).requiresServer) {\n features.push(`Search (${config.search.provider})`);\n }\n return features;\n};\n"
|
|
6
|
-
],
|
|
7
|
-
"mappings": ";;;;;;;;;AAQO,IAAM,iBAAiB,CAAC,WAAqC;AAAA,EAClE,MAAM,WAAqB,CAAC;AAAA,EAC5B,IAAI,OAAO,GAAG,KAAK,WAAW,CAAC,OAAO,GAAG,IAAI,UAAU;AAAA,IACrD,SAAS,KAAK,QAAQ;AAAA,EACxB;AAAA,EAEA,IAAI,OAAO,GAAG,IAAI,SAAS;AAAA,IACzB,SAAS,KAAK,YAAY;AAAA,EAC5B;AAAA,EAIA,IAAI,qBAAqB,MAAM,GAAG;AAAA,IAChC,SAAS,KAAK,sBAAsB;AAAA,EACtC;AAAA,EAGA,IAAI,mBAAmB,OAAO,OAAO,QAAQ,EAAE,gBAAgB;AAAA,IAC7D,SAAS,KAAK,WAAW,OAAO,OAAO,WAAW;AAAA,EACpD;AAAA,EACA,OAAO;AAAA;",
|
|
8
|
-
"debugId": "0DFA9D31AEDBECCC64756E2164756E21",
|
|
9
|
-
"names": []
|
|
10
|
-
}
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import"./chunk-wjt80jps.js";
|
|
3
|
-
import"./chunk-hdm2dkd2.js";
|
|
4
|
-
import {
|
|
5
|
-
commandMeta,
|
|
6
|
-
logger
|
|
7
|
-
} from "./index.js";
|
|
8
|
-
import"./chunk-61j18dwk.js";
|
|
9
|
-
import"./chunk-450a7rcr.js";
|
|
10
|
-
import"./chunk-88by27n5.js";
|
|
11
|
-
import"./chunk-tqa1s0k8.js";
|
|
12
|
-
import"./chunk-5n7t497w.js";
|
|
13
|
-
import"./chunk-jq5n4avg.js";
|
|
14
|
-
import"./chunk-ejjx8znq.js";
|
|
15
|
-
import"./chunk-688e0dde.js";
|
|
16
|
-
import"./chunk-vrfp10qk.js";
|
|
17
|
-
import {
|
|
18
|
-
eject,
|
|
19
|
-
updatePackageScripts,
|
|
20
|
-
commandsFor,
|
|
21
|
-
detectProjectPackageManager
|
|
22
|
-
} from "./chunk-196vjxp9.js";
|
|
23
|
-
import {
|
|
24
|
-
refuseIfDevRunning
|
|
25
|
-
} from "./chunk-exeeb35e.js";
|
|
26
|
-
|
|
27
|
-
// src/cli/commands/eject.ts
|
|
28
|
-
import { defineCommand } from "citty";
|
|
29
|
-
import { relative } from "pathe";
|
|
30
|
-
var ejectCommand = defineCommand({
|
|
31
|
-
args: {
|
|
32
|
-
yes: { description: "Skip the confirmation prompt.", type: "boolean" }
|
|
33
|
-
},
|
|
34
|
-
meta: commandMeta.eject,
|
|
35
|
-
async run({ args }) {
|
|
36
|
-
const root = process.cwd();
|
|
37
|
-
refuseIfDevRunning(root, "ejecting");
|
|
38
|
-
if (!args.yes) {
|
|
39
|
-
logger.warn("Eject is one-way: it writes astro.config.mjs, src/, and (if absent) tsconfig.json, rewrites your package.json scripts, and removes .blume. An existing tsconfig.json is left untouched.");
|
|
40
|
-
logger.info("Re-run with --yes to proceed.");
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
|
-
const { files, warnings } = await eject(root);
|
|
44
|
-
await updatePackageScripts(root);
|
|
45
|
-
for (const warning of warnings) {
|
|
46
|
-
logger.warn(warning);
|
|
47
|
-
}
|
|
48
|
-
logger.success(`Ejected ${files.length} file(s):`);
|
|
49
|
-
for (const file of files) {
|
|
50
|
-
process.stdout.write(` ${relative(root, file)}
|
|
51
|
-
`);
|
|
52
|
-
}
|
|
53
|
-
const pm = await detectProjectPackageManager(root);
|
|
54
|
-
const { build, dev } = commandsFor(pm);
|
|
55
|
-
logger.box(`Your project is now a standalone Astro app.
|
|
56
|
-
|
|
57
|
-
${dev}
|
|
58
|
-
${build}
|
|
59
|
-
|
|
60
|
-
The blume package remains importable.`);
|
|
61
|
-
}
|
|
62
|
-
});
|
|
63
|
-
export {
|
|
64
|
-
ejectCommand
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
//# debugId=2DD1F00676E6F84564756E2164756E21
|
|
68
|
-
//# sourceMappingURL=chunk-mqb2ka8m.js.map
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/cli/commands/eject.ts"],
|
|
4
|
-
"sourcesContent": [
|
|
5
|
-
"import { defineCommand } from \"citty\";\nimport { relative } from \"pathe\";\n\nimport { eject } from \"../../registry/eject.ts\";\nimport { commandMeta } from \"../command-meta.ts\";\nimport { refuseIfDevRunning } from \"../dev-lock.ts\";\nimport { updatePackageScripts } from \"../eject-scripts.ts\";\nimport { commandsFor, detectProjectPackageManager } from \"../init/scaffold.ts\";\nimport { logger } from \"../log.ts\";\n\nexport const ejectCommand = defineCommand({\n args: {\n yes: { description: \"Skip the confirmation prompt.\", type: \"boolean\" },\n },\n meta: commandMeta.eject,\n async run({ args }) {\n const root = process.cwd();\n refuseIfDevRunning(root, \"ejecting\");\n\n if (!args.yes) {\n logger.warn(\n \"Eject is one-way: it writes astro.config.mjs, src/, and (if absent) tsconfig.json, rewrites your package.json scripts, and removes .blume. An existing tsconfig.json is left untouched.\"\n );\n logger.info(\"Re-run with --yes to proceed.\");\n return;\n }\n\n const { files, warnings } = await eject(root);\n await updatePackageScripts(root);\n\n // The same surface as the generated-runtime path (prepare.ts): one warn\n // per generation warning, e.g. a Scalar reference spec that wasn't found.\n for (const warning of warnings) {\n logger.warn(warning);\n }\n\n logger.success(`Ejected ${files.length} file(s):`);\n for (const file of files) {\n process.stdout.write(` ${relative(root, file)}\\n`);\n }\n // Print run commands matching the project's package manager (lockfile\n // detection, since eject runs inside an existing project).\n const pm = await detectProjectPackageManager(root);\n const { build, dev } = commandsFor(pm);\n logger.box(\n `Your project is now a standalone Astro app.\\n\\n ${dev}\\n ${build}\\n\\nThe blume package remains importable.`\n );\n },\n});\n"
|
|
6
|
-
],
|
|
7
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AACA;AASO,IAAM,eAAe,cAAc;AAAA,EACxC,MAAM;AAAA,IACJ,KAAK,EAAE,aAAa,iCAAiC,MAAM,UAAU;AAAA,EACvE;AAAA,EACA,MAAM,YAAY;AAAA,OACZ,IAAG,GAAG,QAAQ;AAAA,IAClB,MAAM,OAAO,QAAQ,IAAI;AAAA,IACzB,mBAAmB,MAAM,UAAU;AAAA,IAEnC,IAAI,CAAC,KAAK,KAAK;AAAA,MACb,OAAO,KACL,yLACF;AAAA,MACA,OAAO,KAAK,+BAA+B;AAAA,MAC3C;AAAA,IACF;AAAA,IAEA,QAAQ,OAAO,aAAa,MAAM,MAAM,IAAI;AAAA,IAC5C,MAAM,qBAAqB,IAAI;AAAA,IAI/B,WAAW,WAAW,UAAU;AAAA,MAC9B,OAAO,KAAK,OAAO;AAAA,IACrB;AAAA,IAEA,OAAO,QAAQ,WAAW,MAAM,iBAAiB;AAAA,IACjD,WAAW,QAAQ,OAAO;AAAA,MACxB,QAAQ,OAAO,MAAM,KAAK,SAAS,MAAM,IAAI;AAAA,CAAK;AAAA,IACpD;AAAA,IAGA,MAAM,KAAK,MAAM,4BAA4B,IAAI;AAAA,IACjD,QAAQ,OAAO,QAAQ,YAAY,EAAE;AAAA,IACrC,OAAO,IACL;AAAA;AAAA,IAAoD;AAAA,IAAU;AAAA;AAAA,sCAChE;AAAA;AAEJ,CAAC;",
|
|
8
|
-
"debugId": "2DD1F00676E6F84564756E2164756E21",
|
|
9
|
-
"names": []
|
|
10
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/cli/commands/init.ts", "../src/cli/init/questions.ts"],
|
|
4
|
-
"sourcesContent": [
|
|
5
|
-
"import * as clack from \"@clack/prompts\";\nimport { defineCommand } from \"citty\";\nimport { resolve } from \"pathe\";\n\nimport { ensureGitignore } from \"../../core/gitignore.ts\";\nimport { eject } from \"../../registry/eject.ts\";\nimport { commandMeta } from \"../command-meta.ts\";\nimport { updatePackageScripts } from \"../eject-scripts.ts\";\nimport { collectAnswers } from \"../init/questions.ts\";\nimport {\n applyPlan,\n buildPlan,\n commandsFor,\n detectPackageManager,\n nextSteps,\n PACKAGE_MANAGERS,\n TEMPLATES,\n validateContentDir,\n} from \"../init/scaffold.ts\";\nimport type { InitAnswers } from \"../init/scaffold.ts\";\nimport { logger } from \"../log.ts\";\n\n/**\n * Eject the freshly scaffolded project, or print the install-then-eject path.\n * Eject jiti-loads the scaffolded blume.config.ts, whose `import { defineConfig }\n * from \"blume\"` only resolves once dependencies are installed (or blume is\n * hoisted from an ancestor node_modules, as in a monorepo) — so on a fresh\n * scaffold the fallback below is the common path.\n */\nconst ejectScaffold = async (\n root: string,\n answers: InitAnswers\n): Promise<void> => {\n const commands = commandsFor(answers.packageManager);\n const cd = answers.directory === \".\" ? [] : [`cd ${answers.directory}`];\n try {\n await eject(root);\n // The scaffolded scripts point at the Blume CLI; the ejected app runs\n // Astro directly (mirroring the standalone `blume eject` command).\n await updatePackageScripts(root);\n logger.success(\"Ejected to a standalone Astro project.\");\n const steps = [...cd, commands.install, commands.dev];\n logger.box(`Next steps:\\n\\n ${steps.join(\"\\n \")}\\n`);\n } catch (error) {\n // SAFETY: eject and the script rewrite throw Error instances; only the\n // message is surfaced in the fallback hint.\n logger.warn(\n `Scaffolded, but eject needs the project's dependencies installed to load blume.config.ts: ${(error as Error).message}`\n );\n const steps = [\n ...cd,\n commands.install,\n `${commands.exec} blume eject --yes`,\n ];\n logger.box(`Next steps:\\n\\n ${steps.join(\"\\n \")}\\n`);\n }\n};\n\nexport const initCommand = defineCommand({\n args: {\n \"content-dir\": {\n description: \"Content directory.\",\n type: \"string\",\n },\n dir: {\n description: \"Directory to scaffold into (default: current directory).\",\n required: false,\n type: \"positional\",\n },\n eject: {\n description: \"Eject to a standalone Astro project after scaffolding.\",\n type: \"boolean\",\n },\n \"package-manager\": {\n description:\n \"Package manager for the next-steps hint (npm|pnpm|yarn|bun).\",\n type: \"string\",\n },\n template: {\n description: \"Starter template: docs | api | sdk | changelog.\",\n type: \"string\",\n },\n yes: {\n description: \"Skip prompts and scaffold with defaults.\",\n type: \"boolean\",\n },\n },\n meta: commandMeta.init,\n async run({ args }) {\n const cwd = process.cwd();\n\n const template = TEMPLATES.find((candidate) => candidate === args.template);\n if (args.template !== undefined && template === undefined) {\n logger.error(\n `Unknown template \"${args.template}\" (use ${TEMPLATES.join(\" | \")}).`\n );\n process.exit(1);\n }\n const pm = PACKAGE_MANAGERS.find(\n (candidate) => candidate === args[\"package-manager\"]\n );\n if (args[\"package-manager\"] !== undefined && pm === undefined) {\n logger.error(\n `Unknown package manager \"${args[\"package-manager\"]}\" (use ${PACKAGE_MANAGERS.join(\" | \")}).`\n );\n process.exit(1);\n }\n\n const interactive =\n !args.yes &&\n process.stdin.isTTY === true &&\n clack.isTTY(process.stdout) &&\n !clack.isCI();\n\n let answers: InitAnswers;\n if (interactive) {\n clack.intro(\"blume init\");\n const collected = await collectAnswers(\n clack,\n {\n contentDir: args[\"content-dir\"],\n directory: args.dir,\n packageManager: pm,\n template,\n },\n { cwd, userAgent: process.env.npm_config_user_agent }\n );\n if (collected === null) {\n clack.cancel(\"Cancelled — nothing was written.\");\n process.exit(0);\n }\n answers = collected;\n } else {\n answers = {\n contentDir: args[\"content-dir\"] ?? \"docs\",\n directory: args.dir ?? \".\",\n packageManager:\n pm ?? detectPackageManager(process.env.npm_config_user_agent),\n sources: [\"filesystem\"],\n template: template ?? \"docs\",\n title: \"My Docs\",\n };\n }\n\n const root = resolve(cwd, answers.directory);\n // Interactive runs validate this inline, but an explicit --content-dir\n // flag skips that prompt, so guard here in both modes.\n if (validateContentDir(root, answers.contentDir) !== undefined) {\n logger.error(\n `Invalid --content-dir \"${answers.contentDir}\" (must be a path inside the project).`\n );\n process.exit(1);\n }\n\n const sink = interactive ? clack.log : logger;\n const { createdPackage } = await applyPlan(buildPlan(root, answers), sink);\n\n // Keep installed dependencies, Blume's generated runtime (`.blume/`), and\n // build output (`dist/`) out of version control. Idempotent: creates\n // `.gitignore` when absent and skips entries already present\n // (trailing-slash agnostic).\n const ignored = await ensureGitignore(root, [\n \"node_modules/\",\n \".blume/\",\n \"dist/\",\n ]);\n if (ignored.length > 0) {\n sink.success(`Added ${ignored.join(\", \")} to .gitignore`);\n }\n\n if (args.eject) {\n await ejectScaffold(root, answers);\n return;\n }\n\n const steps = nextSteps(answers, createdPackage);\n if (interactive) {\n clack.note(steps.trimEnd());\n clack.outro(\"You're all set.\");\n } else {\n logger.box(steps);\n }\n },\n});\n",
|
|
6
|
-
"import { basename, resolve } from \"pathe\";\n\nimport {\n detectPackageManager,\n titleize,\n validateContentDir,\n} from \"./scaffold.ts\";\nimport type {\n InitAnswers,\n PackageManager,\n SourceKind,\n Template,\n} from \"./scaffold.ts\";\n\n/** One prompt option: value plus display label and optional hint. */\ninterface PromptOption<Value> {\n hint?: string;\n label: string;\n value: Value;\n}\n\n/**\n * The prompt surface `collectAnswers` needs — structurally satisfied by the\n * `@clack/prompts` module itself, and by plain fakes in tests. Every prompt\n * resolves to a cancel symbol when the user aborts.\n */\nexport interface Prompter {\n multiselect: (opts: {\n initialValues?: SourceKind[];\n message: string;\n options: PromptOption<SourceKind>[];\n required?: boolean;\n }) => Promise<SourceKind[] | symbol>;\n select: (opts: {\n message: string;\n options: PromptOption<Template>[];\n }) => Promise<Template | symbol>;\n text: (opts: {\n defaultValue?: string;\n initialValue?: string;\n message: string;\n placeholder?: string;\n validate?: (value: string | undefined) => string | undefined;\n }) => Promise<string | symbol>;\n}\n\n/** Flag values the user passed explicitly; each one skips its question. */\nexport interface InitFlags {\n contentDir?: string;\n directory?: string;\n packageManager?: PackageManager;\n template?: Template;\n}\n\nconst cancelled = (value: string | string[] | symbol): value is symbol =>\n typeof value === \"symbol\";\n\n/**\n * Run the interactive init flow, returning the collected answers or `null`\n * when the user cancels. All questions run before anything is written, so a\n * cancel never leaves a partial scaffold behind.\n */\nexport const collectAnswers = async (\n prompter: Prompter,\n flags: InitFlags,\n defaults: { cwd: string; userAgent?: string }\n): Promise<InitAnswers | null> => {\n const directory =\n flags.directory ??\n (await prompter.text({\n defaultValue: \".\",\n message: \"Where should we create your project?\",\n placeholder: \"./my-docs\",\n }));\n if (cancelled(directory)) {\n return null;\n }\n\n const root = resolve(defaults.cwd, directory);\n const title = await prompter.text({\n initialValue: titleize(basename(root)),\n message: \"What's your docs site called?\",\n validate: (value) =>\n value?.trim() ? undefined : \"Give your docs site a name.\",\n });\n if (cancelled(title)) {\n return null;\n }\n\n const template =\n flags.template ??\n (await prompter.select({\n message: \"Which template?\",\n options: [\n { hint: \"Markdown docs site\", label: \"docs\", value: \"docs\" },\n { hint: \"OpenAPI reference at /api\", label: \"api\", value: \"api\" },\n { hint: \"SDK docs with an install page\", label: \"sdk\", value: \"sdk\" },\n {\n hint: \"Docs plus a changelog tab\",\n label: \"changelog\",\n value: \"changelog\",\n },\n ],\n }));\n if (cancelled(template)) {\n return null;\n }\n\n const picked = await prompter.multiselect({\n initialValues: [\"filesystem\"],\n message: \"Where does your content live?\",\n options: [\n { hint: \"Local .mdx files\", label: \"filesystem\", value: \"filesystem\" },\n { hint: \"An Obsidian vault\", label: \"obsidian\", value: \"obsidian\" },\n {\n hint: \"Changelog from GitHub Releases\",\n label: \"github-releases\",\n value: \"github-releases\",\n },\n { hint: \"A Notion database\", label: \"notion\", value: \"notion\" },\n { hint: \"A Sanity dataset\", label: \"sanity\", value: \"sanity\" },\n {\n hint: \"MDX fetched from a GitHub repo\",\n label: \"mdx-remote\",\n value: \"mdx-remote\",\n },\n ],\n required: false,\n });\n if (cancelled(picked)) {\n return null;\n }\n // No selection desugars to the implicit local source, same as the schema.\n const sources: SourceKind[] = picked.length === 0 ? [\"filesystem\"] : picked;\n\n let contentDir = flags.contentDir ?? \"docs\";\n if (flags.contentDir === undefined && sources.includes(\"filesystem\")) {\n const answer = await prompter.text({\n defaultValue: \"docs\",\n message: \"Content directory?\",\n placeholder: \"docs\",\n validate: (value) => validateContentDir(root, value || \"docs\"),\n });\n if (cancelled(answer)) {\n return null;\n }\n contentDir = answer;\n }\n\n return {\n contentDir,\n directory,\n packageManager:\n flags.packageManager ?? detectPackageManager(defaults.userAgent),\n sources,\n template,\n title,\n };\n};\n"
|
|
7
|
-
],
|
|
8
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AACA;AACA,oBAAS;;;ACFT;AAsDA,IAAM,YAAY,CAAC,UACjB,OAAO,UAAU;AAOZ,IAAM,iBAAiB,OAC5B,UACA,OACA,aACgC;AAAA,EAChC,MAAM,YACJ,MAAM,aACL,MAAM,SAAS,KAAK;AAAA,IACnB,cAAc;AAAA,IACd,SAAS;AAAA,IACT,aAAa;AAAA,EACf,CAAC;AAAA,EACH,IAAI,UAAU,SAAS,GAAG;AAAA,IACxB,OAAO;AAAA,EACT;AAAA,EAEA,MAAM,OAAO,QAAQ,SAAS,KAAK,SAAS;AAAA,EAC5C,MAAM,QAAQ,MAAM,SAAS,KAAK;AAAA,IAChC,cAAc,SAAS,SAAS,IAAI,CAAC;AAAA,IACrC,SAAS;AAAA,IACT,UAAU,CAAC,UACT,OAAO,KAAK,IAAI,YAAY;AAAA,EAChC,CAAC;AAAA,EACD,IAAI,UAAU,KAAK,GAAG;AAAA,IACpB,OAAO;AAAA,EACT;AAAA,EAEA,MAAM,WACJ,MAAM,YACL,MAAM,SAAS,OAAO;AAAA,IACrB,SAAS;AAAA,IACT,SAAS;AAAA,MACP,EAAE,MAAM,sBAAsB,OAAO,QAAQ,OAAO,OAAO;AAAA,MAC3D,EAAE,MAAM,6BAA6B,OAAO,OAAO,OAAO,MAAM;AAAA,MAChE,EAAE,MAAM,iCAAiC,OAAO,OAAO,OAAO,MAAM;AAAA,MACpE;AAAA,QACE,MAAM;AAAA,QACN,OAAO;AAAA,QACP,OAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF,CAAC;AAAA,EACH,IAAI,UAAU,QAAQ,GAAG;AAAA,IACvB,OAAO;AAAA,EACT;AAAA,EAEA,MAAM,SAAS,MAAM,SAAS,YAAY;AAAA,IACxC,eAAe,CAAC,YAAY;AAAA,IAC5B,SAAS;AAAA,IACT,SAAS;AAAA,MACP,EAAE,MAAM,oBAAoB,OAAO,cAAc,OAAO,aAAa;AAAA,MACrE,EAAE,MAAM,qBAAqB,OAAO,YAAY,OAAO,WAAW;AAAA,MAClE;AAAA,QACE,MAAM;AAAA,QACN,OAAO;AAAA,QACP,OAAO;AAAA,MACT;AAAA,MACA,EAAE,MAAM,qBAAqB,OAAO,UAAU,OAAO,SAAS;AAAA,MAC9D,EAAE,MAAM,oBAAoB,OAAO,UAAU,OAAO,SAAS;AAAA,MAC7D;AAAA,QACE,MAAM;AAAA,QACN,OAAO;AAAA,QACP,OAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,UAAU;AAAA,EACZ,CAAC;AAAA,EACD,IAAI,UAAU,MAAM,GAAG;AAAA,IACrB,OAAO;AAAA,EACT;AAAA,EAEA,MAAM,UAAwB,OAAO,WAAW,IAAI,CAAC,YAAY,IAAI;AAAA,EAErE,IAAI,aAAa,MAAM,cAAc;AAAA,EACrC,IAAI,MAAM,eAAe,aAAa,QAAQ,SAAS,YAAY,GAAG;AAAA,IACpE,MAAM,SAAS,MAAM,SAAS,KAAK;AAAA,MACjC,cAAc;AAAA,MACd,SAAS;AAAA,MACT,aAAa;AAAA,MACb,UAAU,CAAC,UAAU,mBAAmB,MAAM,SAAS,MAAM;AAAA,IAC/D,CAAC;AAAA,IACD,IAAI,UAAU,MAAM,GAAG;AAAA,MACrB,OAAO;AAAA,IACT;AAAA,IACA,aAAa;AAAA,EACf;AAAA,EAEA,OAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,gBACE,MAAM,kBAAkB,qBAAqB,SAAS,SAAS;AAAA,IACjE;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA;;;ADhIF,IAAM,gBAAgB,OACpB,MACA,YACkB;AAAA,EAClB,MAAM,WAAW,YAAY,QAAQ,cAAc;AAAA,EACnD,MAAM,KAAK,QAAQ,cAAc,MAAM,CAAC,IAAI,CAAC,MAAM,QAAQ,WAAW;AAAA,EACtE,IAAI;AAAA,IACF,MAAM,MAAM,IAAI;AAAA,IAGhB,MAAM,qBAAqB,IAAI;AAAA,IAC/B,OAAO,QAAQ,wCAAwC;AAAA,IACvD,MAAM,QAAQ,CAAC,GAAG,IAAI,SAAS,SAAS,SAAS,GAAG;AAAA,IACpD,OAAO,IAAI;AAAA;AAAA,IAAoB,MAAM,KAAK;AAAA,GAAM;AAAA,CAAK;AAAA,IACrD,OAAO,OAAO;AAAA,IAGd,OAAO,KACL,6FAA8F,MAAgB,SAChH;AAAA,IACA,MAAM,QAAQ;AAAA,MACZ,GAAG;AAAA,MACH,SAAS;AAAA,MACT,GAAG,SAAS;AAAA,IACd;AAAA,IACA,OAAO,IAAI;AAAA;AAAA,IAAoB,MAAM,KAAK;AAAA,GAAM;AAAA,CAAK;AAAA;AAAA;AAIlD,IAAM,cAAc,cAAc;AAAA,EACvC,MAAM;AAAA,IACJ,eAAe;AAAA,MACb,aAAa;AAAA,MACb,MAAM;AAAA,IACR;AAAA,IACA,KAAK;AAAA,MACH,aAAa;AAAA,MACb,UAAU;AAAA,MACV,MAAM;AAAA,IACR;AAAA,IACA,OAAO;AAAA,MACL,aAAa;AAAA,MACb,MAAM;AAAA,IACR;AAAA,IACA,mBAAmB;AAAA,MACjB,aACE;AAAA,MACF,MAAM;AAAA,IACR;AAAA,IACA,UAAU;AAAA,MACR,aAAa;AAAA,MACb,MAAM;AAAA,IACR;AAAA,IACA,KAAK;AAAA,MACH,aAAa;AAAA,MACb,MAAM;AAAA,IACR;AAAA,EACF;AAAA,EACA,MAAM,YAAY;AAAA,OACZ,IAAG,GAAG,QAAQ;AAAA,IAClB,MAAM,MAAM,QAAQ,IAAI;AAAA,IAExB,MAAM,WAAW,UAAU,KAAK,CAAC,cAAc,cAAc,KAAK,QAAQ;AAAA,IAC1E,IAAI,KAAK,aAAa,aAAa,aAAa,WAAW;AAAA,MACzD,OAAO,MACL,qBAAqB,KAAK,kBAAkB,UAAU,KAAK,KAAK,KAClE;AAAA,MACA,QAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,IACA,MAAM,KAAK,iBAAiB,KAC1B,CAAC,cAAc,cAAc,KAAK,kBACpC;AAAA,IACA,IAAI,KAAK,uBAAuB,aAAa,OAAO,WAAW;AAAA,MAC7D,OAAO,MACL,4BAA4B,KAAK,4BAA4B,iBAAiB,KAAK,KAAK,KAC1F;AAAA,MACA,QAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,IAEA,MAAM,cACJ,CAAC,KAAK,OACN,QAAQ,MAAM,UAAU,QAClB,YAAM,QAAQ,MAAM,KAC1B,CAAO,WAAK;AAAA,IAEd,IAAI;AAAA,IACJ,IAAI,aAAa;AAAA,MACT,YAAM,YAAY;AAAA,MACxB,MAAM,YAAY,MAAM,eACtB,OACA;AAAA,QACE,YAAY,KAAK;AAAA,QACjB,WAAW,KAAK;AAAA,QAChB,gBAAgB;AAAA,QAChB;AAAA,MACF,GACA,EAAE,KAAK,WAAW,QAAQ,IAAI,sBAAsB,CACtD;AAAA,MACA,IAAI,cAAc,MAAM;AAAA,QAChB,aAAO,kCAAkC;AAAA,QAC/C,QAAQ,KAAK,CAAC;AAAA,MAChB;AAAA,MACA,UAAU;AAAA,IACZ,EAAO;AAAA,MACL,UAAU;AAAA,QACR,YAAY,KAAK,kBAAkB;AAAA,QACnC,WAAW,KAAK,OAAO;AAAA,QACvB,gBACE,MAAM,qBAAqB,QAAQ,IAAI,qBAAqB;AAAA,QAC9D,SAAS,CAAC,YAAY;AAAA,QACtB,UAAU,YAAY;AAAA,QACtB,OAAO;AAAA,MACT;AAAA;AAAA,IAGF,MAAM,OAAO,SAAQ,KAAK,QAAQ,SAAS;AAAA,IAG3C,IAAI,mBAAmB,MAAM,QAAQ,UAAU,MAAM,WAAW;AAAA,MAC9D,OAAO,MACL,0BAA0B,QAAQ,kDACpC;AAAA,MACA,QAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,IAEA,MAAM,OAAO,cAAoB,YAAM;AAAA,IACvC,QAAQ,mBAAmB,MAAM,UAAU,UAAU,MAAM,OAAO,GAAG,IAAI;AAAA,IAMzE,MAAM,UAAU,MAAM,gBAAgB,MAAM;AAAA,MAC1C;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,IACD,IAAI,QAAQ,SAAS,GAAG;AAAA,MACtB,KAAK,QAAQ,SAAS,QAAQ,KAAK,IAAI,iBAAiB;AAAA,IAC1D;AAAA,IAEA,IAAI,KAAK,OAAO;AAAA,MACd,MAAM,cAAc,MAAM,OAAO;AAAA,MACjC;AAAA,IACF;AAAA,IAEA,MAAM,QAAQ,UAAU,SAAS,cAAc;AAAA,IAC/C,IAAI,aAAa;AAAA,MACT,WAAK,MAAM,QAAQ,CAAC;AAAA,MACpB,YAAM,iBAAiB;AAAA,IAC/B,EAAO;AAAA,MACL,OAAO,IAAI,KAAK;AAAA;AAAA;AAGtB,CAAC;",
|
|
9
|
-
"debugId": "844E1BF775C8782664756E2164756E21",
|
|
10
|
-
"names": []
|
|
11
|
-
}
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
// src/search/providers.ts
|
|
4
|
-
var SEARCH_PROVIDERS = {
|
|
5
|
-
algolia: {
|
|
6
|
-
kind: "hosted",
|
|
7
|
-
requiresServer: false,
|
|
8
|
-
runtimeDeps: ["algoliasearch"],
|
|
9
|
-
syncs: true
|
|
10
|
-
},
|
|
11
|
-
flexsearch: {
|
|
12
|
-
kind: "static",
|
|
13
|
-
requiresServer: false,
|
|
14
|
-
runtimeDeps: ["flexsearch"],
|
|
15
|
-
syncs: false
|
|
16
|
-
},
|
|
17
|
-
mixedbread: {
|
|
18
|
-
kind: "server",
|
|
19
|
-
requiresServer: true,
|
|
20
|
-
runtimeDeps: ["@mixedbread/sdk"],
|
|
21
|
-
syncs: false
|
|
22
|
-
},
|
|
23
|
-
none: {
|
|
24
|
-
kind: "none",
|
|
25
|
-
requiresServer: false,
|
|
26
|
-
runtimeDeps: [],
|
|
27
|
-
syncs: false
|
|
28
|
-
},
|
|
29
|
-
orama: {
|
|
30
|
-
kind: "static",
|
|
31
|
-
requiresServer: false,
|
|
32
|
-
runtimeDeps: ["@orama/orama"],
|
|
33
|
-
syncs: false
|
|
34
|
-
},
|
|
35
|
-
"orama-cloud": {
|
|
36
|
-
kind: "hosted",
|
|
37
|
-
requiresServer: false,
|
|
38
|
-
runtimeDeps: ["@oramacloud/client"],
|
|
39
|
-
syncs: true
|
|
40
|
-
},
|
|
41
|
-
pagefind: {
|
|
42
|
-
kind: "pagefind",
|
|
43
|
-
requiresServer: false,
|
|
44
|
-
runtimeDeps: [],
|
|
45
|
-
syncs: false
|
|
46
|
-
},
|
|
47
|
-
typesense: {
|
|
48
|
-
kind: "hosted",
|
|
49
|
-
requiresServer: false,
|
|
50
|
-
runtimeDeps: ["typesense"],
|
|
51
|
-
syncs: true
|
|
52
|
-
}
|
|
53
|
-
};
|
|
54
|
-
var searchProviderMeta = (provider) => SEARCH_PROVIDERS[provider];
|
|
55
|
-
var servesStaticIndex = (provider) => SEARCH_PROVIDERS[provider].kind === "static";
|
|
56
|
-
|
|
57
|
-
export { searchProviderMeta, servesStaticIndex };
|
|
58
|
-
|
|
59
|
-
//# debugId=B1958AC304E6284364756E2164756E21
|
|
60
|
-
//# sourceMappingURL=chunk-q4rae3bg.js.map
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/search/providers.ts"],
|
|
4
|
-
"sourcesContent": [
|
|
5
|
-
"import type { SearchProvider } from \"../core/schema.ts\";\n\n/**\n * How a search provider integrates with the generated runtime.\n *\n * - `static` providers ship a client-side index (`blume-search.json`) that the\n * browser loads and queries — `orama`, `flexsearch`.\n * - `pagefind` builds its own index from the rendered HTML after the Astro build.\n * - `hosted` providers are queried directly from the browser against an external\n * service, with a build-time sync uploading the index — `algolia`,\n * `orama-cloud`, `typesense`.\n * - `server` providers proxy queries through a generated `/api/search` endpoint\n * that holds a secret key, so they require server output — `mixedbread`.\n */\nexport type SearchProviderKind =\n | \"static\"\n | \"pagefind\"\n | \"hosted\"\n | \"server\"\n | \"none\";\n\nexport interface SearchProviderMeta {\n kind: SearchProviderKind;\n /** Extra packages the generated `.blume/package.json` must declare. */\n runtimeDeps: string[];\n /** Whether the provider needs `deployment.output: \"server\"`. */\n requiresServer: boolean;\n /** Whether a build-time sync uploads the index to an external service. */\n syncs: boolean;\n}\n\nexport const SEARCH_PROVIDERS = {\n algolia: {\n kind: \"hosted\",\n requiresServer: false,\n runtimeDeps: [\"algoliasearch\"],\n syncs: true,\n },\n flexsearch: {\n kind: \"static\",\n requiresServer: false,\n runtimeDeps: [\"flexsearch\"],\n syncs: false,\n },\n mixedbread: {\n // Content is synced to the store out-of-band via the `mxbai` CLI, not by an\n // in-process build step.\n kind: \"server\",\n requiresServer: true,\n runtimeDeps: [\"@mixedbread/sdk\"],\n syncs: false,\n },\n none: {\n kind: \"none\",\n requiresServer: false,\n runtimeDeps: [],\n syncs: false,\n },\n orama: {\n kind: \"static\",\n requiresServer: false,\n runtimeDeps: [\"@orama/orama\"],\n syncs: false,\n },\n \"orama-cloud\": {\n kind: \"hosted\",\n requiresServer: false,\n runtimeDeps: [\"@oramacloud/client\"],\n syncs: true,\n },\n pagefind: {\n kind: \"pagefind\",\n requiresServer: false,\n runtimeDeps: [],\n syncs: false,\n },\n typesense: {\n kind: \"hosted\",\n requiresServer: false,\n runtimeDeps: [\"typesense\"],\n syncs: true,\n },\n} satisfies Record<SearchProvider, SearchProviderMeta>;\n\nexport const searchProviderMeta = (\n provider: SearchProvider\n): SearchProviderMeta => SEARCH_PROVIDERS[provider];\n\n/** Whether a provider ships a client-loaded `blume-search.json` index. */\nexport const servesStaticIndex = (provider: SearchProvider): boolean =>\n SEARCH_PROVIDERS[provider].kind === \"static\";\n"
|
|
6
|
-
],
|
|
7
|
-
"mappings": ";;;AA+BO,IAAM,mBAAmB;AAAA,EAC9B,SAAS;AAAA,IACP,MAAM;AAAA,IACN,gBAAgB;AAAA,IAChB,aAAa,CAAC,eAAe;AAAA,IAC7B,OAAO;AAAA,EACT;AAAA,EACA,YAAY;AAAA,IACV,MAAM;AAAA,IACN,gBAAgB;AAAA,IAChB,aAAa,CAAC,YAAY;AAAA,IAC1B,OAAO;AAAA,EACT;AAAA,EACA,YAAY;AAAA,IAGV,MAAM;AAAA,IACN,gBAAgB;AAAA,IAChB,aAAa,CAAC,iBAAiB;AAAA,IAC/B,OAAO;AAAA,EACT;AAAA,EACA,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,gBAAgB;AAAA,IAChB,aAAa,CAAC;AAAA,IACd,OAAO;AAAA,EACT;AAAA,EACA,OAAO;AAAA,IACL,MAAM;AAAA,IACN,gBAAgB;AAAA,IAChB,aAAa,CAAC,cAAc;AAAA,IAC5B,OAAO;AAAA,EACT;AAAA,EACA,eAAe;AAAA,IACb,MAAM;AAAA,IACN,gBAAgB;AAAA,IAChB,aAAa,CAAC,oBAAoB;AAAA,IAClC,OAAO;AAAA,EACT;AAAA,EACA,UAAU;AAAA,IACR,MAAM;AAAA,IACN,gBAAgB;AAAA,IAChB,aAAa,CAAC;AAAA,IACd,OAAO;AAAA,EACT;AAAA,EACA,WAAW;AAAA,IACT,MAAM;AAAA,IACN,gBAAgB;AAAA,IAChB,aAAa,CAAC,WAAW;AAAA,IACzB,OAAO;AAAA,EACT;AACF;AAEO,IAAM,qBAAqB,CAChC,aACuB,iBAAiB;AAGnC,IAAM,oBAAoB,CAAC,aAChC,iBAAiB,UAAU,SAAS;",
|
|
8
|
-
"debugId": "B1958AC304E6284364756E2164756E21",
|
|
9
|
-
"names": []
|
|
10
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
// src/ai/mcp/tools.ts
|
|
4
|
-
var READ_ONLY = { openWorldHint: false, readOnlyHint: true };
|
|
5
|
-
var MCP_TOOLS = [
|
|
6
|
-
{
|
|
7
|
-
annotations: READ_ONLY,
|
|
8
|
-
description: '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.',
|
|
9
|
-
name: "search_docs",
|
|
10
|
-
title: "Search documentation"
|
|
11
|
-
},
|
|
12
|
-
{
|
|
13
|
-
annotations: READ_ONLY,
|
|
14
|
-
description: "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`.",
|
|
15
|
-
name: "get_page",
|
|
16
|
-
title: "Get page Markdown"
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
annotations: READ_ONLY,
|
|
20
|
-
description: '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.',
|
|
21
|
-
name: "list_pages",
|
|
22
|
-
title: "List pages"
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
annotations: READ_ONLY,
|
|
26
|
-
description: "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.",
|
|
27
|
-
name: "get_navigation",
|
|
28
|
-
title: "Get navigation"
|
|
29
|
-
}
|
|
30
|
-
];
|
|
31
|
-
|
|
32
|
-
export { MCP_TOOLS };
|
|
33
|
-
|
|
34
|
-
//# debugId=56B52393DC55784564756E2164756E21
|
|
35
|
-
//# sourceMappingURL=chunk-ra1v2nc2.js.map
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/ai/mcp/tools.ts"],
|
|
4
|
-
"sourcesContent": [
|
|
5
|
-
"/**\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"
|
|
6
|
-
],
|
|
7
|
-
"mappings": ";;;AAQA,IAAM,YAAY,EAAE,eAAe,OAAO,cAAc,KAAK;AAStD,IAAM,YAA2B;AAAA,EACtC;AAAA,IACE,aAAa;AAAA,IACb,aACE;AAAA,IACF,MAAM;AAAA,IACN,OAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,aAAa;AAAA,IACb,aACE;AAAA,IACF,MAAM;AAAA,IACN,OAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,aAAa;AAAA,IACb,aACE;AAAA,IACF,MAAM;AAAA,IACN,OAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,aAAa;AAAA,IACb,aACE;AAAA,IACF,MAAM;AAAA,IACN,OAAO;AAAA,EACT;AACF;",
|
|
8
|
-
"debugId": "56B52393DC55784564756E2164756E21",
|
|
9
|
-
"names": []
|
|
10
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
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 { join } 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 { runEval } from \"../../eval/run.ts\";\nimport type { EvalResult } from \"../../eval/run.ts\";\nimport { EvalsFileError, loadEvalsFile } from \"../../eval/schema.ts\";\nimport { commandMeta } from \"../command-meta.ts\";\nimport { reportInternalError } from \"../internal-error.ts\";\nimport { flushStdout, logger } 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\n/** The fraction of run (non-skipped) questions that passed. */\nexport const passFraction = (result: EvalResult): number => {\n const ran = result.results.length - result.counts.skip;\n return ran === 0 ? 1 : result.counts.pass / ran;\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 claude | codex).`);\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 if (!Number.isFinite(threshold) || threshold < 0 || threshold > 1) {\n logger.error(`Invalid --threshold \"${args.threshold}\" (use 0..1).`);\n process.exit(1);\n }\n const timeoutS =\n args.timeout === undefined ? DEFAULT_TIMEOUT_S : Number(args.timeout);\n if (!Number.isInteger(timeoutS) || timeoutS <= 0) {\n logger.error(`Invalid --timeout \"${args.timeout}\" (whole seconds).`);\n process.exit(1);\n }\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 = join(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: \"claude\",\n description: \"Agent CLI that reads and grades the docs: claude | codex.\",\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 const evalsPath = join(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 logger.error(error.diagnostic.message);\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 process.exit(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/** `fix:` pointers for failed questions, naming the file that resolves each. */\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 return ` ${colors.cyan(\"fix:\")} ${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/**\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/reference/eval\";\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, anchored to the page that\n * should have answered it (via the first matching route hint) or, failing\n * that, to the question's line in the evals file.\n */\nexport const questionFinding = (\n question: EvalQuestion,\n outcome: QuestionOutcome,\n project: BlumeProject,\n anchor: EvalsAnchor\n): Diagnostic => {\n const route = hintedRoute(question, project);\n const site = route\n ? { file: route.sourcePath, url: route.path }\n : { file: anchor.path, line: locateQuestion(anchor.raw, question.id) };\n\n if (outcome.status === \"error\") {\n return {\n code: \"BLUME_EVAL_QUESTION_ERROR\",\n docsUrl: DOCS_URL,\n message: `Eval run failed for \"${question.question}\"${\n outcome.detail ? ` — ${outcome.detail}` : \"\"\n }.`,\n severity: question.severity,\n suggestion:\n \"Rerun `blume eval`; if it persists, check the agent CLI installation and the failure detail.\",\n ...site,\n };\n }\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": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAEA;AACA,iBAAS;;;ACKF,IAAM,eAAe,CAAC,aAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,YAQU,SAAS;AAAA;AAAA;AAKd,IAAM,cAAc,CAAC,UAAwB,WAA2B;AAAA,EAC7E,MAAM,QAAQ,SAAS,SAAS,IAAI,CAAC,SAAS,KAAK,MAAM,EAAE,KAAK;AAAA,CAAI;AAAA,EACpE,OAAO;AAAA;AAAA,YAEG,SAAS;AAAA;AAAA;AAAA,EAGnB;AAAA;AAAA;AAAA;AAAA,EAIA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAUK,IAAM,gBAAgB,CAAC,eAC5B;AAAA;AAAA,wBAEsB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAUjB,IAAM,aAAa,CAAC,cACzB;AAAA;AAAA,gEAE8D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;AC3DhE;AACA;AAEA;AAEA;AAOA,IAAM,QAAQ;AAAA,EACZ,OAAO;AAAA,EACP,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AACR;AAEA,IAAM,eAAe;AAAA,EACnB,OAAO,OAAO;AAAA,EACd,MAAM,OAAO;AAAA,EACb,MAAM,OAAO;AAAA,EACb,MAAM,OAAO;AACf;AAGA,IAAM,SAAS;AAGR,IAAM,eAAe,CAAC,WAAmC;AAAA,EAC9D,MAAM,QAAQ,aAAa,OAAO;AAAA,EAClC,MAAM,QAAQ,MAAM,MAAM,OAAO,OAAO;AAAA,EACxC,MAAM,KAAK,OAAO,GAAG,OAAO,MAAM;AAAA,EAClC,IAAI,OAAO,WAAW,QAAQ;AAAA,IAC5B,OAAO,KAAK,SAAS,MAAM,OAAO,IAAI,SAAS;AAAA,EACjD;AAAA,EACA,MAAM,QAAQ,OAAO,UAAU,YAAY,KAAK,OAAO,MAAM,QAAQ,CAAC;AAAA,EACtE,MAAM,OAAO,MAAM,OAAO,OAAO;AAAA,EACjC,MAAM,QAAQ;AAAA,IACZ,MAAM,OAAO,MAAM;AAAA,IACnB;AAAA,IACA,OAAO,IAAI,QAAQ,OAAO,UAAU,CAAC;AAAA,IACrC,SAAS,KAAK,KAAK,OAAO,IAAI,IAAI;AAAA,EACpC,EACG,OAAO,CAAC,SAAS,SAAS,EAAE,EAC5B,KAAK,IAAI;AAAA,EACZ,OAAO,KAAK,SAAS,MAAM;AAAA;AAItB,IAAM,kBAAkB,CAC7B,QACA,YACa;AAAA,EACb,MAAM,QAAkB,CAAC;AAAA,EACzB,IAAI,OAAO,WAAW,QAAQ;AAAA,IAC5B,WAAW,QAAQ,OAAO,SAAS;AAAA,MACjC,MAAM,KAAK,SAAS,OAAO,IAAI,YAAY,MAAM,GAAG;AAAA,IACtD;AAAA,EACF;AAAA,EACA,IAAI,OAAO,WAAW,WAAW,OAAO,QAAQ;AAAA,IAC9C,MAAM,KAAK,SAAS,OAAO,IAAI,OAAO,MAAM,GAAG;AAAA,EACjD;AAAA,EACA,IAAI,WAAW,OAAO,UAAU,OAAO,WAAW,QAAQ;AAAA,IACxD,MAAM,KACJ,GAAG,OAAO,OACP,MAAM;AAAA,CAAI,EACV,IAAI,CAAC,SAAS,SAAS,OAAO,IAAI,KAAK,MAAM,GAAG,CACrD;AAAA,EACF;AAAA,EACA,OAAO;AAAA;AAIF,IAAM,cAAc,CAAC,WAA+B;AAAA,EACzD,QAAQ,WAAW;AAAA,EACnB,MAAM,QAAQ;AAAA,IACZ,GAAG,OAAO;AAAA,IACV,OAAO,OAAO,IAAI,GAAG,OAAO,gBAAgB;AAAA,IAC5C,OAAO,QAAQ,IAAI,GAAG,OAAO,kBAAkB;AAAA,IAC/C,OAAO,OAAO,IAAI,GAAG,OAAO,iBAAiB;AAAA,IAC7C,SAAS,OAAO,UAAU;AAAA,IAC1B,MAAM,OAAO,OAAO;AAAA,EACtB,EAAE,OAAO,CAAC,SAAS,SAAS,EAAE;AAAA,EAC9B,OAAO,MAAM,KAAK,KAAK;AAAA;AAIlB,IAAM,aAAa,CAAC,OAAe,UACxC,GAAG,OAAO,KAAK,YAAY,MAAM,uBAAuB,OAAO,OAAO;AAGjE,IAAM,YAAY,CAAC,IAAY,OAAe,UACnD,KAAK,OAAO,IAAI,KAAK,OAAO,QAAQ,KAAK,QAAQ;AAG5C,IAAM,WAAW,CAAC,QAAoB,SAC3C,OAAO,YACJ,OAAO,CAAC,eAAe,WAAW,SAAS,0BAA0B,EACrE,IAAI,CAAC,YAAY;AAAA,EAChB,MAAM,OAAO,QAAQ,OACjB,GAAG,SAAS,MAAM,QAAQ,IAAI,IAAI,QAAQ,OAAO,IAAI,QAAQ,SAAS,OACtE;AAAA,EACJ,OAAO,KAAK,OAAO,KAAK,MAAM,KAAK,QAAQ,OAAO,IAAI,QAAQ,OAAO;AAAA,CACtE;AAGE,IAAM,eAAe,CAAC,QAAoB,SAC/C,OAAO,YACJ,OAAO,CAAC,eAAe,WAAW,SAAS,0BAA0B,EACrE,IAAI,CAAC,YAAY;AAAA,EAChB,MAAM,OAAO,QAAQ,OACjB,IAAI,SAAS,MAAM,QAAQ,IAAI,IAAI,QAAQ,OAAO,IAAI,QAAQ,SAAS,OACvE;AAAA,EACJ,OAAO,KAAK,OAAO,OAAO,GAAG,IAAI,QAAQ,OAAO,IAAI,QAAQ,OAAO;AAAA,CACpE;AAkCE,IAAM,iBAAiB,CAC5B,QACA,MACA,cACW;AAAA,EACX,MAAM,cAAc,OAAO,YAAY,IAAI,CAAC,eAC1C,WAAW,OACP,KAAK,YAAY,MAAM,SAAS,MAAM,WAAW,IAAI,EAAE,IACvD,UACN;AAAA,EACA,OAAO,GAAG,KAAK,UACb;AAAA,IACE;AAAA,IACA,MAAM;AAAA,MACJ,OAAO,OAAO;AAAA,MACd,SAAS,OAAO;AAAA,MAChB,QAAQ,OAAO;AAAA,MACf,YAAY,OAAO;AAAA,MACnB,SAAS,OAAO;AAAA,MAChB;AAAA,IACF;AAAA,IACA,SAAS,gBAAgB,OAAO,WAAW;AAAA,EAC7C,GACA,MACA,CACF;AAAA;AAAA;AAQK,IAAM,kBAAkB,OAC7B,QACA,MACA,cACoB;AAAA,EACpB,MAAM,MAAM,MAAM,QAAQ,KAAK,OAAO,GAAG,aAAa,CAAC;AAAA,EACvD,MAAM,OAAO,KAAK,KAAK,aAAa;AAAA,EACpC,MAAM,UAAU,MAAM,eAAe,QAAQ,MAAM,SAAS,CAAC;AAAA,EAC7D,OAAO;AAAA;;;AC/LT,2BAAgB,uBAAS;AACzB,mBAAS;AAET,iBAAS;;;ACHT;AAEA;AACA;AAKA,IAAM,aAAa;AAEnB,IAAM,iBAAiB,EAAE,aAAa;AAAA,EACpC,UAAU,EACP,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,EACvB,IAAI,GAAG,sCAAsC;AAAA,EAChD,IAAI,EACD,OAAO,EACP,MAAM,YAAY,iDAAiD;AAAA,EACtE,UAAU,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EAC1B,QAAQ,EACL,MAAM,CAAC,EAAE,OAAO,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,EACvC,QAAQ,CAAC,CAAC,EACV,UAAU,CAAC,UAAW,MAAM,QAAQ,KAAK,IAAI,QAAQ,CAAC,KAAK,CAAE;AAAA,EAChE,UAAU,EAAE,KAAK,CAAC,SAAS,SAAS,CAAC,EAAE,QAAQ,OAAO;AAAA,EACtD,MAAM,EAAE,QAAQ,EAAE,QAAQ,KAAK;AACjC,CAAC;AAKD,IAAM,aAAa,EAAE,aAAa;AAAA,EAChC,WAAW,EAAE,MAAM,cAAc,EAAE,IAAI,CAAC;AAAA,EACxC,SAAS,EAAE,QAAQ,CAAC,EAAE,QAAQ,CAAC;AACjC,CAAC;AAQM,IAAM,kBAAkB,WAAW,YAAY,CAAC,OAAO,YAAY;AAAA,EACxE,MAAM,OAAO,IAAI;AAAA,EACjB,WAAW,YAAY,MAAM,WAAW;AAAA,IACtC,IAAI,KAAK,IAAI,SAAS,EAAE,GAAG;AAAA,MACzB,QAAQ,SAAS;AAAA,QACf,MAAM,EAAE,aAAa;AAAA,QACrB,SAAS,0BAA0B,SAAS;AAAA,QAC5C,MAAM,CAAC,WAAW;AAAA,MACpB,CAAC;AAAA,IACH;AAAA,IACA,KAAK,IAAI,SAAS,EAAE;AAAA,EACtB;AAAA,CACD;AAAA;AAKM,MAAM,uBAAuB,MAAM;AAAA,EAC/B;AAAA,EAET,WAAW,CAAC,MAAc,SAAiB;AAAA,IACzC,MAAM,OAAO;AAAA,IACb,KAAK,OAAO;AAAA,IACZ,KAAK,OAAO;AAAA;AAEhB;AAEA,IAAM,iBAAiB,CAAC,UACtB,MAAM,OACH,IAAI,CAAC,UAAU;AAAA,EACd,MAAM,KAAK,MAAM,KAAK,SAAS,IAAI,OAAO,MAAM,KAAK,KAAK,GAAG,MAAM;AAAA,EACnE,OAAO,GAAG,MAAM,UAAU;AAAA,CAC3B,EACA,KAAK,IAAI;AAMP,IAAM,gBAAgB,OAC3B,SAC+C;AAAA,EAC/C,IAAI;AAAA,EACJ,IAAI;AAAA,IACF,MAAM,MAAM,SAAS,MAAM,OAAO;AAAA,IAClC,MAAM;AAAA,IACN,MAAM,IAAI,eACR,MACA,0BAA0B,6CAC5B;AAAA;AAAA,EAGF,IAAI;AAAA,EACJ,IAAI;AAAA,IACF,SAAS,KAAK,KAAK,EAAE,QAAQ,YAAY,CAAC;AAAA,IAC1C,OAAO,OAAO;AAAA,IACd,MAAM,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,IACpE,MAAM,IAAI,eAAe,MAAM,mBAAmB,SAAS,QAAQ;AAAA;AAAA,EAIrE,MAAM,YAAY,MAAM,QAAQ,MAAM,IAAI,EAAE,WAAW,OAAO,IAAI;AAAA,EAClE,MAAM,SAAS,gBAAgB,UAAU,SAAS;AAAA,EAClD,IAAI,CAAC,OAAO,SAAS;AAAA,IACnB,MAAM,IAAI,eACR,MACA,yBAAyB,SAAS,eAAe,OAAO,KAAK,GAC/D;AAAA,EACF;AAAA,EACA,OAAO,EAAE,OAAO,OAAO,MAAM,IAAI;AAAA;AAO5B,IAAM,iBAAiB,CAAC,KAAa,OAAmC;AAAA,EAC7E,MAAM,UAAU,IAAI,OAAO,0BAA0B,gBAAgB,GAAG;AAAA,EACxE,MAAM,QAAQ,IAAI,MAAM;AAAA,CAAI;AAAA,EAC5B,YAAY,OAAO,SAAS,MAAM,QAAQ,GAAG;AAAA,IAC3C,IAAI,QAAQ,KAAK,IAAI,GAAG;AAAA,MACtB,OAAO,QAAQ;AAAA,IACjB;AAAA,EACF;AAAA,EACA;AAAA;;;ACvHF,IAAM,WAAW;AASjB,IAAM,cAAc,CAAC,UAAwB,YAA0B;AAAA,EACrE,WAAW,QAAQ,SAAS,QAAQ;AAAA,IAClC,MAAM,QAAQ,QAAQ,SAAS,OAAO,KACpC,CAAC,cAAc,UAAU,SAAS,IACpC;AAAA,IACA,IAAI,OAAO;AAAA,MACT,OAAO;AAAA,IACT;AAAA,EACF;AAAA;AAQK,IAAM,gBAAgB,CAC3B,UACA,SACA,WACiB;AAAA,EACjB,MAAM,QAAQ,IAAI,IAAI,QAAQ,SAAS,OAAO,IAAI,CAAC,UAAU,MAAM,IAAI,CAAC;AAAA,EACxE,OAAO,SAAS,OACb,OAAO,CAAC,SAAS,CAAC,MAAM,IAAI,IAAI,CAAC,EACjC,IAAI,CAAC,UAAU;AAAA,IACd,MAAM;AAAA,IACN,SAAS;AAAA,IACT,MAAM,OAAO;AAAA,IACb,MAAM,eAAe,OAAO,KAAK,SAAS,EAAE;AAAA,IAC5C,SAAS,aAAa,SAAS,uBAAuB;AAAA,IACtD,UAAU;AAAA,IACV,YACE;AAAA,EACJ,EAAE;AAAA;AAiBC,IAAM,kBAAkB,CAC7B,UACA,SACA,SACA,WACe;AAAA,EACf,MAAM,QAAQ,YAAY,UAAU,OAAO;AAAA,EAC3C,MAAM,OAAO,QACT,EAAE,MAAM,MAAM,YAAY,KAAK,MAAM,KAAK,IAC1C,EAAE,MAAM,OAAO,MAAM,MAAM,eAAe,OAAO,KAAK,SAAS,EAAE,EAAE;AAAA,EAEvE,IAAI,QAAQ,WAAW,SAAS;AAAA,IAC9B,OAAO;AAAA,MACL,MAAM;AAAA,MACN,SAAS;AAAA,MACT,SAAS,wBAAwB,SAAS,YACxC,QAAQ,SAAS,MAAM,QAAQ,WAAW;AAAA,MAE5C,UAAU,SAAS;AAAA,MACnB,YACE;AAAA,SACC;AAAA,IACL;AAAA,EACF;AAAA,EAEA,MAAM,UACJ,QAAQ,QAAQ,SAAS,IACrB,eAAe,QAAQ,QAAQ,KAAK,IAAI,MACxC;AAAA,EACN,OAAO;AAAA,IACL,MAAM;AAAA,IACN,SAAS;AAAA,IACT,SAAS,2BAA2B,SAAS,YAAY;AAAA,IACzD,UAAU,SAAS;AAAA,IACnB,YACE;AAAA,OACC;AAAA,EACL;AAAA;;;AF9EF,IAAM,4BAA4B;AAClC,IAAM,2BAA2B;AAiEjC,IAAM,UAAU,CACd,UACA,QACA,gBACoB;AAAA,EACpB;AAAA,EACA;AAAA,EACA,UAAU,SAAS;AAAA,EACnB,IAAI,SAAS;AAAA,EACb,SAAS,CAAC;AAAA,EACV,UAAU,SAAS;AAAA,EACnB,QAAQ,SAAS;AAAA,EACjB,QAAQ;AACV;AAGA,IAAM,cAAc,OAClB,UACA,OACA,YAC4B;AAAA,EAC5B,MAAM,UAAU,YAAY,IAAI;AAAA,EAChC,MAAM,UAAU,MAAM,KAAK,MAAM,YAAY,IAAI,IAAI,OAAO;AAAA,EAI5D,MAAM,UAAU,MAAK,QAAQ,KAAK,QAAQ,OAAO;AAAA,EACjD,MAAM,MAAM,SAAS,EAAE,WAAW,KAAK,CAAC;AAAA,EAExC,MAAM,aAAa,MAAK,SAAS,YAAY;AAAA,EAC7C,MAAM,SAAS,MAAM,QAAQ,IAC3B,QAAQ,KACR,UAAU,QAAQ,MAAM,EAAE,iBAAiB,YAAY,KAAK,QAAQ,IAAI,CAAC,GACzE;AAAA,IACE,KAAK;AAAA,IACL,QAAQ,aAAa,QAAQ;AAAA,IAC7B,WAAW,QAAQ;AAAA,EACrB,CACF;AAAA,EACA,MAAM,SAAS,MAAM,gBAAgB,QAAQ,MAAM,QAAQ,UAAU;AAAA,EACrE,IAAI,OAAO,SAAS;AAAA,IAClB,OAAO;AAAA,SACF,QAAQ,UAAU,UAAU,OAAO,UAAU,YAAY,QAAQ,CAAC;AAAA,MACrE,SAAS,OAAO;AAAA,IAClB;AAAA,EACF;AAAA,EAEA,MAAM,cAAc,MAAK,SAAS,aAAa;AAAA,EAC/C,MAAM,QAAQ,MAAM,QAAQ,IAC1B,QAAQ,KACR,UAAU,QAAQ,MAAM,EAAE,iBAAiB,YAAY,CAAC,GACxD;AAAA,IACE,KAAK;AAAA,IACL,QAAQ,YAAY,UAAU,OAAO,IAAI;AAAA,IACzC,WAAW,QAAQ;AAAA,EACrB,CACF;AAAA,EACA,MAAM,SAAS,MAAM,gBAAgB,QAAQ,MAAM,OAAO,WAAW;AAAA,EACrE,MAAM,UACJ,OAAO,YAAY,aAAa,OAAO,YAAY,YAC/C,aACC,OAAO,WAAW,MAAM,OAAO,WAAW;AAAA,EACjD,IAAI,OAAO,SAAS;AAAA,IAClB,OAAO;AAAA,SACF,QAAQ,UAAU,SAAS,OAAO,UAAU,YAAY,QAAQ,CAAC;AAAA,MACpE,QAAQ,OAAO;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,UAAU,aAAa,OAAO,IAAI;AAAA,EACxC,IAAI,CAAC,SAAS;AAAA,IACZ,OAAO;AAAA,SACF,QAAQ,UAAU,uCAAuC,QAAQ,CAAC;AAAA,MACrE,QAAQ,OAAO;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAAA,EAEA,OAAO;AAAA,IACL,QAAQ,OAAO;AAAA,IACf;AAAA,IACA,YAAY,QAAQ;AAAA,IACpB,UAAU,SAAS;AAAA,IACnB,IAAI,SAAS;AAAA,IACb,SAAS,QAAQ;AAAA,IACjB,OAAO,QAAQ,SAAS;AAAA,IACxB,UAAU,SAAS;AAAA,IACnB,QAAQ,SAAS;AAAA,IACjB,OAAO,QAAQ;AAAA,IACf,QAAQ,QAAQ,OAAO,SAAS;AAAA,EAClC;AAAA;AAQK,IAAM,UAAU,OAAO,YAAiD;AAAA,EAC7E,MAAM,UAAU,YAAY,IAAI;AAAA,EAChC,MAAM,OAAO,QAAQ;AAAA,EACrB,MAAM,MAAM,QAAQ,OAAO;AAAA,EAC3B,MAAM,SAAS,EAAE,MAAM,QAAQ,WAAW,KAAK,QAAQ,SAAS;AAAA,EAEhE,MAAM,MAAM,MAAM,SAAQ,MAAK,QAAO,GAAG,aAAa,CAAC;AAAA,EACvD,MAAM,eAAe,MAAK,KAAK,eAAe;AAAA,EAC9C,MAAM,WACJ,cACA,KAAK,UAAU,MAAM,aAAa,QAAQ,OAAO,CAAC,CACpD;AAAA,EACA,MAAM,MAAM,MAAM,eAAe,KAAK,YAAY;AAAA,EAElD,MAAM,UAA2B;AAAA,IAC/B,KAAK,OAAO,MAAM;AAAA,IAClB;AAAA,IACA,gBAAgB,QAAQ,kBAAkB;AAAA,IAC1C;AAAA,IACA;AAAA,IACA,iBAAiB,QAAQ,mBAAmB;AAAA,IAC5C;AAAA,EACF;AAAA,EAEA,MAAM,cAA4B,CAAC;AAAA,EACnC,MAAM,UAA4B,CAAC;AAAA,EACnC,QAAQ,cAAc,QAAQ;AAAA,EAE9B,YAAY,OAAO,aAAa,UAAU,QAAQ,GAAG;AAAA,IACnD,YAAY,KAAK,GAAG,cAAc,UAAU,QAAQ,SAAS,MAAM,CAAC;AAAA,IAEpE,IAAI,SAAS,MAAM;AAAA,MACjB,QAAQ,KAAK;AAAA,QACX,YAAY;AAAA,QACZ,UAAU,SAAS;AAAA,QACnB,IAAI,SAAS;AAAA,QACb,SAAS,CAAC;AAAA,QACV,UAAU,SAAS;AAAA,QACnB,QAAQ,SAAS;AAAA,QACjB,QAAQ;AAAA,MACV,CAAC;AAAA,MACD;AAAA,IACF;AAAA,IAEA,QAAQ,aAAa;AAAA,MACnB,IAAI,SAAS;AAAA,MACb;AAAA,MACA,MAAM;AAAA,MACN,OAAO,UAAU;AAAA,IACnB,CAAC;AAAA,IAID,MAAM,SAAS,MAAM,YAAY,UAAU,OAAO,OAAO;AAAA,IACzD,QAAQ,KAAK,MAAM;AAAA,IACnB,IAAI,OAAO,WAAW,UAAU,OAAO,WAAW,SAAS;AAAA,MACzD,YAAY,KACV,gBACE,UACA;AAAA,QACE,QAAQ,OAAO;AAAA,QACf,SAAS,OAAO;AAAA,QAChB,QAAQ,OAAO;AAAA,MACjB,GACA,QAAQ,SACR,MACF,CACF;AAAA,IACF;AAAA,IACA,QAAQ,aAAa;AAAA,MACnB;AAAA,MACA,MAAM;AAAA,MACN;AAAA,MACA,OAAO,UAAU;AAAA,IACnB,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,SAAS;AAAA,IACb,OAAO;AAAA,IACP,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,WAAW,UAAU,SAAS;AAAA,IAC5B,OAAO,OAAO,WAAW;AAAA,EAC3B;AAAA,EACA,MAAM,QAAQ,QAAQ,QAAQ,CAAC,WAC7B,OAAO,YAAY,YAAY,CAAC,IAAI,CAAC,OAAO,OAAO,CACrD;AAAA,EAEA,OAAO;AAAA,IACL,OAAO;AAAA,IACP,SACE,MAAM,SAAS,IACX,MAAM,OAAO,CAAC,OAAO,SAAS,QAAQ,MAAM,CAAC,IAC7C;AAAA,IACN;AAAA,IACA;AAAA,IACA,YAAY,KAAK,MAAM,YAAY,IAAI,IAAI,OAAO;AAAA,IAClD;AAAA,EACF;AAAA;;;AHpQF,IAAM,eAAe;AAGrB,IAAM,oBAAoB;AAE1B,IAAM,cAAc,CAAC,WAAsC,SAAS;AAOpE,IAAM,eAAe,CAAC,UAA4B;AAAA,EAChD,MAAM,MAAM,OAAO;AAAA,EACnB,OAAO,MACL,GAAG,IAAI,WAAW,IAAI,mDAAmD,IAAI,YAC/E;AAAA,EACA,OAAO,QAAQ,KAAK,CAAC;AAAA;AAGvB,IAAM,kBAAkB,OACtB,OACA,WACoB;AAAA,EACpB,IAAI;AAAA,IACF,OAAO,MAAM,YAAY,OAAO,OAAO,KAAK,MAAM;AAAA,IAClD,OAAO,OAAO;AAAA,IAId,IAAK,OAAiC,SAAS,UAAU;AAAA,MACvD,MAAM;AAAA,IACR;AAAA,IACA,OAAO,aAAa,KAAK;AAAA;AAAA;AAKtB,IAAM,eAAe,CAAC,WAA+B;AAAA,EAC1D,MAAM,MAAM,OAAO,QAAQ,SAAS,OAAO,OAAO;AAAA,EAClD,OAAO,QAAQ,IAAI,IAAI,OAAO,OAAO,OAAO;AAAA;AAc9C,IAAM,aAAa,CAAC,SAAoB;AAAA,EACtC,IAAI,CAAC,YAAY,KAAK,KAAK,GAAG;AAAA,IAC5B,OAAO,MAAM,oBAAoB,KAAK,8BAA8B;AAAA,IACpE,QAAQ,KAAK,CAAC;AAAA,EAChB;AAAA,EACA,IAAI,KAAK,WAAW,aAAa,KAAK,WAAW,QAAQ;AAAA,IACvD,OAAO,MAAM,mBAAmB,KAAK,iCAAiC;AAAA,IACtE,QAAQ,KAAK,CAAC;AAAA,EAChB;AAAA,EACA,IAAI,KAAK,QAAQ,KAAK,KAAK;AAAA,IACzB,OAAO,MAAM,0CAA0C;AAAA,IACvD,QAAQ,KAAK,CAAC;AAAA,EAChB;AAAA,EACA,MAAM,YAAY,KAAK,cAAc,YAAY,IAAI,OAAO,KAAK,SAAS;AAAA,EAC1E,IAAI,CAAC,OAAO,SAAS,SAAS,KAAK,YAAY,KAAK,YAAY,GAAG;AAAA,IACjE,OAAO,MAAM,wBAAwB,KAAK,wBAAwB;AAAA,IAClE,QAAQ,KAAK,CAAC;AAAA,EAChB;AAAA,EACA,MAAM,WACJ,KAAK,YAAY,YAAY,oBAAoB,OAAO,KAAK,OAAO;AAAA,EACtE,IAAI,CAAC,OAAO,UAAU,QAAQ,KAAK,YAAY,GAAG;AAAA,IAChD,OAAO,MAAM,sBAAsB,KAAK,2BAA2B;AAAA,IACnE,QAAQ,KAAK,CAAC;AAAA,EAChB;AAAA,EACA,OAAO,EAAE,OAAO,KAAK,OAAO,WAAW,SAAS;AAAA;AAIlD,IAAM,gBAAgB,OACpB,OACA,QACA,MACA,cACkB;AAAA,EAClB,MAAM,QAAQ,OAAO,OAAO,OAAO,OAAO,OAAO;AAAA,EACjD,IAAI,UAAU,GAAG;AAAA,IACf;AAAA,EACF;AAAA,EACA,MAAM,MAAM,OAAO;AAAA,EACnB,MAAM,SAAS,MAAM,gBAAgB,QAAQ,MAAM,SAAS;AAAA,EAC5D,QAAQ,OAAO,MACb,aAAa,wBAAwB,UAAU,IAAI,KAAK,UAAU,IAAI;AAAA;AAAA,CACxE;AAAA,EACA,MAAM,OAAO,MAAM,gBAAgB,OAAO,cAAc,MAAM,CAAC;AAAA,EAC/D,IAAI,SAAS,GAAG;AAAA,IACd,QAAQ,KAAK,IAAI;AAAA,EACnB;AAAA;AAIF,IAAM,UAAU,OAAO,OAAkB,SAAgC;AAAA,EACvE,MAAM,OAAO,MAAK,QAAQ,IAAI,GAAG,IAAI;AAAA,EACrC,IAAI,WAAW,IAAI,GAAG;AAAA,IACpB,OAAO,MACL,GAAG,4EACL;AAAA,IACA,QAAQ,KAAK,CAAC;AAAA,EAChB;AAAA,EACA,MAAM,OAAO,MAAM,gBAAgB,OAAO,WAAW,IAAI,CAAC;AAAA,EAC1D,IAAI,SAAS,GAAG;AAAA,IACd,QAAQ,KAAK,IAAI;AAAA,EACnB;AAAA;AAGK,IAAM,cAAc,cAAc;AAAA,EACvC,MAAM;AAAA,IACJ,QAAQ;AAAA,MACN,aAAa;AAAA,MACb,UAAU;AAAA,MACV,MAAM;AAAA,IACR;AAAA,IACA,OAAO;AAAA,MACL,SAAS;AAAA,MACT,aAAa;AAAA,MACb,MAAM;AAAA,IACR;AAAA,IACA,MAAM;AAAA,MACJ,SAAS;AAAA,MACT,aAAa;AAAA,MACb,MAAM;AAAA,IACR;AAAA,IACA,KAAK;AAAA,MACH,aACE;AAAA,MACF,MAAM;AAAA,IACR;AAAA,IACA,MAAM;AAAA,MACJ,aAAa;AAAA,MACb,MAAM;AAAA,IACR;AAAA,IACA,WAAW;AAAA,MACT,aACE;AAAA,MACF,MAAM;AAAA,IACR;AAAA,IACA,SAAS;AAAA,MACP,aAAa,2DAA2D;AAAA,MACxE,MAAM;AAAA,IACR;AAAA,IACA,SAAS;AAAA,MACP,aAAa;AAAA,MACb,MAAM;AAAA,IACR;AAAA,EACF;AAAA,EACA,MAAM,YAAY;AAAA,OACZ,IAAG,GAAG,QAAQ;AAAA,IAClB,MAAM,OAAO,QAAQ,IAAI;AAAA,IACzB,QAAQ,OAAO,WAAW,aAAa,WAAW,IAAI;AAAA,IACtD,IAAI,KAAK,WAAW,QAAQ;AAAA,MAC1B,MAAM,QAAQ,OAAO,KAAK,IAAI;AAAA,MAC9B;AAAA,IACF;AAAA,IAEA,IAAI;AAAA,IACJ,IAAI;AAAA,MAIF,MAAM,UAAU,MAAM,YAAY,MAAM,EAAE,MAAM,QAAQ,CAAC;AAAA,MACzD,MAAM,YAAY,MAAK,MAAM,KAAK,IAAI;AAAA,MACtC,QAAQ,OAAO,QAAQ,MAAM,cAAc,SAAS;AAAA,MAEpD,QAAQ,OAAO,MAAM,GAAG,WAAW,MAAM,UAAU,QAAQ,KAAK;AAAA;AAAA,CAAO;AAAA,MACvE,SAAS,MAAM,QAAQ;AAAA,QACrB;AAAA,QACA;AAAA,QACA;AAAA,QACA,YAAY,CAAC,UAAU;AAAA,UAGrB,IAAI,MAAM,SAAS,kBAAkB;AAAA,YACnC,QAAQ,OAAO,MACb,GAAG,UAAU,MAAM,IAAI,MAAM,OAAO,MAAM,KAAK;AAAA,CACjD;AAAA,YACA;AAAA,UACF;AAAA,UACA,MAAM,QAAQ;AAAA,YACZ,aAAa,MAAM,MAAM;AAAA,YACzB,GAAG,gBAAgB,MAAM,QAAQ,QAAQ,KAAK,OAAO,CAAC;AAAA,UACxD;AAAA,UACA,QAAQ,OAAO,MAAM,GAAG,MAAM,KAAK;AAAA,CAAI;AAAA,CAAK;AAAA;AAAA,QAE9C;AAAA,QACA,UAAU;AAAA,QACV,iBAAiB,WAAW;AAAA,MAC9B,CAAC;AAAA,MACD,OAAO,OAAO;AAAA,MACd,IAAI,iBAAiB,gBAAgB;AAAA,QACnC,OAAO,MAAM,MAAM,OAAO;AAAA,QAC1B,QAAQ,KAAK,CAAC;AAAA,MAChB;AAAA,MACA,IAAI,iBAAiB,YAAY;AAAA,QAC/B,OAAO,MAAM,MAAM,WAAW,OAAO;AAAA,QACrC,QAAQ,KAAK,CAAC;AAAA,MAChB;AAAA,MAIA,IAAK,OAAiC,SAAS,UAAU;AAAA,QACvD,aAAa,KAAK;AAAA,MACpB;AAAA,MACA,oBAAoB,KAAK;AAAA,MACzB,QAAQ,KAAK,CAAC;AAAA;AAAA,IAGhB,MAAM,OAAO;AAAA,MACX;AAAA,MACA,GAAG,aAAa,QAAQ,IAAI;AAAA,MAC5B,GAAG,SAAS,QAAQ,IAAI;AAAA,MACxB;AAAA,MACA,KAAK,YAAY,MAAM;AAAA,MACvB;AAAA,IACF;AAAA,IACA,QAAQ,OAAO,MAAM,KAAK,KAAK;AAAA,CAAI,CAAC;AAAA,IAEpC,MAAM,SAAS,aAAa,MAAM,IAAI;AAAA,IAEtC,IAAI,KAAK,KAAK;AAAA,MAGZ,MAAM,cAAc,OAAO,QAAQ,MAAM,SAAS;AAAA,MAClD;AAAA,IACF;AAAA,IAEA,IAAI,KAAK,MAAM;AAAA,MACb,QAAQ,OAAO,MAAM,eAAe,QAAQ,MAAM,SAAS,CAAC;AAAA,MAC5D,IAAI,QAAQ;AAAA,QAGV,MAAM,YAAY;AAAA,QAClB,QAAQ,KAAK,CAAC;AAAA,MAChB;AAAA,MACA;AAAA,IACF;AAAA,IAEA,IAAI,QAAQ;AAAA,MACV,QAAQ,KAAK,CAAC;AAAA,IAChB;AAAA;AAEJ,CAAC;",
|
|
13
|
-
"debugId": "83C1CBF787A3FD3264756E2164756E21",
|
|
14
|
-
"names": []
|
|
15
|
-
}
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
absoluteUrl
|
|
4
|
-
} from "./chunk-88by27n5.js";
|
|
5
|
-
import {
|
|
6
|
-
resolveReferences
|
|
7
|
-
} from "./chunk-61j18dwk.js";
|
|
8
|
-
import {
|
|
9
|
-
normalizeBasePath,
|
|
10
|
-
withBasePath
|
|
11
|
-
} from "./chunk-2mzebbbz.js";
|
|
12
|
-
|
|
13
|
-
// src/ai/api/paths.ts
|
|
14
|
-
var OPENAPI_PATH = "/openapi.json";
|
|
15
|
-
var API_BASE = "/api/docs";
|
|
16
|
-
var API_PAGES_PATH = `${API_BASE}/pages.json`;
|
|
17
|
-
var API_PAGE_PATH = `${API_BASE}/pages/{route}.json`;
|
|
18
|
-
var API_NAVIGATION_PATH = `${API_BASE}/navigation.json`;
|
|
19
|
-
var API_SEARCH_PATH = `${API_BASE}/search`;
|
|
20
|
-
var pageParam = (route) => route === "/" ? "index" : route.slice(1);
|
|
21
|
-
var pageJsonPath = (route) => `${API_BASE}/pages/${pageParam(route)}.json`;
|
|
22
|
-
|
|
23
|
-
// src/ai/api-catalog.ts
|
|
24
|
-
var API_CATALOG_PATH = "/.well-known/api-catalog";
|
|
25
|
-
var API_CATALOG_TYPE = "application/linkset+json";
|
|
26
|
-
var HTTP_URL = /^https?:\/\//u;
|
|
27
|
-
var linksetEntries = (config) => {
|
|
28
|
-
const site = config.deployment.site ?? null;
|
|
29
|
-
const deployBase = normalizeBasePath(config.deployment.base);
|
|
30
|
-
const abs = (path) => {
|
|
31
|
-
const based = withBasePath(deployBase, path);
|
|
32
|
-
return site ? absoluteUrl(site, based) : based;
|
|
33
|
-
};
|
|
34
|
-
const entries = [];
|
|
35
|
-
for (const reference of resolveReferences(config)) {
|
|
36
|
-
const docRoute = reference.renderer === "blume" ? withBasePath(reference.basePath, reference.route) : reference.route;
|
|
37
|
-
const entry = {
|
|
38
|
-
anchor: abs(docRoute),
|
|
39
|
-
"service-doc": [{ href: abs(docRoute), type: "text/html" }]
|
|
40
|
-
};
|
|
41
|
-
if (HTTP_URL.test(reference.spec)) {
|
|
42
|
-
entry["service-desc"] = [{ href: reference.spec }];
|
|
43
|
-
}
|
|
44
|
-
entries.push(entry);
|
|
45
|
-
}
|
|
46
|
-
if (config.ai.api) {
|
|
47
|
-
entries.push({
|
|
48
|
-
anchor: abs(API_BASE),
|
|
49
|
-
"service-desc": [{ href: abs(OPENAPI_PATH), type: "application/json" }],
|
|
50
|
-
"service-doc": [{ href: abs("/"), type: "text/html" }]
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
if (config.ai.mcp.enabled) {
|
|
54
|
-
entries.push({
|
|
55
|
-
anchor: abs(config.ai.mcp.route),
|
|
56
|
-
"service-desc": [
|
|
57
|
-
{ href: abs("/.well-known/mcp.json"), type: "application/json" }
|
|
58
|
-
],
|
|
59
|
-
"service-doc": [{ href: abs("/"), type: "text/html" }]
|
|
60
|
-
});
|
|
61
|
-
}
|
|
62
|
-
return entries;
|
|
63
|
-
};
|
|
64
|
-
var hasApiCatalog = (config) => linksetEntries(config).length > 0;
|
|
65
|
-
|
|
66
|
-
export { OPENAPI_PATH, API_PAGES_PATH, API_PAGE_PATH, API_NAVIGATION_PATH, API_SEARCH_PATH, pageJsonPath, API_CATALOG_PATH, API_CATALOG_TYPE, hasApiCatalog };
|
|
67
|
-
|
|
68
|
-
//# debugId=41C2FD41D67952F664756E2164756E21
|
|
69
|
-
//# sourceMappingURL=chunk-tqa1s0k8.js.map
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/ai/api/paths.ts", "../src/ai/api-catalog.ts"],
|
|
4
|
-
"sourcesContent": [
|
|
5
|
-
"/**\n * Where the JSON docs API and its OpenAPI description are served. Base-less\n * (like every route Blume emits); callers layer `deployment.base` on top.\n * Under `/api/` alongside the Ask AI endpoint (`/api/ask`) so the namespace a\n * Blume site reserves for live endpoints stays one prefix, and under its own\n * `docs` segment so a search provider's proxy at `/api/search` never collides.\n */\n\nexport const OPENAPI_PATH = \"/openapi.json\";\nexport const API_BASE = \"/api/docs\";\nexport const API_PAGES_PATH = `${API_BASE}/pages.json`;\nexport const API_PAGE_PATH = `${API_BASE}/pages/{route}.json`;\nexport const API_NAVIGATION_PATH = `${API_BASE}/navigation.json`;\nexport const API_SEARCH_PATH = `${API_BASE}/search`;\n\n/** The `pages/{route}.json` path segment for a route (`index` for home). */\nexport const pageParam = (route: string): string =>\n route === \"/\" ? \"index\" : route.slice(1);\n\n/** The base-less served path of a route's per-page JSON document. */\nexport const pageJsonPath = (route: string): string =>\n `${API_BASE}/pages/${pageParam(route)}.json`;\n",
|
|
6
|
-
"import { normalizeBasePath, withBasePath } from \"../core/base-path.ts\";\nimport type { ResolvedConfig } from \"../core/schema.ts\";\nimport { absoluteUrl } from \"../core/site-url.ts\";\nimport { resolveReferences } from \"../openapi/references.ts\";\nimport { API_BASE, OPENAPI_PATH } from \"./api/paths.ts\";\n\n/**\n * RFC 9727 API catalog: a linkset (RFC 9264) at `/.well-known/api-catalog`\n * enumerating the APIs a publisher offers, so agents can discover them from\n * the domain alone. Blume already knows the site's APIs — the configured\n * OpenAPI/AsyncAPI references and the hosted MCP server — so the catalog is\n * generated, never hand-written: one entry per API, anchored at its docs\n * route (the RFC's own examples anchor on developer-portal pages), with\n * `service-doc` pointing at the rendered reference and `service-desc` at the\n * spec when it lives at a fetchable URL. The site's own JSON docs API is an\n * entry too, described by its generated `/openapi.json`.\n */\n\nexport const API_CATALOG_PATH = \"/.well-known/api-catalog\";\nexport const API_CATALOG_TYPE = \"application/linkset+json\";\n\n/** An RFC 9264 linkset entry, restricted to the relations Blume emits. */\ninterface LinksetEntry {\n anchor: string;\n \"service-desc\"?: { href: string; type?: string }[];\n \"service-doc\"?: { href: string; type: string }[];\n}\n\nconst HTTP_URL = /^https?:\\/\\//u;\n\n/** The catalog's linkset entries; empty when the site publishes no APIs. */\nconst linksetEntries = (config: ResolvedConfig): LinksetEntry[] => {\n const site = config.deployment.site ?? null;\n const deployBase = normalizeBasePath(config.deployment.base);\n const abs = (path: string): string => {\n const based = withBasePath(deployBase, path);\n return site ? absoluteUrl(site, based) : based;\n };\n\n const entries: LinksetEntry[] = [];\n for (const reference of resolveReferences(config)) {\n // Blume-rendered pages mount under `basePath`; Scalar pages stay at the\n // raw route (see `referenceRoutes`).\n const docRoute =\n reference.renderer === \"blume\"\n ? withBasePath(reference.basePath, reference.route)\n : reference.route;\n const entry: LinksetEntry = {\n anchor: abs(docRoute),\n \"service-doc\": [{ href: abs(docRoute), type: \"text/html\" }],\n };\n // A local spec file is parsed into pages, not served, so only a remote\n // spec has a fetchable `service-desc` URL.\n if (HTTP_URL.test(reference.spec)) {\n entry[\"service-desc\"] = [{ href: reference.spec }];\n }\n entries.push(entry);\n }\n\n if (config.ai.api) {\n entries.push({\n anchor: abs(API_BASE),\n \"service-desc\": [{ href: abs(OPENAPI_PATH), type: \"application/json\" }],\n \"service-doc\": [{ href: abs(\"/\"), type: \"text/html\" }],\n });\n }\n\n if (config.ai.mcp.enabled) {\n entries.push({\n anchor: abs(config.ai.mcp.route),\n \"service-desc\": [\n { href: abs(\"/.well-known/mcp.json\"), type: \"application/json\" },\n ],\n \"service-doc\": [{ href: abs(\"/\"), type: \"text/html\" }],\n });\n }\n return entries;\n};\n\n/** Whether the site has anything to catalog — gates every emission surface. */\nexport const hasApiCatalog = (config: ResolvedConfig): boolean =>\n linksetEntries(config).length > 0;\n\n/** The `application/linkset+json` document, or null when there are no APIs. */\nexport const buildApiCatalog = (config: ResolvedConfig): string | null => {\n const linkset = linksetEntries(config);\n if (linkset.length === 0) {\n return null;\n }\n return `${JSON.stringify({ linkset }, null, 2)}\\n`;\n};\n"
|
|
7
|
-
],
|
|
8
|
-
"mappings": ";;;;;;;;;;;;;AAQO,IAAM,eAAe;AACrB,IAAM,WAAW;AACjB,IAAM,iBAAiB,GAAG;AAC1B,IAAM,gBAAgB,GAAG;AACzB,IAAM,sBAAsB,GAAG;AAC/B,IAAM,kBAAkB,GAAG;AAG3B,IAAM,YAAY,CAAC,UACxB,UAAU,MAAM,UAAU,MAAM,MAAM,CAAC;AAGlC,IAAM,eAAe,CAAC,UAC3B,GAAG,kBAAkB,UAAU,KAAK;;;ACH/B,IAAM,mBAAmB;AACzB,IAAM,mBAAmB;AAShC,IAAM,WAAW;AAGjB,IAAM,iBAAiB,CAAC,WAA2C;AAAA,EACjE,MAAM,OAAO,OAAO,WAAW,QAAQ;AAAA,EACvC,MAAM,aAAa,kBAAkB,OAAO,WAAW,IAAI;AAAA,EAC3D,MAAM,MAAM,CAAC,SAAyB;AAAA,IACpC,MAAM,QAAQ,aAAa,YAAY,IAAI;AAAA,IAC3C,OAAO,OAAO,YAAY,MAAM,KAAK,IAAI;AAAA;AAAA,EAG3C,MAAM,UAA0B,CAAC;AAAA,EACjC,WAAW,aAAa,kBAAkB,MAAM,GAAG;AAAA,IAGjD,MAAM,WACJ,UAAU,aAAa,UACnB,aAAa,UAAU,UAAU,UAAU,KAAK,IAChD,UAAU;AAAA,IAChB,MAAM,QAAsB;AAAA,MAC1B,QAAQ,IAAI,QAAQ;AAAA,MACpB,eAAe,CAAC,EAAE,MAAM,IAAI,QAAQ,GAAG,MAAM,YAAY,CAAC;AAAA,IAC5D;AAAA,IAGA,IAAI,SAAS,KAAK,UAAU,IAAI,GAAG;AAAA,MACjC,MAAM,kBAAkB,CAAC,EAAE,MAAM,UAAU,KAAK,CAAC;AAAA,IACnD;AAAA,IACA,QAAQ,KAAK,KAAK;AAAA,EACpB;AAAA,EAEA,IAAI,OAAO,GAAG,KAAK;AAAA,IACjB,QAAQ,KAAK;AAAA,MACX,QAAQ,IAAI,QAAQ;AAAA,MACpB,gBAAgB,CAAC,EAAE,MAAM,IAAI,YAAY,GAAG,MAAM,mBAAmB,CAAC;AAAA,MACtE,eAAe,CAAC,EAAE,MAAM,IAAI,GAAG,GAAG,MAAM,YAAY,CAAC;AAAA,IACvD,CAAC;AAAA,EACH;AAAA,EAEA,IAAI,OAAO,GAAG,IAAI,SAAS;AAAA,IACzB,QAAQ,KAAK;AAAA,MACX,QAAQ,IAAI,OAAO,GAAG,IAAI,KAAK;AAAA,MAC/B,gBAAgB;AAAA,QACd,EAAE,MAAM,IAAI,uBAAuB,GAAG,MAAM,mBAAmB;AAAA,MACjE;AAAA,MACA,eAAe,CAAC,EAAE,MAAM,IAAI,GAAG,GAAG,MAAM,YAAY,CAAC;AAAA,IACvD,CAAC;AAAA,EACH;AAAA,EACA,OAAO;AAAA;AAIF,IAAM,gBAAgB,CAAC,WAC5B,eAAe,MAAM,EAAE,SAAS;",
|
|
9
|
-
"debugId": "41C2FD41D67952F664756E2164756E21",
|
|
10
|
-
"names": []
|
|
11
|
-
}
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
// src/core/probe.ts
|
|
4
|
-
import pMap from "p-map";
|
|
5
|
-
var PROBE_CONCURRENCY = 8;
|
|
6
|
-
var PROBE_TIMEOUT_MS = 1e4;
|
|
7
|
-
var STATUS_NOT_FOUND = 404;
|
|
8
|
-
var STATUS_GONE = 410;
|
|
9
|
-
var STATUS_METHOD_NOT_ALLOWED = 405;
|
|
10
|
-
var STATUS_NOT_IMPLEMENTED = 501;
|
|
11
|
-
var request = async (url, method, timeoutMs) => {
|
|
12
|
-
const controller = new AbortController;
|
|
13
|
-
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
14
|
-
const started = performance.now();
|
|
15
|
-
try {
|
|
16
|
-
const response = await fetch(url, {
|
|
17
|
-
method,
|
|
18
|
-
redirect: "follow",
|
|
19
|
-
signal: controller.signal
|
|
20
|
-
});
|
|
21
|
-
return {
|
|
22
|
-
encoding: response.headers.get("content-encoding"),
|
|
23
|
-
finalUrl: response.url,
|
|
24
|
-
ms: Math.round(performance.now() - started),
|
|
25
|
-
ok: response.ok,
|
|
26
|
-
redirected: response.redirected,
|
|
27
|
-
robotsTag: response.headers.get("x-robots-tag"),
|
|
28
|
-
status: response.status
|
|
29
|
-
};
|
|
30
|
-
} catch (error) {
|
|
31
|
-
if (error instanceof Error && error.name === "AbortError") {
|
|
32
|
-
return { ok: false, timedOut: true };
|
|
33
|
-
}
|
|
34
|
-
return {
|
|
35
|
-
error: error instanceof Error ? error.message : String(error),
|
|
36
|
-
ok: false
|
|
37
|
-
};
|
|
38
|
-
} finally {
|
|
39
|
-
clearTimeout(timer);
|
|
40
|
-
}
|
|
41
|
-
};
|
|
42
|
-
var probe = async (url, options = {}) => {
|
|
43
|
-
const timeoutMs = options.timeoutMs ?? PROBE_TIMEOUT_MS;
|
|
44
|
-
const head = await request(url, "HEAD", timeoutMs);
|
|
45
|
-
const unreachable = !head.ok && head.status === undefined && !head.timedOut;
|
|
46
|
-
const retry = head.status === STATUS_METHOD_NOT_ALLOWED || head.status === STATUS_NOT_IMPLEMENTED || unreachable;
|
|
47
|
-
return retry ? await request(url, "GET", timeoutMs) : head;
|
|
48
|
-
};
|
|
49
|
-
var gradeExternal = (result) => {
|
|
50
|
-
if (result.ok) {
|
|
51
|
-
return null;
|
|
52
|
-
}
|
|
53
|
-
if (result.timedOut) {
|
|
54
|
-
return { detail: "request timed out", severity: "warning" };
|
|
55
|
-
}
|
|
56
|
-
if (result.status === undefined) {
|
|
57
|
-
return { detail: result.error ?? "unreachable", severity: "error" };
|
|
58
|
-
}
|
|
59
|
-
if (result.status === STATUS_NOT_FOUND || result.status === STATUS_GONE) {
|
|
60
|
-
return { detail: `HTTP ${result.status}`, severity: "error" };
|
|
61
|
-
}
|
|
62
|
-
return { detail: `HTTP ${result.status}`, severity: "warning" };
|
|
63
|
-
};
|
|
64
|
-
var probeAll = async (urls, options = {}) => {
|
|
65
|
-
const unique = [...new Set(urls)];
|
|
66
|
-
const entries = await pMap(unique, async (url) => [url, await probe(url, options)], { concurrency: Math.max(1, options.concurrency ?? PROBE_CONCURRENCY) });
|
|
67
|
-
return new Map(entries);
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
export { gradeExternal, probeAll };
|
|
71
|
-
|
|
72
|
-
//# debugId=A29226CDC8AC5EB464756E2164756E21
|
|
73
|
-
//# sourceMappingURL=chunk-vh9w1sgp.js.map
|