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.
Files changed (677) hide show
  1. package/AGENTS.md +19 -0
  2. package/CHANGELOG.md +227 -0
  3. package/README.md +34 -21
  4. package/dist/cli/chunk-11j0384y.js +148 -0
  5. package/dist/cli/chunk-11j0384y.js.map +10 -0
  6. package/dist/cli/{chunk-xhtpx3ff.js → chunk-1w8dp3qb.js} +17 -16
  7. package/dist/cli/{chunk-xhtpx3ff.js.map → chunk-1w8dp3qb.js.map} +3 -3
  8. package/dist/cli/chunk-2q1dwty4.js +75 -0
  9. package/dist/cli/chunk-2q1dwty4.js.map +11 -0
  10. package/dist/cli/chunk-41za066z.js +122 -0
  11. package/dist/cli/chunk-41za066z.js.map +11 -0
  12. package/dist/cli/chunk-5a2z0198.js +133 -0
  13. package/dist/cli/chunk-5a2z0198.js.map +10 -0
  14. package/dist/cli/{chunk-9he6crym.js → chunk-6k8vp3ta.js} +25 -13
  15. package/dist/cli/{chunk-9he6crym.js.map → chunk-6k8vp3ta.js.map} +4 -4
  16. package/dist/cli/{chunk-mt76t7dj.js → chunk-79njf86q.js} +133 -54
  17. package/dist/cli/chunk-79njf86q.js.map +11 -0
  18. package/dist/cli/{chunk-3w7b2vcx.js → chunk-7ez8ny0t.js} +2 -2
  19. package/dist/cli/{chunk-688e0dde.js → chunk-88cpgt6h.js} +1 -1
  20. package/dist/cli/chunk-a9kptbw5.js +361 -0
  21. package/dist/cli/chunk-a9kptbw5.js.map +14 -0
  22. package/dist/cli/chunk-abh8yjkn.js +31 -0
  23. package/dist/cli/chunk-abh8yjkn.js.map +10 -0
  24. package/dist/cli/chunk-b5aj94ah.js +91 -0
  25. package/dist/cli/chunk-b5aj94ah.js.map +10 -0
  26. package/dist/cli/{chunk-hs3gbh8p.js → chunk-bctazmbk.js} +9 -5
  27. package/dist/cli/chunk-bctazmbk.js.map +10 -0
  28. package/dist/cli/chunk-beat36xx.js +279 -0
  29. package/dist/cli/chunk-beat36xx.js.map +10 -0
  30. package/dist/cli/chunk-bnbmcwfb.js +145 -0
  31. package/dist/cli/chunk-bnbmcwfb.js.map +11 -0
  32. package/dist/cli/{chunk-9bkjd11x.js → chunk-bw22s759.js} +15 -5
  33. package/dist/cli/{chunk-9bkjd11x.js.map → chunk-bw22s759.js.map} +4 -4
  34. package/dist/cli/chunk-by2290sx.js +39 -0
  35. package/dist/cli/chunk-by2290sx.js.map +10 -0
  36. package/dist/cli/chunk-d1tadaw7.js +79 -0
  37. package/dist/cli/chunk-d1tadaw7.js.map +10 -0
  38. package/dist/cli/{chunk-t3tj0dgr.js → chunk-d80hr03s.js} +24 -19
  39. package/dist/cli/chunk-d80hr03s.js.map +15 -0
  40. package/dist/cli/chunk-ernrthtr.js +97 -0
  41. package/dist/cli/chunk-ernrthtr.js.map +10 -0
  42. package/dist/cli/chunk-f2972sbt.js +374 -0
  43. package/dist/cli/chunk-f2972sbt.js.map +10 -0
  44. package/dist/cli/{chunk-exeeb35e.js → chunk-f7t03s3g.js} +2 -2
  45. package/dist/cli/{chunk-2z47ypj8.js → chunk-fa25z98p.js} +16 -3
  46. package/dist/cli/chunk-fa25z98p.js.map +11 -0
  47. package/dist/cli/{chunk-12dxjqk7.js → chunk-fh5hj5jt.js} +44 -21
  48. package/dist/cli/chunk-fh5hj5jt.js.map +10 -0
  49. package/dist/cli/{chunk-8cd8tj54.js → chunk-j8mw0za6.js} +86 -57
  50. package/dist/cli/chunk-j8mw0za6.js.map +35 -0
  51. package/dist/cli/chunk-jts8mvcz.js +106 -0
  52. package/dist/cli/{chunk-2mzebbbz.js.map → chunk-jts8mvcz.js.map} +6 -4
  53. package/dist/cli/{chunk-ejjx8znq.js → chunk-mnqj32sj.js} +505 -536
  54. package/dist/cli/chunk-mnqj32sj.js.map +12 -0
  55. package/dist/cli/{chunk-196vjxp9.js → chunk-mwt1k8n7.js} +100 -372
  56. package/dist/cli/chunk-mwt1k8n7.js.map +10 -0
  57. package/dist/cli/chunk-nk3ts2xk.js +51 -0
  58. package/dist/cli/chunk-nk3ts2xk.js.map +10 -0
  59. package/dist/cli/{chunk-n9sra6sy.js → chunk-pat2zzwc.js} +10 -14
  60. package/dist/cli/{chunk-n9sra6sy.js.map → chunk-pat2zzwc.js.map} +2 -2
  61. package/dist/cli/chunk-pnnvybbk.js +176 -0
  62. package/dist/cli/chunk-pnnvybbk.js.map +11 -0
  63. package/dist/cli/{chunk-cvky9gb2.js → chunk-sqn5t4q0.js} +81 -87
  64. package/dist/cli/chunk-sqn5t4q0.js.map +10 -0
  65. package/dist/cli/{chunk-eevwt1sc.js → chunk-tzne8qfq.js} +15 -15
  66. package/dist/cli/{chunk-eevwt1sc.js.map → chunk-tzne8qfq.js.map} +1 -1
  67. package/dist/cli/chunk-xaz13gwg.js +12449 -0
  68. package/dist/cli/chunk-xaz13gwg.js.map +182 -0
  69. package/dist/cli/chunk-y3e45rc8.js +102 -0
  70. package/dist/cli/chunk-y3e45rc8.js.map +10 -0
  71. package/dist/cli/chunk-z01ze5c1.js +261 -0
  72. package/dist/cli/chunk-z01ze5c1.js.map +10 -0
  73. package/dist/cli/{chunk-5n7t497w.js → chunk-z1f5arsg.js} +247 -755
  74. package/dist/cli/chunk-z1f5arsg.js.map +36 -0
  75. package/dist/cli/{chunk-hdm2dkd2.js → chunk-zg2gtj10.js} +1086 -2596
  76. package/dist/cli/chunk-zg2gtj10.js.map +35 -0
  77. package/dist/cli/{chunk-ppfvdcd4.js → chunk-zxccj738.js} +1 -1
  78. package/dist/cli/index.js +214 -57
  79. package/dist/cli/index.js.map +8 -7
  80. package/dist/types/ai/agent-readability.d.ts +52 -0
  81. package/dist/types/ai/ai-catalog.d.ts +42 -0
  82. package/dist/types/ai/api/paths.d.ts +17 -0
  83. package/dist/types/ai/api-catalog.d.ts +18 -0
  84. package/dist/types/ai/ask.d.ts +368 -0
  85. package/dist/types/ai/changelog-markdown.d.ts +2 -0
  86. package/dist/types/ai/component-markdown.d.ts +2 -2
  87. package/dist/types/ai/index.d.ts +24 -0
  88. package/dist/types/ai/link-headers.d.ts +24 -0
  89. package/dist/types/ai/llms.d.ts +25 -0
  90. package/dist/types/ai/markdown.d.ts +45 -0
  91. package/dist/types/ai/mcp/discovery.d.ts +68 -0
  92. package/dist/types/ai/mcp/tools.d.ts +16 -0
  93. package/dist/types/ai/openapi-components.d.ts +43 -0
  94. package/dist/types/ai/relative-links.d.ts +26 -0
  95. package/dist/types/ai/serializers.d.ts +15 -0
  96. package/dist/types/ai/skills.d.ts +42 -0
  97. package/dist/types/ai/tar.d.ts +25 -0
  98. package/dist/types/ai/visibility.d.ts +17 -0
  99. package/dist/types/ai/web-bot-auth.d.ts +16 -0
  100. package/dist/types/analytics/adobe.d.ts +35 -0
  101. package/dist/types/analytics/amplitude.d.ts +50 -0
  102. package/dist/types/analytics/clarity.d.ts +31 -0
  103. package/dist/types/analytics/clearbit.d.ts +29 -0
  104. package/dist/types/analytics/cloudflare.d.ts +41 -0
  105. package/dist/types/analytics/fathom.d.ts +41 -0
  106. package/dist/types/analytics/google-analytics.d.ts +44 -0
  107. package/dist/types/analytics/google-tag-manager.d.ts +40 -0
  108. package/dist/types/analytics/head.d.ts +30 -0
  109. package/dist/types/analytics/heap.d.ts +40 -0
  110. package/dist/types/analytics/hightouch.d.ts +44 -0
  111. package/dist/types/analytics/hotjar.d.ts +33 -0
  112. package/dist/types/analytics/index.d.ts +61 -0
  113. package/dist/types/analytics/inline.d.ts +17 -0
  114. package/dist/types/analytics/logrocket.d.ts +44 -0
  115. package/dist/types/analytics/mixpanel.d.ts +67 -0
  116. package/dist/types/analytics/pirsch.d.ts +42 -0
  117. package/dist/types/analytics/plausible.d.ts +56 -0
  118. package/dist/types/analytics/posthog.d.ts +45 -0
  119. package/dist/types/analytics/schema.d.ts +320 -0
  120. package/dist/types/analytics/script.d.ts +46 -0
  121. package/dist/types/analytics/segment.d.ts +50 -0
  122. package/dist/types/analytics/vercel.d.ts +48 -0
  123. package/dist/types/astro/integration.d.ts +76 -0
  124. package/dist/types/astro/markdown-negotiation.d.ts +23 -0
  125. package/dist/types/astro/module-types.d.ts +14 -0
  126. package/dist/types/astro/pages.d.ts +44 -0
  127. package/dist/types/cli/env.d.ts +12 -0
  128. package/dist/types/cli/init/scaffold.d.ts +154 -0
  129. package/dist/types/components/layout/nav-utils.d.ts +11 -0
  130. package/dist/types/core/adapter.d.ts +47 -0
  131. package/dist/types/core/api-name.d.ts +7 -0
  132. package/dist/types/core/changelog-index.d.ts +13 -0
  133. package/dist/types/core/config-input.d.ts +209 -505
  134. package/dist/types/core/config.d.ts +60 -34
  135. package/dist/types/core/content-assets.d.ts +76 -0
  136. package/dist/types/core/custom-pages.d.ts +33 -0
  137. package/dist/types/core/data.d.ts +28 -11
  138. package/dist/types/core/define-components.d.ts +12 -9
  139. package/dist/types/core/deployment-env.d.ts +6 -11
  140. package/dist/types/core/frontmatter.d.ts +10 -0
  141. package/dist/types/core/graph.d.ts +18 -0
  142. package/dist/types/core/heading-markers.d.ts +54 -0
  143. package/dist/types/core/i18n-ui.d.ts +6 -2
  144. package/dist/types/core/i18n.d.ts +87 -0
  145. package/dist/types/core/includes.d.ts +138 -0
  146. package/dist/types/core/last-modified.d.ts +47 -0
  147. package/dist/types/core/links.d.ts +95 -0
  148. package/dist/types/core/locale-links.d.ts +60 -0
  149. package/dist/types/core/manifest.d.ts +17 -0
  150. package/dist/types/core/meta.d.ts +38 -0
  151. package/dist/types/core/nav-diagnostics.d.ts +26 -0
  152. package/dist/types/core/navigation.d.ts +6 -0
  153. package/dist/types/core/node-require.d.ts +19 -0
  154. package/dist/types/core/package-json.d.ts +13 -0
  155. package/dist/types/core/probe.d.ts +42 -0
  156. package/dist/types/core/project-graph.d.ts +51 -0
  157. package/dist/types/core/project.d.ts +2 -0
  158. package/dist/types/core/safe-href.d.ts +2 -0
  159. package/dist/types/core/safe-links.d.ts +26 -0
  160. package/dist/types/core/schema.d.ts +2291 -441
  161. package/dist/types/core/site-url.d.ts +16 -0
  162. package/dist/types/core/sources/assets.d.ts +36 -0
  163. package/dist/types/core/sources/cache.d.ts +37 -0
  164. package/dist/types/core/sources/collection.d.ts +28 -0
  165. package/dist/types/core/sources/contentful-rich-text.d.ts +31 -0
  166. package/dist/types/core/sources/contentful.d.ts +40 -0
  167. package/dist/types/core/sources/filesystem.d.ts +24 -0
  168. package/dist/types/core/sources/github-releases.d.ts +31 -0
  169. package/dist/types/core/sources/json.d.ts +30 -0
  170. package/dist/types/core/sources/lexical.d.ts +19 -0
  171. package/dist/types/core/sources/lower.d.ts +75 -0
  172. package/dist/types/core/sources/mdx-remote.d.ts +28 -0
  173. package/dist/types/core/sources/normalize.d.ts +147 -0
  174. package/dist/types/core/sources/notion.d.ts +131 -0
  175. package/dist/types/core/sources/obsidian.d.ts +46 -0
  176. package/dist/types/core/sources/payload.d.ts +39 -0
  177. package/dist/types/core/sources/portable-text.d.ts +42 -0
  178. package/dist/types/core/sources/read.d.ts +23 -0
  179. package/dist/types/core/sources/remote.d.ts +74 -0
  180. package/dist/types/core/sources/resolve.d.ts +19 -0
  181. package/dist/types/core/sources/sanity.d.ts +43 -0
  182. package/dist/types/core/sources/strapi-blocks.d.ts +12 -0
  183. package/dist/types/core/sources/strapi.d.ts +33 -0
  184. package/dist/types/core/sources/types.d.ts +7 -0
  185. package/dist/types/core/sources/watch.d.ts +45 -0
  186. package/dist/types/core/text-width.d.ts +11 -0
  187. package/dist/types/core/types.d.ts +20 -1
  188. package/dist/types/core/unrecognized-keys.d.ts +7 -0
  189. package/dist/types/core/versions.d.ts +72 -0
  190. package/dist/types/core/yaml.d.ts +9 -0
  191. package/dist/types/deploy/adapter-output.d.ts +45 -0
  192. package/dist/types/deploy/adapters/cloudflare.d.ts +40 -0
  193. package/dist/types/deploy/adapters/index.d.ts +29 -0
  194. package/dist/types/deploy/adapters/netlify.d.ts +37 -0
  195. package/dist/types/deploy/adapters/node.d.ts +37 -0
  196. package/dist/types/deploy/adapters/registry.d.ts +133 -0
  197. package/dist/types/deploy/adapters/types.d.ts +71 -0
  198. package/dist/types/deploy/adapters/vercel.d.ts +38 -0
  199. package/dist/types/deploy/artifacts.d.ts +65 -0
  200. package/dist/types/deploy/cloudflare-negotiation.d.ts +196 -0
  201. package/dist/types/deploy/function-bundle.d.ts +80 -0
  202. package/dist/types/deploy/headers.d.ts +50 -0
  203. package/dist/types/deploy/node-headers.d.ts +42 -0
  204. package/dist/types/deploy/platforms/cloudflare.d.ts +40 -0
  205. package/dist/types/deploy/platforms/index.d.ts +18 -0
  206. package/dist/types/deploy/platforms/netlify.d.ts +13 -0
  207. package/dist/types/deploy/platforms/node.d.ts +11 -0
  208. package/dist/types/deploy/platforms/paths.d.ts +27 -0
  209. package/dist/types/deploy/platforms/static.d.ts +10 -0
  210. package/dist/types/deploy/platforms/types.d.ts +104 -0
  211. package/dist/types/deploy/platforms/vercel.d.ts +32 -0
  212. package/dist/types/deploy/redirects.d.ts +53 -0
  213. package/dist/types/deploy/robots.d.ts +8 -0
  214. package/dist/types/deploy/rss.d.ts +31 -0
  215. package/dist/types/deploy/sitemap.d.ts +21 -0
  216. package/dist/types/deploy/vercel-negotiation.d.ts +109 -0
  217. package/dist/types/markdown/code-title.d.ts +32 -0
  218. package/dist/types/markdown/fence-meta.d.ts +23 -0
  219. package/dist/types/markdown/themes.d.ts +3 -3
  220. package/dist/types/openapi/asyncapi.d.ts +129 -0
  221. package/dist/types/openapi/graphql-build.d.ts +8 -0
  222. package/dist/types/openapi/graphql.d.ts +122 -0
  223. package/dist/types/openapi/model.d.ts +158 -0
  224. package/dist/types/openapi/parse.d.ts +57 -0
  225. package/dist/types/openapi/references.d.ts +37 -25
  226. package/dist/types/openapi/render-mdx.d.ts +33 -0
  227. package/dist/types/openapi/sentence.d.ts +7 -0
  228. package/dist/types/openapi/signature.d.ts +10 -0
  229. package/dist/types/openapi/source.d.ts +22 -0
  230. package/dist/types/openapi/spec-dependency-error.d.ts +10 -0
  231. package/dist/types/reference/asyncapi.d.ts +166 -0
  232. package/dist/types/reference/graphql.d.ts +181 -0
  233. package/dist/types/reference/index.d.ts +32 -0
  234. package/dist/types/reference/openapi.d.ts +165 -0
  235. package/dist/types/reference/options.d.ts +157 -0
  236. package/dist/types/reference/scalar.d.ts +136 -0
  237. package/dist/types/reference/schema.d.ts +630 -0
  238. package/dist/types/search/adapters/algolia.d.ts +32 -0
  239. package/dist/types/search/adapters/flexsearch.d.ts +12 -0
  240. package/dist/types/search/adapters/index.d.ts +31 -0
  241. package/dist/types/search/adapters/mixedbread.d.ts +22 -0
  242. package/dist/types/search/adapters/orama-cloud.d.ts +33 -0
  243. package/dist/types/search/adapters/orama.d.ts +13 -0
  244. package/dist/types/search/adapters/pagefind.d.ts +12 -0
  245. package/dist/types/search/adapters/registry.d.ts +228 -0
  246. package/dist/types/search/adapters/types.d.ts +34 -0
  247. package/dist/types/search/adapters/typesense.d.ts +42 -0
  248. package/dist/types/search/build.d.ts +23 -0
  249. package/dist/types/search/documents.d.ts +90 -0
  250. package/dist/types/search/facets.d.ts +3 -0
  251. package/dist/types/search/sync/algolia.d.ts +14 -0
  252. package/dist/types/search/sync/index.d.ts +14 -0
  253. package/dist/types/search/sync/orama-cloud.d.ts +10 -0
  254. package/dist/types/search/sync/typesense.d.ts +14 -0
  255. package/dist/types/sources/contentful.d.ts +68 -0
  256. package/dist/types/sources/custom.d.ts +20 -0
  257. package/dist/types/sources/filesystem.d.ts +42 -0
  258. package/dist/types/sources/github-releases.d.ts +46 -0
  259. package/dist/types/sources/index.d.ts +48 -0
  260. package/dist/types/sources/mdx-remote.d.ts +63 -0
  261. package/dist/types/sources/notion.d.ts +65 -0
  262. package/dist/types/sources/obsidian.d.ts +34 -0
  263. package/dist/types/sources/payload.d.ts +68 -0
  264. package/dist/types/sources/registry.d.ts +1414 -0
  265. package/dist/types/sources/sanity.d.ts +69 -0
  266. package/dist/types/sources/shared.d.ts +46 -0
  267. package/dist/types/sources/strapi.d.ts +66 -0
  268. package/dist/types/theme/icon-kind.d.ts +11 -0
  269. package/dist/types/theme/icons.d.ts +20 -0
  270. package/docs/01-quickstart.mdx +18 -18
  271. package/docs/02-deployment.mdx +50 -26
  272. package/docs/03-upgrading.mdx +351 -0
  273. package/docs/04-migrating.mdx +58 -0
  274. package/docs/08-faq.mdx +3 -3
  275. package/docs/advanced/blog.mdx +13 -6
  276. package/docs/advanced/changelog.mdx +23 -35
  277. package/docs/advanced/custom-pages.mdx +20 -8
  278. package/docs/advanced/meta.ts +1 -8
  279. package/docs/advanced/skills.mdx +8 -0
  280. package/docs/cli/audit.mdx +646 -0
  281. package/docs/cli/doctor.mdx +29 -0
  282. package/docs/{reference/eval.mdx → cli/evals.mdx} +9 -8
  283. package/docs/cli/index.mdx +105 -0
  284. package/docs/cli/meta.ts +7 -0
  285. package/docs/{reference → cli}/translate.mdx +1 -1
  286. package/docs/cli/validate.mdx +41 -0
  287. package/docs/cli/version.mdx +40 -0
  288. package/docs/configuration/analytics.mdx +350 -59
  289. package/docs/configuration/ask-ai.mdx +176 -61
  290. package/docs/configuration/customization.mdx +15 -9
  291. package/docs/configuration/index.mdx +52 -31
  292. package/docs/configuration/search.mdx +75 -54
  293. package/docs/configuration/theming.mdx +24 -15
  294. package/docs/content/components.mdx +21 -5
  295. package/docs/{reference → content}/frontmatter.mdx +37 -1
  296. package/docs/content/i18n.mdx +8 -6
  297. package/docs/content/includes.mdx +2 -4
  298. package/docs/content/index.mdx +1 -1
  299. package/docs/content/islands.mdx +10 -5
  300. package/docs/content/meta.mdx +1 -1
  301. package/docs/content/meta.ts +1 -0
  302. package/docs/content/navigation.mdx +12 -7
  303. package/docs/content/sources.mdx +145 -50
  304. package/docs/content/syntax.mdx +26 -12
  305. package/docs/content/versioning.mdx +3 -3
  306. package/docs/discoverability/agent-discovery.mdx +91 -10
  307. package/docs/discoverability/index.mdx +5 -5
  308. package/docs/discoverability/json-api.mdx +4 -4
  309. package/docs/discoverability/llms-txt.mdx +6 -6
  310. package/docs/discoverability/markdown.mdx +4 -4
  311. package/docs/discoverability/mcp.mdx +11 -11
  312. package/docs/discoverability/sitemap-and-robots.mdx +3 -3
  313. package/docs/index.mdx +2 -2
  314. package/docs/references/asyncapi.mdx +59 -0
  315. package/docs/{advanced → references}/graphql.mdx +45 -32
  316. package/docs/{reference → references}/meta.ts +2 -2
  317. package/docs/references/openapi.mdx +171 -0
  318. package/docs/references/scalar.mdx +64 -0
  319. package/package.json +42 -8
  320. package/skills/blume/SKILL.md +21 -8
  321. package/skills/blume-migrate/SKILL.md +22 -21
  322. package/skills/blume-migrate/assets/oxfmt@0.67.0.patch +49 -0
  323. package/skills/blume-migrate/references/docusaurus.md +5 -4
  324. package/skills/blume-migrate/references/fumadocs.md +4 -4
  325. package/skills/blume-migrate/references/mintlify.md +23 -8
  326. package/skills/blume-migrate/references/monorepo.md +6 -6
  327. package/skills/blume-migrate/references/starlight.md +4 -4
  328. package/src/ai/agent-readability.ts +26 -22
  329. package/src/ai/ai-catalog.ts +259 -0
  330. package/src/ai/api/handlers.ts +46 -11
  331. package/src/ai/api-catalog.ts +8 -8
  332. package/src/ai/ask-data.ts +1 -1
  333. package/src/ai/ask.ts +624 -100
  334. package/src/ai/changelog-markdown.ts +91 -0
  335. package/src/ai/component-markdown.ts +328 -12
  336. package/src/ai/index.ts +45 -0
  337. package/src/ai/link-headers.ts +19 -6
  338. package/src/ai/llms.ts +26 -15
  339. package/src/ai/markdown.ts +35 -5
  340. package/src/ai/mcp/data.ts +9 -5
  341. package/src/ai/mcp/discovery.ts +1 -1
  342. package/src/ai/openapi-components.ts +4 -1
  343. package/src/ai/relative-links.ts +170 -0
  344. package/src/ai/serializers.ts +2 -2
  345. package/src/ai/skills.ts +1 -1
  346. package/src/ai/web-bot-auth.ts +2 -2
  347. package/src/analytics/adobe.ts +46 -0
  348. package/src/analytics/amplitude.ts +79 -0
  349. package/src/analytics/clarity.ts +46 -0
  350. package/src/analytics/clearbit.ts +47 -0
  351. package/src/analytics/cloudflare.ts +67 -0
  352. package/src/analytics/fathom.ts +64 -0
  353. package/src/analytics/google-analytics.ts +84 -0
  354. package/src/analytics/google-tag-manager.ts +61 -0
  355. package/src/analytics/head.ts +130 -0
  356. package/src/analytics/heap.ts +65 -0
  357. package/src/analytics/hightouch.ts +77 -0
  358. package/src/analytics/hotjar.ts +47 -0
  359. package/src/analytics/index.ts +71 -0
  360. package/src/analytics/inline.ts +21 -0
  361. package/src/analytics/logrocket.ts +71 -0
  362. package/src/analytics/mixpanel.ts +92 -0
  363. package/src/analytics/pirsch.ts +66 -0
  364. package/src/analytics/plausible.ts +83 -0
  365. package/src/analytics/posthog.ts +78 -0
  366. package/src/analytics/schema.ts +60 -0
  367. package/src/analytics/script.ts +60 -0
  368. package/src/analytics/segment.ts +85 -0
  369. package/src/analytics/vercel.ts +50 -0
  370. package/src/astro/adapter-root.ts +7 -9
  371. package/src/astro/component-slots.ts +131 -91
  372. package/src/astro/generate.ts +114 -345
  373. package/src/astro/integration.ts +2 -6
  374. package/src/astro/pages.ts +13 -101
  375. package/src/astro/render-deps.ts +379 -0
  376. package/src/astro/runtime-deps.ts +201 -0
  377. package/src/astro/templates.ts +554 -541
  378. package/src/audit/agent.ts +24 -0
  379. package/src/audit/catalog.ts +2 -2
  380. package/src/audit/checks/assets.ts +2 -2
  381. package/src/audit/checks/dns-aid.ts +1 -1
  382. package/src/audit/checks/duplicates.ts +3 -1
  383. package/src/audit/checks/i18n.ts +1 -1
  384. package/src/audit/checks/indexability.ts +7 -7
  385. package/src/audit/checks/links.ts +2 -2
  386. package/src/audit/checks/llms.ts +6 -6
  387. package/src/audit/checks/network.ts +3 -3
  388. package/src/audit/checks/og-image.ts +2 -2
  389. package/src/audit/checks/robots.ts +1 -1
  390. package/src/audit/checks/sitemap.ts +2 -2
  391. package/src/audit/checks/social.ts +1 -1
  392. package/src/audit/run.ts +4 -3
  393. package/src/audit/terms.ts +31 -0
  394. package/src/audit/url.ts +13 -13
  395. package/src/cli/command-meta.ts +10 -0
  396. package/src/cli/commands/audit.ts +39 -20
  397. package/src/cli/commands/build.ts +71 -314
  398. package/src/cli/commands/check.ts +1 -0
  399. package/src/cli/commands/dev.ts +40 -1
  400. package/src/cli/commands/doctor.ts +90 -14
  401. package/src/cli/commands/eject.ts +44 -7
  402. package/src/cli/commands/eval.ts +2 -2
  403. package/src/cli/commands/init.ts +161 -41
  404. package/src/cli/commands/migrate.ts +121 -0
  405. package/src/cli/commands/preview.ts +7 -1
  406. package/src/cli/commands/translate.ts +2 -2
  407. package/src/cli/commands/upgrade.ts +141 -0
  408. package/src/cli/commands/version.ts +57 -44
  409. package/src/cli/eject-scripts.ts +121 -6
  410. package/src/cli/index.ts +11 -1
  411. package/src/cli/init/install.ts +70 -0
  412. package/src/cli/init/questions.ts +7 -0
  413. package/src/cli/init/scaffold.ts +459 -75
  414. package/src/cli/lazy-command.ts +37 -1
  415. package/src/cli/prepare.ts +40 -6
  416. package/src/cli/required-secrets.ts +38 -11
  417. package/src/cli/unknown-flags.ts +266 -0
  418. package/src/cli/yarn-pnp.ts +52 -0
  419. package/src/components/content/AccordionItem.astro +7 -1
  420. package/src/components/content/Card.astro +4 -3
  421. package/src/components/content/ColorItem.astro +22 -4
  422. package/src/components/content/GithubInfo.astro +2 -2
  423. package/src/components/content/Prompt.astro +25 -25
  424. package/src/components/content/Tabs.astro +3 -1
  425. package/src/components/content/Tile.astro +2 -3
  426. package/src/components/content/Tooltip.astro +57 -9
  427. package/src/components/content/content-strings.ts +34 -0
  428. package/src/components/content/diff.ts +1 -1
  429. package/src/components/content/mermaid-element.ts +13 -2
  430. package/src/components/content/prompt-markdown.ts +292 -0
  431. package/src/components/content/tooltip-id.ts +41 -0
  432. package/src/components/islands/hooks.ts +75 -3
  433. package/src/components/layout/Analytics.astro +21 -79
  434. package/src/components/layout/Banner.astro +3 -1
  435. package/src/components/layout/DiscoveryLinks.astro +69 -0
  436. package/src/components/layout/Header.astro +83 -20
  437. package/src/components/layout/LanguageSwitcher.astro +4 -1
  438. package/src/components/layout/Logo.astro +23 -2
  439. package/src/components/layout/NavSelector.astro +13 -2
  440. package/src/components/layout/NavTree.astro +12 -3
  441. package/src/components/layout/NavTreeScript.astro +17 -3
  442. package/src/components/layout/PageActions.astro +3 -3
  443. package/src/components/layout/PageFeedback.astro +11 -1
  444. package/src/components/layout/PageLayout.astro +52 -5
  445. package/src/components/layout/ReferenceLayout.astro +21 -12
  446. package/src/components/layout/RootLayout.astro +69 -43
  447. package/src/components/layout/Search.astro +30 -6
  448. package/src/components/layout/WebMcp.astro +1 -1
  449. package/src/components/layout/analytics-client.ts +101 -15
  450. package/src/components/layout/drawer-inert.ts +113 -15
  451. package/src/components/layout/dropdown-clamp.ts +105 -0
  452. package/src/components/layout/head-scripts.ts +15 -6
  453. package/src/components/layout/nav-utils.ts +17 -0
  454. package/src/components/layout/search/algolia.ts +8 -8
  455. package/src/components/layout/search/orama-cloud.ts +9 -7
  456. package/src/components/layout/search/typesense.ts +11 -17
  457. package/src/components/openapi/MessageComposer.astro +2 -2
  458. package/src/components/openapi/Playground.astro +2 -2
  459. package/src/components/openapi/playground-client.ts +79 -10
  460. package/src/core/changelog-index.ts +24 -0
  461. package/src/core/component-overrides.ts +399 -154
  462. package/src/core/config-input.ts +212 -543
  463. package/src/core/config.ts +130 -41
  464. package/src/core/custom-pages.ts +105 -0
  465. package/src/core/data.ts +32 -11
  466. package/src/core/define-components.ts +12 -9
  467. package/src/core/deployment-env.ts +18 -74
  468. package/src/core/diagnostics.ts +14 -7
  469. package/src/core/graph.ts +69 -25
  470. package/src/core/i18n-ui.ts +6 -2
  471. package/src/core/i18n.ts +17 -0
  472. package/src/core/includes.ts +156 -38
  473. package/src/core/last-modified.ts +6 -11
  474. package/src/core/links.ts +166 -2
  475. package/src/core/manifest.ts +10 -3
  476. package/src/core/navigation.ts +137 -19
  477. package/src/core/new-tab.ts +35 -0
  478. package/src/core/node-require.ts +21 -0
  479. package/src/core/project-graph.ts +42 -26
  480. package/src/core/project.ts +9 -4
  481. package/src/core/request-body.ts +61 -0
  482. package/src/core/safe-href.ts +28 -0
  483. package/src/core/safe-links.ts +68 -0
  484. package/src/core/schema.ts +531 -721
  485. package/src/core/server-features.ts +8 -9
  486. package/src/core/sources/assets.ts +47 -11
  487. package/src/core/sources/collection.ts +67 -0
  488. package/src/core/sources/contentful-rich-text.ts +285 -0
  489. package/src/core/sources/contentful.ts +173 -0
  490. package/src/core/sources/github-releases.ts +51 -1
  491. package/src/core/sources/json.ts +71 -0
  492. package/src/core/sources/lexical.ts +195 -0
  493. package/src/core/sources/lower.ts +226 -0
  494. package/src/core/sources/normalize.ts +52 -2
  495. package/src/core/sources/notion.ts +39 -28
  496. package/src/core/sources/payload.ts +135 -0
  497. package/src/core/sources/portable-text.ts +11 -16
  498. package/src/core/sources/remote.ts +226 -0
  499. package/src/core/sources/resolve.ts +104 -166
  500. package/src/core/sources/sanity.ts +16 -49
  501. package/src/core/sources/strapi-blocks.ts +124 -0
  502. package/src/core/sources/strapi.ts +191 -0
  503. package/src/core/sources/types.ts +12 -1
  504. package/src/core/types.ts +20 -1
  505. package/src/core/ui-packs/ar.ts +6 -2
  506. package/src/core/ui-packs/bg.ts +6 -2
  507. package/src/core/ui-packs/bn.ts +6 -2
  508. package/src/core/ui-packs/ca.ts +3 -1
  509. package/src/core/ui-packs/cs.ts +6 -2
  510. package/src/core/ui-packs/da.ts +6 -2
  511. package/src/core/ui-packs/de.ts +6 -2
  512. package/src/core/ui-packs/el.ts +3 -1
  513. package/src/core/ui-packs/es.ts +3 -1
  514. package/src/core/ui-packs/fa.ts +6 -2
  515. package/src/core/ui-packs/fi.ts +6 -2
  516. package/src/core/ui-packs/fr.ts +3 -1
  517. package/src/core/ui-packs/he.ts +6 -2
  518. package/src/core/ui-packs/hi.ts +6 -2
  519. package/src/core/ui-packs/hr.ts +6 -2
  520. package/src/core/ui-packs/hu.ts +6 -2
  521. package/src/core/ui-packs/id.ts +6 -2
  522. package/src/core/ui-packs/it.ts +3 -1
  523. package/src/core/ui-packs/ja.ts +3 -1
  524. package/src/core/ui-packs/ko.ts +3 -1
  525. package/src/core/ui-packs/nl.ts +6 -2
  526. package/src/core/ui-packs/no.ts +6 -2
  527. package/src/core/ui-packs/pl.ts +6 -2
  528. package/src/core/ui-packs/pt-br.ts +3 -1
  529. package/src/core/ui-packs/pt.ts +3 -1
  530. package/src/core/ui-packs/ro.ts +6 -2
  531. package/src/core/ui-packs/ru.ts +6 -2
  532. package/src/core/ui-packs/sk.ts +6 -2
  533. package/src/core/ui-packs/sr.ts +6 -2
  534. package/src/core/ui-packs/sv.ts +6 -2
  535. package/src/core/ui-packs/th.ts +3 -1
  536. package/src/core/ui-packs/tr.ts +6 -2
  537. package/src/core/ui-packs/uk.ts +6 -2
  538. package/src/core/ui-packs/vi.ts +3 -1
  539. package/src/core/ui-packs/zh-tw.ts +3 -1
  540. package/src/core/ui-packs/zh.ts +3 -1
  541. package/src/core/unrecognized-keys.ts +10 -0
  542. package/src/core/version-cut.ts +116 -8
  543. package/src/deploy/adapter-output.ts +57 -97
  544. package/src/deploy/adapters/cloudflare.ts +39 -0
  545. package/src/deploy/adapters/index.ts +41 -0
  546. package/src/deploy/adapters/netlify.ts +34 -0
  547. package/src/deploy/adapters/node.ts +34 -0
  548. package/src/deploy/adapters/registry.ts +127 -0
  549. package/src/deploy/adapters/types.ts +92 -0
  550. package/src/deploy/adapters/vercel.ts +35 -0
  551. package/src/deploy/artifacts.ts +67 -28
  552. package/src/deploy/cloudflare-negotiation.ts +179 -100
  553. package/src/deploy/function-bundle.ts +18 -3
  554. package/src/deploy/headers.ts +129 -22
  555. package/src/deploy/node-headers.ts +198 -0
  556. package/src/deploy/platforms/cloudflare.ts +312 -0
  557. package/src/deploy/platforms/index.ts +67 -0
  558. package/src/deploy/platforms/netlify.ts +52 -0
  559. package/src/deploy/platforms/node.ts +40 -0
  560. package/src/deploy/platforms/paths.ts +42 -0
  561. package/src/deploy/platforms/static.ts +29 -0
  562. package/src/deploy/platforms/types.ts +112 -0
  563. package/src/deploy/platforms/vercel.ts +193 -0
  564. package/src/deploy/redirects.ts +30 -18
  565. package/src/deploy/robots.ts +3 -3
  566. package/src/deploy/rss.ts +2 -2
  567. package/src/deploy/sitemap.ts +2 -2
  568. package/src/deploy/vercel-negotiation.ts +27 -4
  569. package/src/eval/agents.ts +32 -1
  570. package/src/eval/findings.ts +19 -11
  571. package/src/eval/report.ts +10 -2
  572. package/src/markdown/external-links.ts +65 -0
  573. package/src/markdown/include.ts +45 -27
  574. package/src/markdown/index.ts +34 -9
  575. package/src/markdown/inline-code.ts +12 -6
  576. package/src/markdown/relative-links.ts +324 -0
  577. package/src/markdown/themes.ts +3 -3
  578. package/src/migrate/migrate.ts +149 -0
  579. package/src/openapi/parse.ts +64 -16
  580. package/src/openapi/proxy.ts +62 -10
  581. package/src/openapi/references.ts +147 -147
  582. package/src/openapi/render-mdx.ts +32 -10
  583. package/src/openapi/scalar.ts +15 -13
  584. package/src/openapi/sentence.ts +14 -0
  585. package/src/openapi/source.ts +37 -21
  586. package/src/openapi/spec-dependency-error.ts +15 -0
  587. package/src/reference/asyncapi.ts +83 -0
  588. package/src/reference/graphql.ts +89 -0
  589. package/src/reference/index.ts +40 -0
  590. package/src/reference/openapi.ts +83 -0
  591. package/src/reference/options.ts +201 -0
  592. package/src/reference/scalar.ts +136 -0
  593. package/src/reference/schema.ts +88 -0
  594. package/src/registry/eject.ts +97 -42
  595. package/src/search/adapters/algolia.ts +46 -0
  596. package/src/search/adapters/flexsearch.ts +29 -0
  597. package/src/search/adapters/index.ts +39 -0
  598. package/src/search/adapters/mixedbread.ts +39 -0
  599. package/src/search/adapters/orama-cloud.ts +51 -0
  600. package/src/search/adapters/orama.ts +24 -0
  601. package/src/search/adapters/pagefind.ts +27 -0
  602. package/src/search/adapters/registry.ts +131 -0
  603. package/src/search/adapters/types.ts +46 -0
  604. package/src/search/adapters/typesense.ts +57 -0
  605. package/src/search/build.ts +33 -7
  606. package/src/search/documents.ts +6 -0
  607. package/src/search/sync/algolia.ts +12 -11
  608. package/src/search/sync/index.ts +35 -20
  609. package/src/search/sync/orama-cloud.ts +12 -9
  610. package/src/search/sync/typesense.ts +15 -13
  611. package/src/sources/contentful.ts +63 -0
  612. package/src/sources/custom.ts +38 -0
  613. package/src/sources/filesystem.ts +51 -0
  614. package/src/sources/github-releases.ts +52 -0
  615. package/src/sources/index.ts +60 -0
  616. package/src/sources/mdx-remote.ts +76 -0
  617. package/src/sources/notion.ts +63 -0
  618. package/src/sources/obsidian.ts +38 -0
  619. package/src/sources/payload.ts +60 -0
  620. package/src/sources/registry.ts +182 -0
  621. package/src/sources/sanity.ts +66 -0
  622. package/src/sources/shared.ts +52 -0
  623. package/src/sources/strapi.ts +58 -0
  624. package/src/theme/entry.ts +47 -2
  625. package/src/translate/report.ts +40 -7
  626. package/src/upgrade/upgrade.ts +499 -0
  627. package/dist/cli/chunk-12dxjqk7.js.map +0 -10
  628. package/dist/cli/chunk-196vjxp9.js.map +0 -13
  629. package/dist/cli/chunk-2mzebbbz.js +0 -69
  630. package/dist/cli/chunk-2z47ypj8.js.map +0 -11
  631. package/dist/cli/chunk-30e87n55.js +0 -108
  632. package/dist/cli/chunk-30e87n55.js.map +0 -10
  633. package/dist/cli/chunk-450a7rcr.js +0 -185
  634. package/dist/cli/chunk-450a7rcr.js.map +0 -11
  635. package/dist/cli/chunk-5n7t497w.js.map +0 -40
  636. package/dist/cli/chunk-61j18dwk.js +0 -5342
  637. package/dist/cli/chunk-61j18dwk.js.map +0 -58
  638. package/dist/cli/chunk-88by27n5.js +0 -17
  639. package/dist/cli/chunk-88by27n5.js.map +0 -10
  640. package/dist/cli/chunk-8cd8tj54.js.map +0 -34
  641. package/dist/cli/chunk-aztttvb3.js +0 -381
  642. package/dist/cli/chunk-aztttvb3.js.map +0 -12
  643. package/dist/cli/chunk-cvky9gb2.js.map +0 -11
  644. package/dist/cli/chunk-ejjx8znq.js.map +0 -15
  645. package/dist/cli/chunk-fmceyezb.js +0 -1007
  646. package/dist/cli/chunk-fmceyezb.js.map +0 -13
  647. package/dist/cli/chunk-hdm2dkd2.js.map +0 -48
  648. package/dist/cli/chunk-hs3gbh8p.js.map +0 -10
  649. package/dist/cli/chunk-jbj4qhfw.js +0 -30
  650. package/dist/cli/chunk-jbj4qhfw.js.map +0 -10
  651. package/dist/cli/chunk-mqb2ka8m.js +0 -68
  652. package/dist/cli/chunk-mqb2ka8m.js.map +0 -10
  653. package/dist/cli/chunk-mt76t7dj.js.map +0 -11
  654. package/dist/cli/chunk-q4rae3bg.js +0 -60
  655. package/dist/cli/chunk-q4rae3bg.js.map +0 -10
  656. package/dist/cli/chunk-ra1v2nc2.js +0 -35
  657. package/dist/cli/chunk-ra1v2nc2.js.map +0 -10
  658. package/dist/cli/chunk-t3tj0dgr.js.map +0 -15
  659. package/dist/cli/chunk-tqa1s0k8.js +0 -69
  660. package/dist/cli/chunk-tqa1s0k8.js.map +0 -11
  661. package/dist/cli/chunk-vh9w1sgp.js +0 -73
  662. package/dist/cli/chunk-vh9w1sgp.js.map +0 -10
  663. package/dist/cli/chunk-vkrsvbr5.js +0 -107
  664. package/dist/cli/chunk-vkrsvbr5.js.map +0 -11
  665. package/dist/cli/chunk-vrfp10qk.js +0 -81
  666. package/dist/cli/chunk-vrfp10qk.js.map +0 -10
  667. package/dist/cli/chunk-wjt80jps.js +0 -1049
  668. package/dist/cli/chunk-wjt80jps.js.map +0 -24
  669. package/docs/advanced/api-reference.mdx +0 -240
  670. package/docs/reference/cli.mdx +0 -197
  671. package/skills/blume-migrate/assets/oxfmt@0.55.0.patch +0 -20
  672. package/src/components/content/changelog-element.ts +0 -69
  673. package/src/search/providers.ts +0 -91
  674. /package/dist/cli/{chunk-3w7b2vcx.js.map → chunk-7ez8ny0t.js.map} +0 -0
  675. /package/dist/cli/{chunk-688e0dde.js.map → chunk-88cpgt6h.js.map} +0 -0
  676. /package/dist/cli/{chunk-exeeb35e.js.map → chunk-f7t03s3g.js.map} +0 -0
  677. /package/dist/cli/{chunk-ppfvdcd4.js.map → chunk-zxccj738.js.map} +0 -0
@@ -0,0 +1,193 @@
1
+ import { existsSync } from "node:fs";
2
+ import { readFile, writeFile } from "node:fs/promises";
3
+
4
+ import { join } from "pathe";
5
+
6
+ import { crossOriginDiscoveryPaths } from "../../ai/ai-catalog.ts";
7
+ import {
8
+ API_CATALOG_PATH,
9
+ API_CATALOG_TYPE,
10
+ hasApiCatalog,
11
+ } from "../../ai/api-catalog.ts";
12
+ import { buildHomeLinkHeader } from "../../ai/link-headers.ts";
13
+ import {
14
+ agentMarkdown,
15
+ buildRawMarkdown,
16
+ markdownRoutePaths,
17
+ markdownTokenCount,
18
+ } from "../../ai/markdown.ts";
19
+ import {
20
+ SIGNATURES_DIRECTORY_PATH,
21
+ SIGNATURES_DIRECTORY_TYPE,
22
+ } from "../../ai/web-bot-auth.ts";
23
+ import type { BlumeProject } from "../../core/project-graph.ts";
24
+ import type { ProjectContext } from "../../core/types.ts";
25
+ import { VERCEL_ADAPTER_PACKAGE } from "../adapters/vercel.ts";
26
+ import {
27
+ addDevDependencyCommand,
28
+ auditVercelFunctions,
29
+ blumeDependencyNames,
30
+ functionBundleVerdict,
31
+ } from "../function-bundle.ts";
32
+ import { buildVercelConfig } from "../redirects.ts";
33
+ import { injectNegotiationRoutes } from "../vercel-negotiation.ts";
34
+ import { adapterRoot, toSiteUrl } from "./paths.ts";
35
+ import type { BuildLog, DeployPlatform, RedirectFile } from "./types.ts";
36
+
37
+ /** `vercel.json` with a `redirects` array, for a static deploy of `dist/`. */
38
+ export const VERCEL_JSON_FILE: RedirectFile = {
39
+ build: buildVercelConfig,
40
+ name: "vercel.json",
41
+ };
42
+
43
+ /**
44
+ * The Build Output tree. The adapter is shown the project root (see
45
+ * `hiddenRuntime.showProjectRoot`), so for a real build this is
46
+ * `<project>/.vercel/output`; an isolated build keeps it under the relocated
47
+ * runtime.
48
+ */
49
+ const buildOutputDir = (context: ProjectContext): string =>
50
+ join(adapterRoot(context), ".vercel", "output");
51
+
52
+ /**
53
+ * Refuse to ship a function bundle that would crash at runtime: a bare import
54
+ * the adapter's dependency trace silently dropped (see
55
+ * `deploy/function-bundle.ts`). A missing package that is one of Blume's own
56
+ * dependencies is fatal — the generated runtime imports it, so every request
57
+ * would die; a project's own external import is reported as a warning and
58
+ * left to the author. Resolves to whether the bundle may ship.
59
+ */
60
+ export const checkVercelFunctionBundles = async (
61
+ outputDir: string,
62
+ root: string,
63
+ log: BuildLog
64
+ ): Promise<boolean> => {
65
+ const audits = await auditVercelFunctions(outputDir);
66
+ const own = blumeDependencyNames();
67
+ // The remedy names the project's own package manager (`pnpm add -D`, …).
68
+ const addDevCommand = await addDevDependencyCommand(root);
69
+ let fatal = false;
70
+ for (const audit of audits) {
71
+ const verdict = functionBundleVerdict(audit, root, own, addDevCommand);
72
+ if (verdict.fatal) {
73
+ fatal = true;
74
+ log.error(verdict.message);
75
+ } else {
76
+ log.warn(verdict.message);
77
+ }
78
+ }
79
+ return !fatal;
80
+ };
81
+
82
+ /**
83
+ * Splice `Accept: text/markdown` negotiation routes into the adapter's Build
84
+ * Output config, so a content-page request that prefers Markdown gets the
85
+ * page's prerendered `.md` mirror (content pages are prerendered even in
86
+ * server output, so Astro middleware never sees them — the routing layer is
87
+ * the only request-time hook). The adapter writes the config straight to the
88
+ * root it was shown.
89
+ */
90
+ export const emitVercelNegotiation = async (
91
+ project: BlumeProject,
92
+ log: BuildLog
93
+ ): Promise<void> => {
94
+ const { config, context } = project;
95
+ const outputDir = buildOutputDir(context);
96
+ const configPath = join(outputDir, "config.json");
97
+ if (!existsSync(configPath)) {
98
+ return;
99
+ }
100
+ const routePaths = markdownRoutePaths(project);
101
+ const overrides: Record<string, string> = {};
102
+ if (hasApiCatalog(config)) {
103
+ overrides[API_CATALOG_PATH.slice(1)] = API_CATALOG_TYPE;
104
+ }
105
+ if (config.agents.webBotAuth.keys.length > 0) {
106
+ overrides[SIGNATURES_DIRECTORY_PATH.slice(1)] = SIGNATURES_DIRECTORY_TYPE;
107
+ }
108
+ // The homepage rewrite serves `/index.md` from the static layer, so its
109
+ // `x-markdown-tokens` estimate has to ride the routing config; the runtime
110
+ // endpoint stamps it on dev/server-rendered responses itself.
111
+ const rawMarkdown = await buildRawMarkdown(project);
112
+ const home = rawMarkdown["/"];
113
+ // The Markdown and JSON 404 routes point at the prerendered twins; only
114
+ // wire each when the build actually emitted it (a project that owns `/404`
115
+ // gets none).
116
+ const staticDir = join(outputDir, "static");
117
+ const injected = injectNegotiationRoutes(
118
+ await readFile(configPath, "utf-8"),
119
+ routePaths,
120
+ buildHomeLinkHeader(config, routePaths),
121
+ overrides,
122
+ home ? markdownTokenCount(agentMarkdown(home)) : undefined,
123
+ {
124
+ json: existsSync(join(staticDir, "404.json")),
125
+ markdown: existsSync(join(staticDir, "404.md")),
126
+ },
127
+ crossOriginDiscoveryPaths(config)
128
+ );
129
+ if (injected === null) {
130
+ log.warn(
131
+ "Could not wire Accept: text/markdown negotiation into .vercel/output/config.json — raw Markdown stays available at the .md URLs."
132
+ );
133
+ return;
134
+ }
135
+ await writeFile(configPath, injected, "utf-8");
136
+ log.success(
137
+ "Wired Accept: text/markdown negotiation into the Vercel routing config"
138
+ );
139
+ };
140
+
141
+ /**
142
+ * Vercel. A server build's Build Output tree lands at `.vercel/output` — at
143
+ * the project root, because the adapter is handed that root up front: its
144
+ * `@vercel/nft` dependency trace is rooted there too, and tracing from the
145
+ * hidden runtime silently drops the function's chunks and `node_modules`.
146
+ * Static assets are served from the tree's `static/` half, so the deploy
147
+ * artifacts are written there; headers arrive through the routing config
148
+ * rather than a `_headers` file, which Vercel never reads.
149
+ */
150
+ export const vercelPlatform: DeployPlatform = {
151
+ astro: {
152
+ config: {},
153
+ options: () => ({}),
154
+ package: VERCEL_ADAPTER_PACKAGE,
155
+ },
156
+ env: {
157
+ detect: (env) => Boolean(env.VERCEL),
158
+ // The stable production domain wins over the per-deployment preview URL
159
+ // so the inferred origin (sitemap, OG, RSS) stays put across deploys;
160
+ // the chain falls through per resolved value, so an empty
161
+ // VERCEL_PROJECT_PRODUCTION_URL doesn't dead-end it.
162
+ site: (env) =>
163
+ toSiteUrl(env.VERCEL_PROJECT_PRODUCTION_URL) ?? toSiteUrl(env.VERCEL_URL),
164
+ },
165
+ finalizeBuild: async ({ isolated, log, project }) => {
166
+ const { context } = project;
167
+ const ok = await checkVercelFunctionBundles(
168
+ buildOutputDir(context),
169
+ context.root,
170
+ log
171
+ );
172
+ if (!ok) {
173
+ return false;
174
+ }
175
+ // An isolated verify only proves the bundle would ship; the routing
176
+ // config is a deploy artifact and stays untouched.
177
+ if (!isolated) {
178
+ await emitVercelNegotiation(project, log);
179
+ }
180
+ return true;
181
+ },
182
+ hiddenRuntime: {
183
+ ignoreDir: ".vercel/",
184
+ showProjectRoot: true,
185
+ surfacePath: null,
186
+ },
187
+ kind: "vercel",
188
+ negotiatesMarkdown: true,
189
+ readsHeaderFiles: { server: false, static: false },
190
+ redirectFiles: [VERCEL_JSON_FILE],
191
+ serverOutputDir: buildOutputDir,
192
+ serverStaticDir: (context) => join(buildOutputDir(context), "static"),
193
+ };
@@ -4,13 +4,14 @@ import {
4
4
  withComposedBasePath,
5
5
  } from "../core/base-path.ts";
6
6
  import type { ResolvedConfig } from "../core/schema.ts";
7
+ import type { VercelHeader } from "./headers.ts";
7
8
 
8
9
  /**
9
10
  * Platform redirect files for a static build. Astro already emits redirect HTML
10
- * (meta-refresh) pages for `deployment.output: "static"`, but that's a soft
11
- * client redirect. These give the host a real HTTP 3xx: Netlify/Cloudflare read
12
- * `_redirects`, Vercel reads `vercel.json`, and `blume-redirects.json` is a
13
- * structured manifest for anything else (Apache/nginx rules, an edge worker).
11
+ * (meta-refresh) pages for static output, but that's a soft client redirect.
12
+ * These give the host a real HTTP 3xx: Netlify/Cloudflare read `_redirects`,
13
+ * Vercel reads `vercel.json`, and `blume-redirects.json` is a structured
14
+ * manifest for anything else (Apache/nginx rules, an edge worker).
14
15
  */
15
16
 
16
17
  type Redirect = ResolvedConfig["redirects"][number];
@@ -78,7 +79,7 @@ export const platformRedirects = (config: ResolvedConfig): Redirect[] =>
78
79
  applyBaseToPlatformRedirects(
79
80
  config.redirects,
80
81
  config.basePath,
81
- config.deployment.base ?? ""
82
+ config.deployment.options.base ?? ""
82
83
  );
83
84
 
84
85
  /** `_redirects` text (Netlify + Cloudflare Pages): `from to status` per line. */
@@ -87,24 +88,35 @@ export const buildNetlifyRedirects = (redirects: Redirect[]): string =>
87
88
  .map((redirect) => `${redirect.from} ${redirect.to} ${redirect.status}`)
88
89
  .join("\n")}\n`;
89
90
 
91
+ /** The `vercel.json` Blume writes for a static deploy of `dist/`. */
92
+ interface VercelConfig {
93
+ headers?: readonly VercelHeader[];
94
+ redirects: { destination: string; source: string; statusCode: number }[];
95
+ }
96
+
90
97
  /**
91
- * `vercel.json` contents with a `redirects` array. Uses `statusCode` (Vercel's
98
+ * `vercel.json` contents with a `redirects` array, and a `headers` array when
99
+ * header rules are given (see `buildVercelHeaders`). Uses `statusCode` (Vercel's
92
100
  * alternative to the boolean `permanent`) so the configured code ships exactly:
93
101
  * `permanent` would silently coerce a 301 to 308 and a 302 to 307, diverging
94
102
  * from the `_redirects` file, which preserves exact codes.
95
103
  */
96
- export const buildVercelConfig = (redirects: Redirect[]): string =>
97
- `${JSON.stringify(
98
- {
99
- redirects: redirects.map((redirect) => ({
100
- destination: redirect.to,
101
- source: redirect.from,
102
- statusCode: redirect.status,
103
- })),
104
- },
105
- null,
106
- 2
107
- )}\n`;
104
+ export const buildVercelConfig = (
105
+ redirects: Redirect[],
106
+ headers: readonly VercelHeader[] = []
107
+ ): string => {
108
+ const config: VercelConfig = {
109
+ redirects: redirects.map((redirect) => ({
110
+ destination: redirect.to,
111
+ source: redirect.from,
112
+ statusCode: redirect.status,
113
+ })),
114
+ };
115
+ if (headers.length > 0) {
116
+ config.headers = headers;
117
+ }
118
+ return `${JSON.stringify(config, null, 2)}\n`;
119
+ };
108
120
 
109
121
  /** Structured manifest for hosts that need manual wiring. */
110
122
  export const buildRedirectManifest = (redirects: Redirect[]): string =>
@@ -41,16 +41,16 @@ export const buildRobots = (project: BlumeProject): string | null => {
41
41
  }
42
42
 
43
43
  const lines = ["User-agent: *"];
44
- const signal = contentSignalLine(config.seo.contentSignals);
44
+ const signal = contentSignalLine(config.agents.contentSignals);
45
45
  if (signal) {
46
46
  lines.push(signal);
47
47
  }
48
48
  lines.push("Allow: /");
49
49
 
50
- const { site } = config.deployment;
50
+ const { site } = config.deployment.options;
51
51
  if (site && config.seo.sitemap) {
52
52
  const sitemapPath = withBasePath(
53
- normalizeBasePath(config.deployment.base),
53
+ normalizeBasePath(config.deployment.options.base),
54
54
  "/sitemap.xml"
55
55
  );
56
56
  lines.push("", `Sitemap: ${absoluteUrl(site, sitemapPath)}`);
package/src/deploy/rss.ts CHANGED
@@ -52,7 +52,7 @@ const pageDate = (page: PageRecord): Date | undefined => {
52
52
  export const buildRssFeeds = (project: BlumeProject): RssFeed[] => {
53
53
  const { config } = project;
54
54
  const { rss } = config.seo;
55
- const { site } = config.deployment;
55
+ const { site } = config.deployment.options;
56
56
  if (!(rss.enabled && site)) {
57
57
  return [];
58
58
  }
@@ -60,7 +60,7 @@ export const buildRssFeeds = (project: BlumeProject): RssFeed[] => {
60
60
  // Routes carry `basePath`; a `deployment.base` subdirectory is layered on top.
61
61
  // The feed's own `link`/self URL points at the docs root under that base, while
62
62
  // `path` stays base-less (it's also the on-disk output location).
63
- const deployBase = normalizeBasePath(config.deployment.base);
63
+ const deployBase = normalizeBasePath(config.deployment.options.base);
64
64
  const rootLink = `${base}${deployBase}`;
65
65
 
66
66
  const feeds: RssFeed[] = [];
@@ -72,14 +72,14 @@ ${urls.join("\n")}
72
72
  export const buildSitemapFiles = (
73
73
  project: BlumeProject
74
74
  ): SitemapFile[] | null => {
75
- const { site } = project.config.deployment;
75
+ const { site } = project.config.deployment.options;
76
76
  if (!(site && project.config.seo.sitemap)) {
77
77
  return null;
78
78
  }
79
79
 
80
80
  const base = siteRoot(site);
81
81
  // Routes carry `basePath`; a `deployment.base` subdirectory is layered on top.
82
- const deployBase = normalizeBasePath(project.config.deployment.base);
82
+ const deployBase = normalizeBasePath(project.config.deployment.options.base);
83
83
 
84
84
  // Archived-version pages leave the sitemap when the version is noindexed,
85
85
  // or when their canonical points at a still-existing latest equivalent —
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * `Accept: text/markdown` content negotiation for Vercel server builds.
3
3
  *
4
- * Blume prerenders every content page — even under `deployment.output:
5
- * "server"` — so a page request never reaches Astro middleware: Vercel serves
4
+ * Blume prerenders every content page — even in a server build (`deployment:
5
+ * vercel()`) — so a page request never reaches Astro middleware: Vercel serves
6
6
  * the prerendered HTML straight from its static layer. Request-time negotiation
7
7
  * therefore has to live in the platform's routing config. The Vercel adapter
8
8
  * emits a Build Output API `config.json`; these helpers splice extra routes
@@ -235,6 +235,26 @@ export const buildNegotiationRoutes = (
235
235
  /** The `src` of the injected homepage `Link` header route. */
236
236
  const HOME_SRC = "^/$";
237
237
 
238
+ const ALLOW_ANY_ORIGIN = "*";
239
+
240
+ /**
241
+ * A main-phase `continue` route stamping `Access-Control-Allow-Origin: *` on
242
+ * one static discovery document (see `crossOriginDiscoveryPaths`), so a
243
+ * registry reading it from another origin isn't refused by the browser.
244
+ */
245
+ const corsRoute = (path: string): VercelRoute => ({
246
+ continue: true,
247
+ headers: { "access-control-allow-origin": ALLOW_ANY_ORIGIN },
248
+ src: `^${routePattern(path)}$`,
249
+ });
250
+
251
+ /** Whether a route is a `corsRoute` — the same three-field shape test as the others. */
252
+ const isCorsRoute = (route: VercelRoute): boolean =>
253
+ route.continue === true &&
254
+ route.headers?.["access-control-allow-origin"] === ALLOW_ANY_ORIGIN &&
255
+ isString(route.src) &&
256
+ Object.keys(route).length === 3;
257
+
238
258
  /**
239
259
  * Whether a route is one this module previously injected, so re-injection
240
260
  * replaces rather than duplicates. Rewrites are identified by their `accept`
@@ -258,7 +278,8 @@ const isNegotiationRoute = (route: VercelRoute): boolean =>
258
278
  (route.continue === true &&
259
279
  isString(route.headers?.link) &&
260
280
  route.src === HOME_SRC &&
261
- Object.keys(route).length === 3);
281
+ Object.keys(route).length === 3) ||
282
+ isCorsRoute(route);
262
283
 
263
284
  /**
264
285
  * Splice the negotiation routes into a Build Output `config.json`, plus — when
@@ -287,7 +308,8 @@ export const injectNegotiationRoutes = (
287
308
  homeLinkHeader?: string | null,
288
309
  contentTypeOverrides?: Record<string, string>,
289
310
  homeTokens?: number,
290
- notFound: NotFoundVariants = {}
311
+ notFound: NotFoundVariants = {},
312
+ corsPaths: readonly string[] = []
291
313
  ): string | null => {
292
314
  const overrideEntries = Object.entries(contentTypeOverrides ?? {});
293
315
  let config: {
@@ -325,6 +347,7 @@ export const injectNegotiationRoutes = (
325
347
  src: HOME_SRC,
326
348
  });
327
349
  }
350
+ headerRoutes.push(...corsPaths.map(corsRoute));
328
351
  // Headers first: `continue` routes accumulate, so a request the rewrite
329
352
  // route then terminates (Markdown negotiation on the homepage) still carries
330
353
  // the Link header.
@@ -48,6 +48,8 @@ export interface HeadlessResult {
48
48
 
49
49
  export interface HeadlessOptions {
50
50
  cwd: string;
51
+ /** How long the SIGTERM gets before SIGKILL follows (default 5s). */
52
+ killGraceMs?: number;
51
53
  prompt: string;
52
54
  timeoutMs: number;
53
55
  }
@@ -89,10 +91,14 @@ export const runAgentHeadless = (
89
91
  stderr += chunk.toString("utf-8");
90
92
  });
91
93
 
94
+ let hardKill: ReturnType<typeof setTimeout> | undefined;
92
95
  const deadline = setTimeout(() => {
93
96
  timedOut = true;
94
97
  child.kill("SIGTERM");
95
- const hardKill = setTimeout(() => child.kill("SIGKILL"), KILL_GRACE_MS);
98
+ hardKill = setTimeout(
99
+ () => child.kill("SIGKILL"),
100
+ options.killGraceMs ?? KILL_GRACE_MS
101
+ );
96
102
  hardKill.unref();
97
103
  }, options.timeoutMs);
98
104
  deadline.unref();
@@ -109,6 +115,9 @@ export const runAgentHeadless = (
109
115
  // (an MCP server, a shell) can hold open past the SIGTERM. A timed-out
110
116
  // run's output is discarded anyway, so the process dying is enough.
111
117
  child.once("exit", (code) => {
118
+ // Once the process is gone the SIGKILL follow-up has nothing to do, and
119
+ // firing it later could signal an unrelated process that reused the pid.
120
+ clearTimeout(hardKill);
112
121
  if (timedOut) {
113
122
  clearTimeout(deadline);
114
123
  resolve({ code: code ?? 1, stderr, stdout, timedOut });
@@ -197,6 +206,27 @@ const claudeArgs = (context: InvocationContext): string[] => {
197
206
  ];
198
207
  };
199
208
 
209
+ /**
210
+ * Codex config overrides that leave an eval run nothing but its prompt and the
211
+ * docs MCP tools. `--sandbox read-only` blocks writes and the network but still
212
+ * lets the shell tool read any file the user can, and the docs a reader
213
+ * searches — or the answer a judge grades — can come from a remote source, so
214
+ * an instruction planted there could otherwise pull a local secret into the
215
+ * transcript sent to the model provider. With both command tools and the
216
+ * local-image tool off, and any subprocess started with no inherited
217
+ * environment, there is nothing on the machine for a run to read.
218
+ */
219
+ const CODEX_LOCKDOWN = [
220
+ "-c",
221
+ "features.shell_tool=false",
222
+ "-c",
223
+ "features.unified_exec=false",
224
+ "-c",
225
+ "tools.view_image=false",
226
+ "-c",
227
+ 'shell_environment_policy.inherit="none"',
228
+ ];
229
+
200
230
  const codexArgs = (context: InvocationContext): string[] => {
201
231
  const base = [
202
232
  "exec",
@@ -205,6 +235,7 @@ const codexArgs = (context: InvocationContext): string[] => {
205
235
  "--ephemeral",
206
236
  "--sandbox",
207
237
  "read-only",
238
+ ...CODEX_LOCKDOWN,
208
239
  "--output-last-message",
209
240
  context.lastMessagePath,
210
241
  ];
@@ -3,7 +3,7 @@ import type { Diagnostic } from "../core/types.ts";
3
3
  import { locateQuestion } from "./schema.ts";
4
4
  import type { EvalQuestion } from "./schema.ts";
5
5
 
6
- const DOCS_URL = "https://useblume.dev/docs/reference/eval";
6
+ const DOCS_URL = "https://useblume.dev/docs/cli/evals";
7
7
 
8
8
  /** Where a finding should anchor when no route hint matches a page. */
9
9
  export interface EvalsAnchor {
@@ -58,9 +58,12 @@ export interface QuestionOutcome {
58
58
  }
59
59
 
60
60
  /**
61
- * The diagnostic for a failed or errored question, anchored to the page that
62
- * should have answered it (via the first matching route hint) or, failing
63
- * that, to the question's line in the evals file.
61
+ * The diagnostic for a failed or errored question. A failure is anchored to
62
+ * the page that should have answered it (via the first matching route hint)
63
+ * or, failing that, to the question's line in the evals file. An errored run —
64
+ * the agent crashed, timed out, or answered in a shape Blume couldn't read —
65
+ * says nothing about the docs, so it always points at the question instead of
66
+ * a page there's nothing to fix in.
64
67
  */
65
68
  export const questionFinding = (
66
69
  question: EvalQuestion,
@@ -68,25 +71,30 @@ export const questionFinding = (
68
71
  project: BlumeProject,
69
72
  anchor: EvalsAnchor
70
73
  ): Diagnostic => {
71
- const route = hintedRoute(question, project);
72
- const site = route
73
- ? { file: route.sourcePath, url: route.path }
74
- : { file: anchor.path, line: locateQuestion(anchor.raw, question.id) };
74
+ const questionSite = {
75
+ file: anchor.path,
76
+ line: locateQuestion(anchor.raw, question.id),
77
+ };
75
78
 
76
79
  if (outcome.status === "error") {
77
80
  return {
78
81
  code: "BLUME_EVAL_QUESTION_ERROR",
79
82
  docsUrl: DOCS_URL,
80
- message: `Eval run failed for "${question.question}"${
83
+ message: `The agent run failed for "${question.question}"${
81
84
  outcome.detail ? ` — ${outcome.detail}` : ""
82
- }.`,
85
+ }, so the docs weren't graded.`,
83
86
  severity: question.severity,
84
87
  suggestion:
85
88
  "Rerun `blume eval`; if it persists, check the agent CLI installation and the failure detail.",
86
- ...site,
89
+ ...questionSite,
87
90
  };
88
91
  }
89
92
 
93
+ const route = hintedRoute(question, project);
94
+ const site = route
95
+ ? { file: route.sourcePath, url: route.path }
96
+ : questionSite;
97
+
90
98
  const missing =
91
99
  outcome.missing.length > 0
92
100
  ? ` — missing: ${outcome.missing.join("; ")}`
@@ -94,7 +94,11 @@ export const headerLine = (total: number, agent: EvalResult["agent"]): string =>
94
94
  export const startLine = (id: string, index: number, total: number): string =>
95
95
  ` ${colors.dim(`▸ ${id} (${index + 1}/${total})`)}`;
96
96
 
97
- /** `fix:` pointers for failed questions, naming the file that resolves each. */
97
+ /**
98
+ * `fix:` pointers for failed questions, naming the file that resolves each. A
99
+ * question whose agent run errored gets a `run failed:` line pointing at the
100
+ * question instead: the run never graded the docs, so there's no page to fix.
101
+ */
98
102
  export const fixLines = (result: EvalResult, root: string): string[] =>
99
103
  result.diagnostics
100
104
  .filter((diagnostic) => diagnostic.code !== "BLUME_EVAL_ROUTE_UNKNOWN")
@@ -102,7 +106,11 @@ export const fixLines = (result: EvalResult, root: string): string[] =>
102
106
  const site = finding.file
103
107
  ? `${relative(root, finding.file)}${finding.line ? `:${finding.line}` : ""}`
104
108
  : "";
105
- return ` ${colors.cyan("fix:")} ${site} ${colors.dim(finding.message)}`;
109
+ const label =
110
+ finding.code === "BLUME_EVAL_QUESTION_ERROR"
111
+ ? colors.red("run failed:")
112
+ : colors.cyan("fix:");
113
+ return ` ${label} ${site} ${colors.dim(finding.message)}`;
106
114
  });
107
115
 
108
116
  /** Dim warnings for route hints that no longer match a page. */
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Opens external Markdown links in a new tab (`markdown.externalLinks`). A
3
+ * Satteri hast plugin: every `<a>` whose href passes the shared
4
+ * `isExternalUrl` predicate — the one behind the header actions and featured
5
+ * sidebar links — gets `target="_blank"`, `rel="noreferrer"`, an
6
+ * `aria-describedby` pointing at the layout's hidden "Opens in a new tab"
7
+ * element, and a `data-blume-external` marker the theme draws the arrow icon
8
+ * from. So a Markdown link and a chrome link to the same place behave alike.
9
+ *
10
+ * Site routes, fragments, relative paths, and other schemes (`mailto:`,
11
+ * `tel:`) stay in the current tab. Raw `<a>` tags written in Markdown, and JSX
12
+ * or components in MDX, keep whatever attributes their author gave them. Only
13
+ * constructed when the option is on (see `markdown/index.ts`).
14
+ */
15
+
16
+ import { isExternalUrl } from "../core/base-path.ts";
17
+ import { NEW_TAB_HINT_ID } from "../core/new-tab.ts";
18
+
19
+ /** A hast property value: an attribute primitive or a token list. */
20
+ type HastPropertyValue = string | number | boolean | (string | number)[];
21
+
22
+ /** A minimal hast node (avoids a hast type dependency). */
23
+ interface HastNode {
24
+ properties?: Record<string, HastPropertyValue>;
25
+ tagName?: string;
26
+ type: string;
27
+ }
28
+
29
+ /**
30
+ * The slice of Satteri's hast visitor context this plugin needs. Satteri
31
+ * serializes an unchanged node by identity, so attributes are recorded via
32
+ * `setProperty` rather than by mutating `node.properties`.
33
+ */
34
+ interface HastContext {
35
+ setProperty: (node: HastNode, key: string, value: HastPropertyValue) => void;
36
+ }
37
+
38
+ /** A Satteri hast plugin, typed structurally to avoid a Satteri dep. */
39
+ export interface ExternalLinksPlugin {
40
+ name: string;
41
+ element: {
42
+ filter: string[];
43
+ visit: (node: HastNode, ctx: HastContext) => void;
44
+ };
45
+ }
46
+
47
+ /** Only a string href can be tested; hast allows numbers and token lists. */
48
+ const isHref = (value: HastPropertyValue | undefined): value is string =>
49
+ typeof value === "string";
50
+
51
+ export const externalLinksPlugin = (): ExternalLinksPlugin => ({
52
+ element: {
53
+ filter: ["a"],
54
+ visit(node, ctx) {
55
+ const href = node.properties?.href;
56
+ if (isHref(href) && isExternalUrl(href)) {
57
+ ctx.setProperty(node, "target", "_blank");
58
+ ctx.setProperty(node, "rel", ["noreferrer"]);
59
+ ctx.setProperty(node, "ariaDescribedBy", [NEW_TAB_HINT_ID]);
60
+ ctx.setProperty(node, "dataBlumeExternal", "");
61
+ }
62
+ },
63
+ },
64
+ name: "blume:external-links",
65
+ });