blume 2.0.1 → 2.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (492) hide show
  1. package/CHANGELOG.md +147 -0
  2. package/dist/cli/{chunk-qwsrynx5.js → chunk-1d7ve1dm.js} +38 -19
  3. package/dist/cli/{chunk-qwsrynx5.js.map → chunk-1d7ve1dm.js.map} +4 -4
  4. package/dist/cli/{chunk-s6jhgk0q.js → chunk-2eytanqx.js} +2 -2
  5. package/dist/cli/{chunk-kdp5q7ke.js → chunk-2hsdwb9n.js} +18 -19
  6. package/dist/cli/{chunk-kdp5q7ke.js.map → chunk-2hsdwb9n.js.map} +2 -2
  7. package/dist/cli/{chunk-hdpx1tax.js → chunk-2z928egk.js} +5 -5
  8. package/dist/cli/{chunk-jwyddg7y.js → chunk-35d4wj9f.js} +30 -24
  9. package/dist/cli/chunk-35d4wj9f.js.map +15 -0
  10. package/dist/cli/{chunk-ah61y8py.js → chunk-364znk6q.js} +2 -2
  11. package/dist/cli/{chunk-jts8mvcz.js → chunk-3em5wd2y.js} +25 -6
  12. package/dist/cli/{chunk-jts8mvcz.js.map → chunk-3em5wd2y.js.map} +3 -3
  13. package/dist/cli/{chunk-s1p84fyh.js → chunk-5f86nr5m.js} +63 -22
  14. package/dist/cli/chunk-5f86nr5m.js.map +11 -0
  15. package/dist/cli/{chunk-2hn4b8z7.js → chunk-5m5nmvyq.js} +170 -76
  16. package/dist/cli/chunk-5m5nmvyq.js.map +13 -0
  17. package/dist/cli/{chunk-epjnccmv.js → chunk-5xvm6tfj.js} +18 -15
  18. package/dist/cli/chunk-5xvm6tfj.js.map +10 -0
  19. package/dist/cli/{chunk-fz5wtpmh.js → chunk-6dsbexzp.js} +18 -15
  20. package/dist/cli/chunk-6dsbexzp.js.map +10 -0
  21. package/dist/cli/{chunk-vtk4a6dg.js → chunk-8ktnccpt.js} +1 -1
  22. package/dist/cli/{chunk-6hsn950k.js → chunk-9t7a85s3.js} +178 -48
  23. package/dist/cli/chunk-9t7a85s3.js.map +10 -0
  24. package/dist/cli/{chunk-fxypxtvm.js → chunk-a58773jm.js} +2 -2
  25. package/dist/cli/{chunk-mb2919y2.js → chunk-acanzt5p.js} +17 -6
  26. package/dist/cli/chunk-acanzt5p.js.map +10 -0
  27. package/dist/cli/{chunk-27g6wdth.js → chunk-akbpwfxc.js} +90 -26
  28. package/dist/cli/chunk-akbpwfxc.js.map +10 -0
  29. package/dist/cli/{chunk-wm7js3j9.js → chunk-b07cmahc.js} +2 -2
  30. package/dist/cli/{chunk-wgm7m9qk.js → chunk-c8chx29p.js} +179 -51
  31. package/dist/cli/chunk-c8chx29p.js.map +36 -0
  32. package/dist/cli/{chunk-qs4q5p4e.js → chunk-crgn1q09.js} +32 -14
  33. package/dist/cli/chunk-crgn1q09.js.map +10 -0
  34. package/dist/cli/chunk-e04dxsz1.js +39 -0
  35. package/dist/cli/chunk-e04dxsz1.js.map +10 -0
  36. package/dist/cli/{chunk-yt5n7ppj.js → chunk-ey84smr6.js} +17 -7
  37. package/dist/cli/chunk-ey84smr6.js.map +10 -0
  38. package/dist/cli/{chunk-f2z5v128.js → chunk-g4hq16wv.js} +14 -15
  39. package/dist/cli/{chunk-f2z5v128.js.map → chunk-g4hq16wv.js.map} +2 -2
  40. package/dist/cli/{chunk-fa25z98p.js → chunk-ga0pf4aj.js} +9 -8
  41. package/dist/cli/chunk-ga0pf4aj.js.map +11 -0
  42. package/dist/cli/{chunk-kpf8rrjc.js → chunk-hm3vjy5s.js} +109 -58
  43. package/dist/cli/chunk-hm3vjy5s.js.map +19 -0
  44. package/dist/cli/{chunk-fs23ddbb.js → chunk-j85vccga.js} +625 -750
  45. package/dist/cli/chunk-j85vccga.js.map +36 -0
  46. package/dist/cli/{chunk-ch6g3ar0.js → chunk-p3v96n38.js} +6 -6
  47. package/dist/cli/{chunk-ch6g3ar0.js.map → chunk-p3v96n38.js.map} +3 -3
  48. package/dist/cli/{chunk-q5163e60.js → chunk-p73c0m7w.js} +21 -19
  49. package/dist/cli/chunk-p73c0m7w.js.map +11 -0
  50. package/dist/cli/{chunk-dh8cwk36.js → chunk-pehfxfta.js} +24 -9
  51. package/dist/cli/chunk-pehfxfta.js.map +10 -0
  52. package/dist/cli/{chunk-qkqwkpte.js → chunk-pv29h0wf.js} +3688 -1313
  53. package/dist/cli/chunk-pv29h0wf.js.map +190 -0
  54. package/dist/cli/{chunk-6vm74dry.js → chunk-q58y5e6a.js} +10 -10
  55. package/dist/cli/{chunk-6vm74dry.js.map → chunk-q58y5e6a.js.map} +3 -3
  56. package/dist/cli/{chunk-zxcczpyx.js → chunk-r20tn01b.js} +1 -1
  57. package/dist/cli/{chunk-m3vmjgmq.js → chunk-r9rcc4w7.js} +16 -8
  58. package/dist/cli/chunk-r9rcc4w7.js.map +10 -0
  59. package/dist/cli/{chunk-5shv93fd.js → chunk-tkacnehg.js} +2 -2
  60. package/dist/cli/{chunk-zxh4d9vy.js → chunk-tzmab476.js} +4 -4
  61. package/dist/cli/{chunk-yw7dm696.js → chunk-vg9r4eb9.js} +24 -11
  62. package/dist/cli/chunk-vg9r4eb9.js.map +14 -0
  63. package/dist/cli/{chunk-79jhk4py.js → chunk-wrr3j9w9.js} +260 -132
  64. package/dist/cli/chunk-wrr3j9w9.js.map +35 -0
  65. package/dist/cli/{chunk-6crbhc3x.js → chunk-yfyb25rh.js} +54 -27
  66. package/dist/cli/chunk-yfyb25rh.js.map +14 -0
  67. package/dist/cli/index.js +162 -35
  68. package/dist/cli/index.js.map +4 -4
  69. package/dist/types/ai/agent-surface.d.ts +32 -0
  70. package/dist/types/ai/api-catalog.d.ts +7 -1
  71. package/dist/types/ai/ask-context.d.ts +7 -0
  72. package/dist/types/ai/component-markdown.d.ts +4 -4
  73. package/dist/types/ai/link-headers.d.ts +8 -1
  74. package/dist/types/ai/openapi-components.d.ts +5 -2
  75. package/dist/types/ai/relative-links.d.ts +11 -4
  76. package/dist/types/ai/skills.d.ts +4 -1
  77. package/dist/types/ai/static-expression.d.ts +28 -0
  78. package/dist/types/ai/tar.d.ts +1 -3
  79. package/dist/types/analytics/databuddy.d.ts +43 -0
  80. package/dist/types/analytics/index.d.ts +4 -0
  81. package/dist/types/analytics/one-dollar-stats.d.ts +48 -0
  82. package/dist/types/analytics/schema.d.ts +28 -0
  83. package/dist/types/astro/integration.d.ts +3 -2
  84. package/dist/types/cli/env.d.ts +5 -0
  85. package/dist/types/cli/init/scaffold.d.ts +19 -3
  86. package/dist/types/cli/init/starter-spec.d.ts +11 -0
  87. package/dist/types/core/base-path.d.ts +24 -1
  88. package/dist/types/core/config-input.d.ts +13 -11
  89. package/dist/types/core/config.d.ts +2 -2
  90. package/dist/types/core/directive-diagnostics.d.ts +12 -0
  91. package/dist/types/core/graph.d.ts +2 -0
  92. package/dist/types/core/heading-markers.d.ts +5 -7
  93. package/dist/types/core/i18n-ui.d.ts +31 -0
  94. package/dist/types/core/i18n.d.ts +9 -1
  95. package/dist/types/core/last-modified.d.ts +10 -0
  96. package/dist/types/core/links.d.ts +3 -1
  97. package/dist/types/core/load-module.d.ts +10 -0
  98. package/dist/types/core/locale-links.d.ts +12 -2
  99. package/dist/types/core/meta.d.ts +13 -1
  100. package/dist/types/core/nav-diagnostics.d.ts +10 -0
  101. package/dist/types/core/navigation.d.ts +38 -0
  102. package/dist/types/core/ordering-prefix.d.ts +4 -0
  103. package/dist/types/core/safe-links.d.ts +3 -1
  104. package/dist/types/core/schema.d.ts +59 -13
  105. package/dist/types/core/sources/github-releases.d.ts +5 -0
  106. package/dist/types/core/sources/lower.d.ts +38 -13
  107. package/dist/types/core/sources/normalize.d.ts +23 -2
  108. package/dist/types/core/sources/remote.d.ts +11 -1
  109. package/dist/types/core/sources/resolve.d.ts +12 -0
  110. package/dist/types/core/sources/types.d.ts +31 -0
  111. package/dist/types/core/sources/watch.d.ts +12 -5
  112. package/dist/types/core/standard-schema.d.ts +5 -0
  113. package/dist/types/core/types.d.ts +9 -0
  114. package/dist/types/deploy/adapters/node.d.ts +5 -2
  115. package/dist/types/deploy/adapters/types.d.ts +7 -0
  116. package/dist/types/deploy/artifacts.d.ts +6 -4
  117. package/dist/types/deploy/cloudflare-negotiation.d.ts +3 -2
  118. package/dist/types/deploy/headers.d.ts +36 -7
  119. package/dist/types/deploy/node-headers.d.ts +43 -8
  120. package/dist/types/deploy/platforms/netlify.d.ts +27 -2
  121. package/dist/types/deploy/platforms/node.d.ts +6 -5
  122. package/dist/types/deploy/platforms/types.d.ts +15 -0
  123. package/dist/types/deploy/platforms/vercel.d.ts +3 -2
  124. package/dist/types/deploy/redirects.d.ts +31 -15
  125. package/dist/types/deploy/vercel-negotiation.d.ts +3 -2
  126. package/dist/types/markdown/directives.d.ts +62 -0
  127. package/dist/types/markdown/features.d.ts +21 -0
  128. package/dist/types/markdown/mdast.d.ts +63 -0
  129. package/dist/types/openapi/asyncapi.d.ts +4 -2
  130. package/dist/types/openapi/model.d.ts +20 -6
  131. package/dist/types/search/sync/algolia.d.ts +3 -1
  132. package/docs/01-quickstart.mdx +3 -2
  133. package/docs/02-deployment.mdx +20 -9
  134. package/docs/08-faq.mdx +10 -3
  135. package/docs/advanced/changelog.mdx +1 -1
  136. package/docs/advanced/custom-pages.mdx +7 -5
  137. package/docs/cli/audit.mdx +19 -3
  138. package/docs/cli/doctor.mdx +2 -2
  139. package/docs/cli/evals.mdx +4 -4
  140. package/docs/cli/index.mdx +4 -1
  141. package/docs/cli/translate.mdx +4 -4
  142. package/docs/cli/version.mdx +1 -1
  143. package/docs/configuration/analytics.mdx +42 -2
  144. package/docs/configuration/assistant.mdx +1 -1
  145. package/docs/configuration/customization.mdx +6 -3
  146. package/docs/configuration/index.mdx +5 -3
  147. package/docs/configuration/search.mdx +2 -2
  148. package/docs/content/components.mdx +2 -2
  149. package/docs/content/frontmatter.mdx +5 -1
  150. package/docs/content/i18n.mdx +3 -1
  151. package/docs/content/index.mdx +8 -4
  152. package/docs/content/islands.mdx +1 -1
  153. package/docs/content/meta.mdx +7 -3
  154. package/docs/content/navigation.mdx +29 -4
  155. package/docs/content/sources.mdx +18 -16
  156. package/docs/content/syntax.mdx +14 -0
  157. package/docs/content/versioning.mdx +2 -1
  158. package/docs/discoverability/agent-discovery.mdx +22 -8
  159. package/docs/discoverability/index.mdx +4 -3
  160. package/docs/discoverability/llms-txt.mdx +2 -5
  161. package/docs/discoverability/markdown.mdx +6 -4
  162. package/docs/discoverability/mcp.mdx +4 -0
  163. package/docs/discoverability/metadata.mdx +3 -2
  164. package/docs/discoverability/open-graph.mdx +8 -4
  165. package/docs/discoverability/rss.mdx +4 -2
  166. package/docs/references/asyncapi.mdx +2 -2
  167. package/docs/references/graphql.mdx +2 -2
  168. package/docs/references/openapi.mdx +6 -4
  169. package/package.json +1 -1
  170. package/skills/blume-migrate/SKILL.md +6 -6
  171. package/skills/blume-migrate/references/docusaurus.md +6 -6
  172. package/skills/blume-migrate/references/fumadocs.md +1 -1
  173. package/skills/blume-migrate/references/mintlify.md +3 -3
  174. package/skills/blume-migrate/references/monorepo.md +1 -1
  175. package/skills/blume-migrate/references/nextra.md +2 -2
  176. package/skills/blume-migrate/references/starlight.md +5 -5
  177. package/skills/blume-migrate/scripts/mintlify-codemod.mjs +9 -4
  178. package/skills/blume-update-docs/references/audit-checklist.md +1 -1
  179. package/src/ai/agent-readability.ts +2 -2
  180. package/src/ai/agent-surface.ts +56 -0
  181. package/src/ai/ai-catalog.ts +6 -2
  182. package/src/ai/api/handlers.ts +2 -2
  183. package/src/ai/api/spec.ts +17 -4
  184. package/src/ai/api-catalog.ts +13 -3
  185. package/src/ai/ask-context.ts +14 -2
  186. package/src/ai/ask-data.ts +26 -12
  187. package/src/ai/changelog-markdown.ts +2 -2
  188. package/src/ai/component-markdown.ts +43 -37
  189. package/src/ai/link-headers.ts +22 -8
  190. package/src/ai/llms.ts +22 -10
  191. package/src/ai/markdown.ts +23 -11
  192. package/src/ai/mcp/discovery.ts +2 -2
  193. package/src/ai/mcp/query.ts +2 -2
  194. package/src/ai/mcp/server.ts +80 -9
  195. package/src/ai/openapi-components.ts +22 -6
  196. package/src/ai/relative-links.ts +99 -15
  197. package/src/ai/serializers.ts +2 -1
  198. package/src/ai/skills.ts +14 -1
  199. package/src/ai/static-expression.ts +416 -0
  200. package/src/ai/tar.ts +139 -12
  201. package/src/ai/visibility.ts +45 -14
  202. package/src/analytics/databuddy.ts +67 -0
  203. package/src/analytics/head.ts +8 -0
  204. package/src/analytics/index.ts +7 -0
  205. package/src/analytics/one-dollar-stats.ts +86 -0
  206. package/src/analytics/posthog.ts +21 -3
  207. package/src/analytics/schema.ts +4 -0
  208. package/src/astro/generate.ts +72 -28
  209. package/src/astro/include-hmr.ts +31 -12
  210. package/src/astro/include-refresh.ts +19 -8
  211. package/src/astro/integration.ts +108 -14
  212. package/src/astro/runtime-modules.ts +28 -13
  213. package/src/astro/templates.ts +139 -57
  214. package/src/audit/catalog.ts +2 -2
  215. package/src/audit/checks/assets.ts +25 -5
  216. package/src/audit/checks/content.ts +20 -2
  217. package/src/audit/checks/i18n.ts +46 -8
  218. package/src/audit/checks/indexability.ts +39 -19
  219. package/src/audit/checks/links.ts +22 -1
  220. package/src/audit/checks/llms.ts +6 -3
  221. package/src/audit/checks/network.ts +3 -1
  222. package/src/audit/checks/og-image.ts +10 -0
  223. package/src/audit/checks/robots.ts +6 -1
  224. package/src/audit/checks/sitemap.ts +56 -31
  225. package/src/audit/checks/social.ts +21 -2
  226. package/src/audit/crawl.ts +88 -15
  227. package/src/audit/graph.ts +3 -1
  228. package/src/audit/report.ts +54 -17
  229. package/src/audit/run.ts +13 -9
  230. package/src/audit/snapshot.ts +5 -0
  231. package/src/audit/types.ts +18 -0
  232. package/src/audit/url.ts +37 -6
  233. package/src/cli/args.ts +32 -0
  234. package/src/cli/build-failure.ts +50 -0
  235. package/src/cli/commands/audit.ts +11 -1
  236. package/src/cli/commands/build.ts +19 -5
  237. package/src/cli/commands/check.ts +2 -0
  238. package/src/cli/commands/doctor.ts +3 -1
  239. package/src/cli/commands/eval.ts +20 -18
  240. package/src/cli/commands/init.ts +15 -5
  241. package/src/cli/commands/preview.ts +15 -0
  242. package/src/cli/commands/sync.ts +2 -0
  243. package/src/cli/commands/translate.ts +18 -18
  244. package/src/cli/commands/upgrade.ts +11 -0
  245. package/src/cli/commands/validate.ts +3 -1
  246. package/src/cli/dev-lock.ts +157 -37
  247. package/src/cli/eject-scripts.ts +32 -7
  248. package/src/cli/env.ts +12 -1
  249. package/src/cli/init/scaffold.ts +117 -11
  250. package/src/cli/init/starter-spec.ts +235 -0
  251. package/src/cli/report-format.ts +11 -6
  252. package/src/components/colors.ts +19 -0
  253. package/src/components/content/AccordionItem.astro +26 -22
  254. package/src/components/content/Badge.astro +7 -12
  255. package/src/components/content/Card.astro +2 -2
  256. package/src/components/content/Component.astro +11 -5
  257. package/src/components/content/Expandable.astro +5 -1
  258. package/src/components/content/Frame.astro +2 -7
  259. package/src/components/content/GithubInfo.astro +12 -2
  260. package/src/components/content/Prompt.astro +2 -7
  261. package/src/components/content/Tab.astro +0 -1
  262. package/src/components/content/Tabs.astro +58 -5
  263. package/src/components/content/Tile.astro +1 -1
  264. package/src/components/content/Tooltip.astro +69 -7
  265. package/src/components/content/Tree.astro +7 -2
  266. package/src/components/content/TypeTable.astro +10 -5
  267. package/src/components/content/Update.astro +8 -2
  268. package/src/components/content/auto-type-table.ts +4 -1
  269. package/src/components/content/badge-color.ts +20 -0
  270. package/src/components/content/base-href.ts +14 -22
  271. package/src/components/content/inline-markdown.ts +27 -7
  272. package/src/components/copy-feedback.ts +35 -8
  273. package/src/components/islands/assistant.tsx +37 -6
  274. package/src/components/islands/base-path.ts +47 -10
  275. package/src/components/islands/hooks.ts +42 -21
  276. package/src/components/islands/webmcp.ts +16 -10
  277. package/src/components/layout/Banner.astro +23 -4
  278. package/src/components/layout/Breadcrumbs.astro +5 -2
  279. package/src/components/layout/DiscoveryLinks.astro +9 -5
  280. package/src/components/layout/Header.astro +23 -10
  281. package/src/components/layout/LanguageSwitcher.astro +2 -2
  282. package/src/components/layout/Logo.astro +5 -0
  283. package/src/components/layout/NavSelector.astro +8 -3
  284. package/src/components/layout/NavTabMenu.astro +133 -0
  285. package/src/components/layout/NavTree.astro +31 -12
  286. package/src/components/layout/NavTreeCache.astro +5 -2
  287. package/src/components/layout/NavTreeScript.astro +45 -5
  288. package/src/components/layout/PageActions.astro +4 -3
  289. package/src/components/layout/PageLayout.astro +28 -13
  290. package/src/components/layout/Pagination.astro +3 -3
  291. package/src/components/layout/ReferenceLayout.astro +4 -1
  292. package/src/components/layout/RootLayout.astro +25 -12
  293. package/src/components/layout/Search.astro +38 -14
  294. package/src/components/layout/VersionBanner.astro +2 -2
  295. package/src/components/layout/analytics-client.ts +14 -0
  296. package/src/components/layout/toc-active.ts +41 -0
  297. package/src/components/layout/toc-element.ts +8 -14
  298. package/src/components/openapi/ApiTagOperations.astro +2 -2
  299. package/src/components/openapi/AsyncApiOperation.astro +7 -4
  300. package/src/components/openapi/GraphqlChip.astro +2 -2
  301. package/src/components/openapi/GraphqlType.astro +11 -3
  302. package/src/components/openapi/MessageComposer.astro +1 -1
  303. package/src/components/openapi/Operation.astro +23 -5
  304. package/src/components/openapi/PanelTabs.astro +4 -1
  305. package/src/components/openapi/Playground.astro +8 -2
  306. package/src/components/openapi/RequestPanel.astro +13 -6
  307. package/src/components/openapi/SchemaProperty.astro +11 -33
  308. package/src/components/openapi/SchemaTable.astro +34 -52
  309. package/src/components/openapi/async.ts +38 -6
  310. package/src/components/openapi/helpers.ts +100 -12
  311. package/src/components/openapi/message-composer.ts +14 -1
  312. package/src/components/openapi/message-model.ts +12 -2
  313. package/src/components/openapi/message.ts +21 -3
  314. package/src/components/openapi/operation-model.ts +119 -17
  315. package/src/components/openapi/panel.ts +31 -5
  316. package/src/components/openapi/param-style.ts +181 -0
  317. package/src/components/openapi/playground-client.ts +110 -23
  318. package/src/components/openapi/playground-schema.ts +25 -6
  319. package/src/components/openapi/request.ts +192 -26
  320. package/src/components/openapi/schema-tree.ts +209 -0
  321. package/src/components/openapi/snippets.ts +113 -19
  322. package/src/components/openapi/validate-json.ts +1 -1
  323. package/src/components/openapi/ws-client.ts +18 -2
  324. package/src/core/base-path.ts +69 -8
  325. package/src/core/config-input.ts +13 -11
  326. package/src/core/config.ts +18 -4
  327. package/src/core/diagnostics.ts +219 -30
  328. package/src/core/directive-diagnostics.ts +99 -0
  329. package/src/core/frontmatter.ts +21 -18
  330. package/src/core/graph.ts +120 -11
  331. package/src/core/heading-markers.ts +5 -18
  332. package/src/core/i18n-ui.ts +39 -2
  333. package/src/core/i18n.ts +44 -5
  334. package/src/core/last-modified.ts +25 -3
  335. package/src/core/links.ts +7 -4
  336. package/src/core/load-module.ts +20 -0
  337. package/src/core/locale-links.ts +22 -18
  338. package/src/core/manifest.ts +3 -2
  339. package/src/core/meta.ts +89 -12
  340. package/src/core/nav-diagnostics.ts +56 -1
  341. package/src/core/navigation.ts +272 -83
  342. package/src/core/ordering-prefix.ts +27 -0
  343. package/src/core/project-graph.ts +50 -6
  344. package/src/core/safe-href.ts +53 -1
  345. package/src/core/safe-links.ts +11 -2
  346. package/src/core/schema.ts +94 -18
  347. package/src/core/sources/assets.ts +83 -41
  348. package/src/core/sources/contentful-rich-text.ts +28 -20
  349. package/src/core/sources/contentful.ts +25 -12
  350. package/src/core/sources/filesystem.ts +25 -3
  351. package/src/core/sources/github-releases.ts +131 -11
  352. package/src/core/sources/lexical.ts +30 -20
  353. package/src/core/sources/lower.ts +276 -56
  354. package/src/core/sources/mdx-remote.ts +52 -16
  355. package/src/core/sources/normalize.ts +456 -119
  356. package/src/core/sources/notion.ts +77 -34
  357. package/src/core/sources/obsidian.ts +40 -9
  358. package/src/core/sources/payload.ts +1 -0
  359. package/src/core/sources/portable-text.ts +85 -49
  360. package/src/core/sources/remote.ts +18 -2
  361. package/src/core/sources/resolve.ts +52 -33
  362. package/src/core/sources/sanity.ts +1 -0
  363. package/src/core/sources/strapi-blocks.ts +28 -19
  364. package/src/core/sources/strapi.ts +1 -0
  365. package/src/core/sources/types.ts +31 -0
  366. package/src/core/sources/watch.ts +20 -7
  367. package/src/core/standard-schema.ts +10 -6
  368. package/src/core/types.ts +9 -0
  369. package/src/core/ui-packs/ar.ts +13 -0
  370. package/src/core/ui-packs/bg.ts +13 -0
  371. package/src/core/ui-packs/bn.ts +13 -0
  372. package/src/core/ui-packs/ca.ts +13 -0
  373. package/src/core/ui-packs/cs.ts +13 -0
  374. package/src/core/ui-packs/da.ts +13 -0
  375. package/src/core/ui-packs/de.ts +13 -0
  376. package/src/core/ui-packs/el.ts +13 -0
  377. package/src/core/ui-packs/es.ts +13 -0
  378. package/src/core/ui-packs/fa.ts +13 -0
  379. package/src/core/ui-packs/fi.ts +13 -0
  380. package/src/core/ui-packs/fr.ts +13 -0
  381. package/src/core/ui-packs/he.ts +13 -0
  382. package/src/core/ui-packs/hi.ts +13 -0
  383. package/src/core/ui-packs/hr.ts +13 -0
  384. package/src/core/ui-packs/hu.ts +13 -0
  385. package/src/core/ui-packs/id.ts +13 -0
  386. package/src/core/ui-packs/it.ts +13 -0
  387. package/src/core/ui-packs/ja.ts +13 -0
  388. package/src/core/ui-packs/ko.ts +13 -0
  389. package/src/core/ui-packs/nl.ts +13 -0
  390. package/src/core/ui-packs/no.ts +13 -0
  391. package/src/core/ui-packs/pl.ts +13 -0
  392. package/src/core/ui-packs/pt-br.ts +13 -0
  393. package/src/core/ui-packs/pt.ts +13 -0
  394. package/src/core/ui-packs/ro.ts +13 -0
  395. package/src/core/ui-packs/ru.ts +13 -0
  396. package/src/core/ui-packs/sk.ts +13 -0
  397. package/src/core/ui-packs/sr.ts +13 -0
  398. package/src/core/ui-packs/sv.ts +13 -0
  399. package/src/core/ui-packs/th.ts +13 -0
  400. package/src/core/ui-packs/tr.ts +13 -0
  401. package/src/core/ui-packs/uk.ts +13 -0
  402. package/src/core/ui-packs/vi.ts +13 -0
  403. package/src/core/ui-packs/zh-tw.ts +13 -0
  404. package/src/core/ui-packs/zh.ts +13 -0
  405. package/src/core/version-cut.ts +69 -17
  406. package/src/core/versions.ts +4 -1
  407. package/src/deploy/adapters/node.ts +5 -2
  408. package/src/deploy/adapters/registry.ts +2 -1
  409. package/src/deploy/adapters/types.ts +13 -1
  410. package/src/deploy/artifacts.ts +52 -11
  411. package/src/deploy/cloudflare-negotiation.ts +27 -16
  412. package/src/deploy/headers.ts +75 -55
  413. package/src/deploy/node-headers.ts +148 -27
  414. package/src/deploy/platforms/cloudflare.ts +13 -3
  415. package/src/deploy/platforms/netlify.ts +83 -5
  416. package/src/deploy/platforms/node.ts +8 -5
  417. package/src/deploy/platforms/static.ts +2 -0
  418. package/src/deploy/platforms/types.ts +15 -0
  419. package/src/deploy/platforms/vercel.ts +10 -3
  420. package/src/deploy/redirects.ts +68 -21
  421. package/src/deploy/robots.ts +2 -2
  422. package/src/deploy/rss.ts +4 -3
  423. package/src/deploy/sitemap.ts +7 -5
  424. package/src/deploy/vercel-negotiation.ts +35 -3
  425. package/src/eval/agents.ts +10 -2
  426. package/src/eval/run.ts +25 -0
  427. package/src/markdown/base-links.ts +74 -29
  428. package/src/markdown/directives.ts +242 -36
  429. package/src/markdown/features.ts +17 -0
  430. package/src/markdown/index.ts +13 -9
  431. package/src/markdown/mdast.ts +5 -2
  432. package/src/markdown/relative-links.ts +15 -27
  433. package/src/markdown/route-snapshot.ts +37 -0
  434. package/src/og/card.ts +149 -9
  435. package/src/og/derive.ts +156 -5
  436. package/src/og/index.ts +1 -0
  437. package/src/openapi/asyncapi.ts +4 -2
  438. package/src/openapi/graphql-build.ts +28 -2
  439. package/src/openapi/model.ts +99 -27
  440. package/src/openapi/proxy.ts +63 -10
  441. package/src/openapi/render-mdx.ts +51 -3
  442. package/src/registry/eject.ts +297 -43
  443. package/src/search/adapters/version-scope.ts +30 -0
  444. package/src/search/documents.ts +89 -27
  445. package/src/search/popular.ts +2 -1
  446. package/src/search/sync/algolia.ts +36 -2
  447. package/src/seo/jsonld.ts +7 -3
  448. package/src/sources/registry.ts +5 -0
  449. package/src/theme/entry.ts +11 -4
  450. package/src/translate/agents.ts +6 -1
  451. package/src/translate/ledger.ts +26 -3
  452. package/src/translate/meta.ts +76 -24
  453. package/src/translate/run.ts +14 -8
  454. package/src/translate/validate.ts +14 -2
  455. package/src/translate/work-list.ts +91 -19
  456. package/src/upgrade/upgrade.ts +36 -4
  457. package/dist/cli/chunk-27g6wdth.js.map +0 -10
  458. package/dist/cli/chunk-2hn4b8z7.js.map +0 -12
  459. package/dist/cli/chunk-6crbhc3x.js.map +0 -14
  460. package/dist/cli/chunk-6hsn950k.js.map +0 -10
  461. package/dist/cli/chunk-79jhk4py.js.map +0 -35
  462. package/dist/cli/chunk-82bbrxdn.js +0 -51
  463. package/dist/cli/chunk-82bbrxdn.js.map +0 -10
  464. package/dist/cli/chunk-abh8yjkn.js +0 -31
  465. package/dist/cli/chunk-abh8yjkn.js.map +0 -10
  466. package/dist/cli/chunk-ce574jw2.js +0 -23
  467. package/dist/cli/chunk-ce574jw2.js.map +0 -10
  468. package/dist/cli/chunk-dh8cwk36.js.map +0 -10
  469. package/dist/cli/chunk-epjnccmv.js.map +0 -10
  470. package/dist/cli/chunk-fa25z98p.js.map +0 -11
  471. package/dist/cli/chunk-fs23ddbb.js.map +0 -35
  472. package/dist/cli/chunk-fz5wtpmh.js.map +0 -10
  473. package/dist/cli/chunk-jwyddg7y.js.map +0 -15
  474. package/dist/cli/chunk-kpf8rrjc.js.map +0 -19
  475. package/dist/cli/chunk-m3vmjgmq.js.map +0 -10
  476. package/dist/cli/chunk-mb2919y2.js.map +0 -10
  477. package/dist/cli/chunk-q5163e60.js.map +0 -11
  478. package/dist/cli/chunk-qkqwkpte.js.map +0 -182
  479. package/dist/cli/chunk-qs4q5p4e.js.map +0 -10
  480. package/dist/cli/chunk-s1p84fyh.js.map +0 -10
  481. package/dist/cli/chunk-wgm7m9qk.js.map +0 -36
  482. package/dist/cli/chunk-yt5n7ppj.js.map +0 -10
  483. package/dist/cli/chunk-yw7dm696.js.map +0 -14
  484. /package/dist/cli/{chunk-s6jhgk0q.js.map → chunk-2eytanqx.js.map} +0 -0
  485. /package/dist/cli/{chunk-hdpx1tax.js.map → chunk-2z928egk.js.map} +0 -0
  486. /package/dist/cli/{chunk-ah61y8py.js.map → chunk-364znk6q.js.map} +0 -0
  487. /package/dist/cli/{chunk-vtk4a6dg.js.map → chunk-8ktnccpt.js.map} +0 -0
  488. /package/dist/cli/{chunk-fxypxtvm.js.map → chunk-a58773jm.js.map} +0 -0
  489. /package/dist/cli/{chunk-wm7js3j9.js.map → chunk-b07cmahc.js.map} +0 -0
  490. /package/dist/cli/{chunk-zxcczpyx.js.map → chunk-r20tn01b.js.map} +0 -0
  491. /package/dist/cli/{chunk-5shv93fd.js.map → chunk-tkacnehg.js.map} +0 -0
  492. /package/dist/cli/{chunk-zxh4d9vy.js.map → chunk-tzmab476.js.map} +0 -0
@@ -3,19 +3,20 @@ import {
3
3
  writeTextAtomic
4
4
  } from "./chunk-jq5n4avg.js";
5
5
  import {
6
- nextFenceState,
7
6
  localizeRoute,
7
+ nextFenceState,
8
8
  VERSION_ID,
9
9
  VERSION_LIKE,
10
10
  versionizeRoute
11
- } from "./chunk-qkqwkpte.js";
11
+ } from "./chunk-pv29h0wf.js";
12
12
  import {
13
+ mountBasePath,
13
14
  stripBasePath
14
- } from "./chunk-jts8mvcz.js";
15
+ } from "./chunk-3em5wd2y.js";
15
16
  import {
16
17
  isWithin,
17
18
  scanProject
18
- } from "./chunk-fs23ddbb.js";
19
+ } from "./chunk-j85vccga.js";
19
20
 
20
21
  // src/core/version-cut.ts
21
22
  import { existsSync } from "node:fs";
@@ -28,22 +29,39 @@ class CutError extends Error {
28
29
  }
29
30
  }
30
31
  var INLINE_CODE = /`[^`]*`/gu;
31
- var ROOT_LINK = /(?<prefix>\]\(|href="|src=")(?<target>\/[^\s"')]*)/gu;
32
+ var ROOT_LINK = /(?<prefix>\]\(|^ {0,3}\[(?!\^)[^\]]+\]:[ \t]*<?|(?:href|src)=["'])(?<target>\/[^\s"'<>)]*)/gu;
32
33
  var buildRouteRewrites = (project, id) => {
33
34
  const { basePath, i18n } = project.config;
34
35
  const { contentRoot } = project.context;
35
36
  const rewrites = new Map;
37
+ const logical = new Map;
36
38
  for (const page of project.graph.pages) {
37
39
  const { sourcePath } = page;
38
40
  if (page.version !== "" || page.collection === "staged" || !sourcePath || relative(contentRoot, sourcePath).startsWith("..")) {
39
41
  continue;
40
42
  }
41
- const logical = versionizeRoute(page.versionKey, id);
42
- rewrites.set(stripBasePath(basePath, page.route), i18n ? localizeRoute(logical, page.locale, i18n) : logical);
43
+ const snapshot = versionizeRoute(page.versionKey, id);
44
+ rewrites.set(stripBasePath(basePath, page.route), i18n ? localizeRoute(snapshot, page.locale, i18n) : snapshot);
45
+ if (i18n) {
46
+ logical.set(page.versionKey, snapshot);
47
+ }
48
+ }
49
+ for (const [route, snapshot] of logical) {
50
+ if (!rewrites.has(route)) {
51
+ rewrites.set(route, snapshot);
52
+ }
43
53
  }
44
54
  return rewrites;
45
55
  };
46
- var rewriteLine = (line, rewrites) => {
56
+ var snapshotTarget = (path, rewrites, basePath) => {
57
+ const based = basePath !== "" && (path === basePath || path.startsWith(`${basePath}/`));
58
+ if (!based) {
59
+ return rewrites.get(path);
60
+ }
61
+ const replacement = rewrites.get(stripBasePath(basePath, path));
62
+ return replacement === undefined ? undefined : mountBasePath(basePath, replacement);
63
+ };
64
+ var rewriteLine = (line, rewrites, basePath) => {
47
65
  const masked = line.replaceAll(INLINE_CODE, (span) => " ".repeat(span.length));
48
66
  let out = "";
49
67
  let cursor = 0;
@@ -54,7 +72,7 @@ var rewriteLine = (line, rewrites) => {
54
72
  const path = hash === -1 ? target : target.slice(0, hash);
55
73
  const suffix = hash === -1 ? "" : target.slice(hash);
56
74
  const bare = path !== "/" && path.endsWith("/") ? path.slice(0, -1) : path;
57
- const replacement = rewrites.get(bare);
75
+ const replacement = snapshotTarget(bare, rewrites, basePath);
58
76
  if (replacement === undefined) {
59
77
  continue;
60
78
  }
@@ -65,7 +83,7 @@ var rewriteLine = (line, rewrites) => {
65
83
  }
66
84
  return count === 0 ? line : out + line.slice(cursor);
67
85
  };
68
- var rewriteSnapshotLinks = (source, rewrites) => {
86
+ var rewriteSnapshotLinks = (source, rewrites, basePath = "") => {
69
87
  let fence = null;
70
88
  let count = 0;
71
89
  const lines = source.split(`
@@ -76,7 +94,7 @@ var rewriteSnapshotLinks = (source, rewrites) => {
76
94
  if (inFence) {
77
95
  return line;
78
96
  }
79
- const rewrittenLine = rewriteLine(line, rewrites);
97
+ const rewrittenLine = rewriteLine(line, rewrites, basePath);
80
98
  if (rewrittenLine !== line) {
81
99
  count += 1;
82
100
  }
@@ -238,7 +256,7 @@ var cutVersion = async (root, id, options = {}) => {
238
256
  return;
239
257
  }
240
258
  const source = await readFile(abs, "utf-8");
241
- const { text, count } = rewriteSnapshotLinks(source, rewrites);
259
+ const { text, count } = rewriteSnapshotLinks(source, rewrites, project.config.basePath);
242
260
  if (count > 0) {
243
261
  await writeTextAtomic(abs, text);
244
262
  rewritten.push({ count, file: relative(dir, abs) });
@@ -261,5 +279,5 @@ var cutVersion = async (root, id, options = {}) => {
261
279
 
262
280
  export { CutError, unregisteredSnapshotDiagnostics, cutVersion };
263
281
 
264
- //# debugId=B376AC6B634C865364756E2164756E21
265
- //# sourceMappingURL=chunk-qs4q5p4e.js.map
282
+ //# debugId=8631919BA7BA49B664756E2164756E21
283
+ //# sourceMappingURL=chunk-crgn1q09.js.map
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/core/version-cut.ts"],
4
+ "sourcesContent": [
5
+ "import { existsSync } from \"node:fs\";\nimport { cp, readdir, readFile, rm } from \"node:fs/promises\";\n\nimport { join, relative } from \"pathe\";\n\nimport { mountBasePath, stripBasePath } from \"./base-path.ts\";\nimport { nextFenceState } from \"./code-fences.ts\";\nimport type { FenceState } from \"./code-fences.ts\";\nimport { writeTextAtomic } from \"./fs-atomic.ts\";\nimport { localizeRoute } from \"./i18n.ts\";\nimport type { BlumeProject } from \"./project-graph.ts\";\nimport { isWithin, scanProject } from \"./project-graph.ts\";\nimport { VERSION_ID } from \"./schema.ts\";\nimport type { Diagnostic } from \"./types.ts\";\nimport { VERSION_LIKE, versionizeRoute } from \"./versions.ts\";\n\n/** What `cutVersion` did, for the CLI to report. */\nexport interface CutResult {\n /** Files copied into the snapshot. */\n copied: number;\n /** Markdown pages whose root-absolute links were rewritten, with counts. */\n rewritten: { file: string; count: number }[];\n /** Whether `blume.config.ts` was updated in place. */\n configUpdated: boolean;\n /**\n * Whether that update added the whole `versions` block — the first cut of a\n * project that had no versioning — rather than one `archived` entry.\n */\n versionsAdded: boolean;\n /** Ready-to-paste config snippet when in-place update was not possible. */\n configSnippet: string | null;\n /** Absolute path of the created snapshot directory. */\n dir: string;\n}\n\n/** A `cutVersion` failure the CLI reports as a user error, not a crash. */\nexport class CutError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"CutError\";\n }\n}\n\n// Inline code spans are syntax being *shown*, not links — blank them before\n// matching so replacements can splice into the real line by index (the mask\n// preserves length). Mirrors the content-assets rewriter.\nconst INLINE_CODE = /`[^`]*`/gu;\n// A root-absolute markdown link/image target, reference-style link definition\n// (`[setup]: /guides/setup`, up to three spaces in, never a `[^note]:`\n// footnote), or HTML href/src attribute in either quote style. Named groups\n// carry the prefix (kept) and target (rewritten).\nconst ROOT_LINK =\n /(?<prefix>\\]\\(|^ {0,3}\\[(?!\\^)[^\\]]+\\]:[ \\t]*<?|(?:href|src)=[\"'])(?<target>\\/[^\\s\"'<>)]*)/gu;\n\n/**\n * Build the link-rewrite table: every current-version route (basePath\n * stripped, since authors write root-absolute links as if mounted at root;\n * a link that spells the base out is looked up without it, see\n * `snapshotTarget`) mapped to the same page's route inside the new snapshot.\n * Only pages the snapshot actually contains qualify — filesystem pages under\n * the content root. Spec-rendered references (`/api`, `/events`) and remote\n * sources aren't copied, so links to them keep pointing at the live pages\n * instead of a 404 inside the snapshot.\n */\nconst buildRouteRewrites = (\n project: BlumeProject,\n id: string\n): Map<string, string> => {\n const { basePath, i18n } = project.config;\n const { contentRoot } = project.context;\n const rewrites = new Map<string, string>();\n // Under i18n, authors write links in the unprefixed form (`/guides/setup`)\n // and rendering moves them into the reader's locale — a form no page is\n // routed at when the default locale keeps its prefix\n // (`hideDefaultLocalePrefix: false`). So it is mapped too, to the\n // unprefixed snapshot route, which rendering localizes the same way. Page\n // routes win where the two forms coincide.\n const logical = new Map<string, string>();\n for (const page of project.graph.pages) {\n // `sourcePath` marks a page backed by a local file, which excludes\n // generated and remote pages; the content-root check below excludes local\n // files that live outside the tree a version snapshot copies. A staged\n // page (an Obsidian note) is served from its source, not from the copied\n // tree, so it keeps publishing as current even when its file sits under\n // the content root.\n const { sourcePath } = page;\n if (\n page.version !== \"\" ||\n page.collection === \"staged\" ||\n !sourcePath ||\n relative(contentRoot, sourcePath).startsWith(\"..\")\n ) {\n continue;\n }\n const snapshot = versionizeRoute(page.versionKey, id);\n rewrites.set(\n stripBasePath(basePath, page.route),\n i18n ? localizeRoute(snapshot, page.locale, i18n) : snapshot\n );\n if (i18n) {\n logical.set(page.versionKey, snapshot);\n }\n }\n for (const [route, snapshot] of logical) {\n if (!rewrites.has(route)) {\n rewrites.set(route, snapshot);\n }\n }\n return rewrites;\n};\n\n/**\n * The snapshot link a root-absolute path rewrites to, or undefined when the\n * snapshot has no copy of its page. A path written with the base path by hand\n * (`/docs/guides/x` under `basePath: \"/docs\"`) names the same page as\n * `/guides/x` — rendering leaves an already-based link alone (see\n * `withBasePath`) — so it is looked up without the base and keeps it.\n */\nconst snapshotTarget = (\n path: string,\n rewrites: Map<string, string>,\n basePath: string\n): string | undefined => {\n const based =\n basePath !== \"\" && (path === basePath || path.startsWith(`${basePath}/`));\n if (!based) {\n return rewrites.get(path);\n }\n const replacement = rewrites.get(stripBasePath(basePath, path));\n return replacement === undefined\n ? undefined\n : mountBasePath(basePath, replacement);\n};\n\n/** Rewrite one line's root-absolute internal links via the rewrite table. */\nconst rewriteLine = (\n line: string,\n rewrites: Map<string, string>,\n basePath: string\n): string => {\n const masked = line.replaceAll(INLINE_CODE, (span) =>\n \" \".repeat(span.length)\n );\n let out = \"\";\n let cursor = 0;\n let count = 0;\n for (const match of masked.matchAll(ROOT_LINK)) {\n const target = match.groups?.target ?? \"\";\n // An anchor or query stays attached to the rewritten path.\n const hash = target.search(/[#?]/u);\n const path = hash === -1 ? target : target.slice(0, hash);\n const suffix = hash === -1 ? \"\" : target.slice(hash);\n const bare = path !== \"/\" && path.endsWith(\"/\") ? path.slice(0, -1) : path;\n const replacement = snapshotTarget(bare, rewrites, basePath);\n if (replacement === undefined) {\n continue;\n }\n const offset = (match.index ?? 0) + (match.groups?.prefix?.length ?? 0);\n out += line.slice(cursor, offset) + replacement + suffix;\n cursor = offset + target.length;\n count += 1;\n }\n return count === 0 ? line : out + line.slice(cursor);\n};\n\n/** A page's link-rewritten text and how many of its lines changed. */\nexport interface SnapshotRewrite {\n text: string;\n count: number;\n}\n\n/**\n * Rewrite a copied page's root-absolute internal links to their snapshot\n * equivalents, skipping fenced and inline code. Relative links need no\n * rewriting — the whole tree copies together, so they stay self-contained.\n * `basePath` is the site's, for links that spell it out by hand.\n */\nexport const rewriteSnapshotLinks = (\n source: string,\n rewrites: Map<string, string>,\n basePath = \"\"\n): SnapshotRewrite => {\n let fence: FenceState = null;\n let count = 0;\n const lines = source.split(\"\\n\").map((line) => {\n const next = nextFenceState(line, fence);\n const inFence = fence !== null || next !== null;\n fence = next;\n if (inFence) {\n return line;\n }\n const rewrittenLine = rewriteLine(line, rewrites, basePath);\n if (rewrittenLine !== line) {\n count += 1;\n }\n return rewrittenLine;\n });\n return { count, text: lines.join(\"\\n\") };\n};\n\n/**\n * The switcher label a first cut gives the live docs. `versions.current.label`\n * is required, and \"Latest\" reads right until the author names the release.\n */\nconst CURRENT_LABEL = \"Latest\";\n\n/** The config entry to add, as a paste-ready snippet for the fallback path. */\nconst snippetFor = (id: string, hasVersions: boolean): string =>\n hasVersions\n ? `Add to versions.archived in blume.config.ts (newest first):\\n\\n { id: \"${id}\" },\\n`\n : `Add to blume.config.ts:\\n\\n versions: {\\n archived: [{ id: \"${id}\" }],\\n current: { label: \"${CURRENT_LABEL}\" },\\n },\\n`;\n\n/**\n * Best-effort in-place config update: insert the new id at the head of an\n * existing \\`archived: [\\` array literal, preserving indentation. Anything\n * fancier (computed arrays, config spread across files) falls back to a\n * printed snippet — the config is user-authored TypeScript, and string-level\n * surgery beyond this simple shape risks corrupting it.\n */\nexport const insertArchivedVersion = async (\n configPath: string,\n id: string\n): Promise<boolean> => {\n let text: string;\n try {\n text = await readFile(configPath, \"utf-8\");\n } catch {\n return false;\n }\n const match = text.match(/(?<lead>archived:\\s*\\[)/u);\n if (!match || match.index === undefined) {\n return false;\n }\n const insertAt = match.index + (match.groups?.lead?.length ?? 0);\n // Indentation: one level deeper than the line holding `archived:`.\n const lineStart = text.lastIndexOf(\"\\n\", match.index) + 1;\n const indent = text.slice(lineStart).match(/^\\s*/u)?.[0] ?? \"\";\n const rest = text.slice(insertAt);\n // Match the array's authored shape: empty stays bare, an inline array gets\n // an inline entry, a multiline array gets its own indented line — on the\n // file's own line ending, so a CRLF config doesn't gain a lone LF.\n const eol = /^\\r?\\n/u.exec(rest)?.[0];\n let entry: string;\n if (rest.trimStart().startsWith(\"]\")) {\n entry = `{ id: \"${id}\" }`;\n } else if (eol) {\n entry = `${eol}${indent} { id: \"${id}\" },`;\n } else {\n entry = `{ id: \"${id}\" }, `;\n }\n await writeTextAtomic(configPath, text.slice(0, insertAt) + entry + rest);\n return true;\n};\n\n/** The opening brace of the config object: `defineConfig({` or `export default {`. */\nconst CONFIG_OBJECT = /(?:defineConfig\\(\\s*|export\\s+default\\s+)\\{/gu;\n\n/**\n * Best-effort in-place registration of a first version: add a `versions` block\n * (the id archived, the live docs labeled {@link CURRENT_LABEL}) as the first\n * property of the config object. Only the plain shape is edited — exactly one\n * `defineConfig({` or `export default {` and no `versions` key yet — so a\n * config built any other way falls back to the printed snippet rather than\n * risk corrupting it.\n */\nexport const insertVersionsBlock = async (\n configPath: string,\n id: string\n): Promise<boolean> => {\n let text: string;\n try {\n text = await readFile(configPath, \"utf-8\");\n } catch {\n return false;\n }\n const matches = [...text.matchAll(CONFIG_OBJECT)];\n const [match] = matches;\n if (matches.length !== 1 || !match || /\\bversions\\s*:/u.test(text)) {\n return false;\n }\n const insertAt = match.index + match[0].length;\n const rest = text.slice(insertAt);\n const eol = text.includes(\"\\r\\n\") ? \"\\r\\n\" : \"\\n\";\n const lineStart = text.lastIndexOf(\"\\n\", match.index) + 1;\n const outer = /^[ \\t]*/u.exec(text.slice(lineStart))?.[0] ?? \"\";\n // Match the indentation of the property on the next line, when there is one.\n const indent =\n /^[ \\t]*\\r?\\n(?<indent>[ \\t]*)\\S/u.exec(rest)?.groups?.indent ??\n `${outer} `;\n const block = [\n \"versions: {\",\n ` archived: [{ id: \"${id}\" }],`,\n ` current: { label: \"${CURRENT_LABEL}\" },`,\n \"},\",\n ]\n .map((line) => `${indent}${line}`)\n .join(eol);\n const body = rest.trimStart();\n let tail: string;\n if (body.startsWith(\"}\")) {\n // An empty object: close it on its own line.\n tail = `${eol}${outer}${body}`;\n } else if (/^[ \\t]*\\r?\\n/u.test(rest)) {\n tail = rest;\n } else {\n // An inline object: move its first property onto the next line.\n tail = `${eol}${indent}${body}`;\n }\n await writeTextAtomic(\n configPath,\n `${text.slice(0, insertAt)}${eol}${block}${tail}`\n );\n return true;\n};\n\n/**\n * Version-shaped folders (`v1.0/`) at the top of the content root of a project\n * with no `versions` config — usually a snapshot `blume version` cut but\n * couldn't register — which build as ordinary content at `/v1.0/…`, so every\n * page ships twice. With versioning configured, the scan's own\n * `BLUME_VERSIONS_UNCONFIGURED_VERSION` covers a folder it doesn't list; this\n * check is `blume doctor`'s alone, since an unversioned site can have a real\n * `v1/` section that a warning on every build would only nag about.\n */\nexport const unregisteredSnapshotDiagnostics = (\n project: BlumeProject\n): Diagnostic[] => {\n if (project.config.versions) {\n return [];\n }\n const { contentRoot } = project.context;\n const folders = new Set<string>();\n for (const page of project.graph.pages) {\n const [first, ...rest] = page.sourcePath\n ? relative(contentRoot, page.sourcePath).split(\"/\")\n : [];\n if (first && rest.length > 0 && VERSION_LIKE.test(first)) {\n folders.add(first);\n }\n }\n return [...folders].toSorted().map((folder) => ({\n code: \"BLUME_VERSIONS_UNCONFIGURED_VERSION\",\n file: join(contentRoot, folder),\n message: `Folder \"${folder}/\" looks like a version snapshot, but versioning isn't configured, so its pages build as ordinary content at /${folder}/….`,\n severity: \"warning\",\n suggestion: `If it's a snapshot, register it with \\`versions: { archived: [{ id: \"${folder}\" }], current: { label: \"${CURRENT_LABEL}\" } }\\` in blume.config.ts; if it's an ordinary section, ignore this.`,\n }));\n};\n\n/**\n * Freeze the current docs as an archived version: copy the content tree into\n * `<contentRoot>/<id>/` (excluding existing snapshots), rewrite root-absolute\n * internal links so the copy is self-contained, and register the id in\n * `blume.config.ts` (or print the snippet to paste).\n */\nexport const cutVersion = async (\n root: string,\n id: string,\n options: { force?: boolean } = {}\n): Promise<CutResult> => {\n if (!VERSION_ID.test(id)) {\n throw new CutError(\n `Version ids must start with a letter (e.g. \"v1.0\") and contain only letters, digits, dots, hyphens, and underscores — got \"${id}\".`\n );\n }\n\n const project = await scanProject(root);\n const errors = project.diagnostics.filter(\n (diagnostic) => diagnostic.severity === \"error\"\n );\n if (errors.length > 0) {\n throw new CutError(\n `The project has ${errors.length} error diagnostic(s) — fix them before cutting a version (run \\`blume validate\\`).`\n );\n }\n // A missing content root already fails inside `scanProject` (the filesystem\n // source's own validation), so only the version-level checks remain here.\n const { contentRoot } = project.context;\n if (project.config.versions?.archived.some((version) => version.id === id)) {\n throw new CutError(\n `Version \"${id}\" is already registered in versions.archived.`\n );\n }\n\n const dir = join(contentRoot, id);\n if (existsSync(dir)) {\n if (!options.force) {\n throw new CutError(\n `${dir} already exists — pass --force to overwrite the snapshot.`\n );\n }\n await rm(dir, { force: true, recursive: true });\n }\n\n // Existing snapshots must not nest inside the new one: configured ids, plus\n // any version-shaped directory (`v1.0/`) that never made it into the config —\n // e.g. a prior cut whose config update fell back to a printed snippet. A\n // genuine content folder that merely looks like a version already draws the\n // rename-or-register diagnostic, so skipping it here is consistent.\n const excluded = new Set([\n id,\n \"node_modules\",\n ...(project.config.versions?.archived.map((version) => version.id) ?? []),\n ]);\n // Another local source's tree under the content root — an Obsidian vault the\n // filesystem source excludes — is that source's to publish. Copying it would\n // republish its raw notes (wikilinks and `%%comments%%` intact) as\n // filesystem pages of the snapshot, while the source itself keeps serving\n // them as current.\n const foreignRoots = project.sources\n .flatMap((source) =>\n source.staged && source.contentRoot ? [source.contentRoot] : []\n )\n .filter((tree) => isWithin(contentRoot, tree));\n const isForeign = (path: string): boolean =>\n foreignRoots.some((tree) => isWithin(tree, path));\n const entries = await readdir(contentRoot, { withFileTypes: true });\n let copied = 0;\n await Promise.all(\n entries.map(async (entry) => {\n if (\n excluded.has(entry.name) ||\n entry.name.startsWith(\".\") ||\n (entry.isDirectory() && VERSION_LIKE.test(entry.name))\n ) {\n return;\n }\n await cp(join(contentRoot, entry.name), join(dir, entry.name), {\n filter: (source) => !isForeign(source),\n recursive: true,\n });\n })\n );\n\n // Rewrite root-absolute internal links in every copied markdown page.\n const rewrites = buildRouteRewrites(project, id);\n const rewritten: { file: string; count: number }[] = [];\n const walk = async (current: string): Promise<void> => {\n const children = await readdir(current, { withFileTypes: true });\n await Promise.all(\n children.map(async (child) => {\n const abs = join(current, child.name);\n if (child.isDirectory()) {\n await walk(abs);\n return;\n }\n copied += 1;\n if (!/\\.mdx?$/u.test(child.name)) {\n return;\n }\n const source = await readFile(abs, \"utf-8\");\n const { text, count } = rewriteSnapshotLinks(\n source,\n rewrites,\n project.config.basePath\n );\n if (count > 0) {\n await writeTextAtomic(abs, text);\n rewritten.push({ count, file: relative(dir, abs) });\n }\n })\n );\n };\n await walk(dir);\n\n const configPath =\n project.context.configFile ?? join(root, \"blume.config.ts\");\n const firstVersion = project.config.versions === undefined;\n const configUpdated = firstVersion\n ? await insertVersionsBlock(configPath, id)\n : await insertArchivedVersion(configPath, id);\n\n return {\n configSnippet: configUpdated ? null : snippetFor(id, !firstVersion),\n configUpdated,\n copied,\n dir,\n rewritten,\n versionsAdded: configUpdated && firstVersion,\n };\n};\n"
6
+ ],
7
+ "mappings": "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",
8
+ "debugId": "8631919BA7BA49B664756E2164756E21",
9
+ "names": []
10
+ }
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ logger
4
+ } from "./index.js";
5
+
6
+ // src/cli/args.ts
7
+ var MAX_PORT = 65535;
8
+ var parsePort = (value) => {
9
+ if (value === undefined) {
10
+ return;
11
+ }
12
+ const port = Number(value);
13
+ if (!(Number.isInteger(port) && port >= 1 && port <= MAX_PORT)) {
14
+ logger.error(`Invalid --port "${value}" (expected an integer 1-${MAX_PORT}).`);
15
+ process.exit(1);
16
+ }
17
+ return port;
18
+ };
19
+ var MAX_TIMEOUT_S = Math.floor(2147483647 / 1000);
20
+ var parseTimeoutSeconds = (value, fallback) => {
21
+ if (value === undefined) {
22
+ return fallback;
23
+ }
24
+ const timeout = Number(value);
25
+ if (!Number.isInteger(timeout) || timeout <= 0) {
26
+ logger.error(`Invalid --timeout "${value}" (whole seconds).`);
27
+ process.exit(1);
28
+ }
29
+ if (timeout > MAX_TIMEOUT_S) {
30
+ logger.error(`Invalid --timeout "${value}" (at most ${MAX_TIMEOUT_S} seconds, about 24 days).`);
31
+ process.exit(1);
32
+ }
33
+ return timeout;
34
+ };
35
+
36
+ export { parsePort, parseTimeoutSeconds };
37
+
38
+ //# debugId=02AD79A562BBAEE664756E2164756E21
39
+ //# sourceMappingURL=chunk-e04dxsz1.js.map
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/cli/args.ts"],
4
+ "sourcesContent": [
5
+ "import { logger } from \"./log.ts\";\n\nconst MAX_PORT = 65_535;\n\n/**\n * Parse a `--port` value into a valid port number, or `undefined` when unset.\n * A non-integer or out-of-range value (`--port abc` → `NaN`) exits with an\n * error rather than propagating `localhost:NaN` into the dev server and the\n * `deployment.site` fallback.\n */\nexport const parsePort = (value?: string): number | undefined => {\n if (value === undefined) {\n return;\n }\n const port = Number(value);\n if (!(Number.isInteger(port) && port >= 1 && port <= MAX_PORT)) {\n logger.error(\n `Invalid --port \"${value}\" (expected an integer 1-${MAX_PORT}).`\n );\n process.exit(1);\n }\n return port;\n};\n\n/**\n * The longest `--timeout` a timer can hold, in seconds. Node clamps a\n * `setTimeout` delay above 2^31−1 ms (about 24.8 days) to 1 ms, so a larger\n * value would time every agent out the moment it starts.\n */\nexport const MAX_TIMEOUT_S = Math.floor(2_147_483_647 / 1000);\n\n/**\n * Parse a `--timeout` value in whole seconds, or return `fallback` when unset.\n * A non-integer, non-positive, or too-long value exits with an error.\n */\nexport const parseTimeoutSeconds = (\n value: string | undefined,\n fallback: number\n): number => {\n if (value === undefined) {\n return fallback;\n }\n const timeout = Number(value);\n if (!Number.isInteger(timeout) || timeout <= 0) {\n logger.error(`Invalid --timeout \"${value}\" (whole seconds).`);\n process.exit(1);\n }\n if (timeout > MAX_TIMEOUT_S) {\n logger.error(\n `Invalid --timeout \"${value}\" (at most ${MAX_TIMEOUT_S} seconds, about 24 days).`\n );\n process.exit(1);\n }\n return timeout;\n};\n"
6
+ ],
7
+ "mappings": ";;;;;;AAEA,IAAM,WAAW;AAQV,IAAM,YAAY,CAAC,UAAuC;AAAA,EAC/D,IAAI,UAAU,WAAW;AAAA,IACvB;AAAA,EACF;AAAA,EACA,MAAM,OAAO,OAAO,KAAK;AAAA,EACzB,IAAI,EAAE,OAAO,UAAU,IAAI,KAAK,QAAQ,KAAK,QAAQ,WAAW;AAAA,IAC9D,OAAO,MACL,mBAAmB,iCAAiC,YACtD;AAAA,IACA,QAAQ,KAAK,CAAC;AAAA,EAChB;AAAA,EACA,OAAO;AAAA;AAQF,IAAM,gBAAgB,KAAK,MAAM,aAAgB,IAAI;AAMrD,IAAM,sBAAsB,CACjC,OACA,aACW;AAAA,EACX,IAAI,UAAU,WAAW;AAAA,IACvB,OAAO;AAAA,EACT;AAAA,EACA,MAAM,UAAU,OAAO,KAAK;AAAA,EAC5B,IAAI,CAAC,OAAO,UAAU,OAAO,KAAK,WAAW,GAAG;AAAA,IAC9C,OAAO,MAAM,sBAAsB,yBAAyB;AAAA,IAC5D,QAAQ,KAAK,CAAC;AAAA,EAChB;AAAA,EACA,IAAI,UAAU,eAAe;AAAA,IAC3B,OAAO,MACL,sBAAsB,mBAAmB,wCAC3C;AAAA,IACA,QAAQ,KAAK,CAAC;AAAA,EAChB;AAAA,EACA,OAAO;AAAA;",
8
+ "debugId": "02AD79A562BBAEE664756E2164756E21",
9
+ "names": []
10
+ }
@@ -2,14 +2,14 @@
2
2
  import {
3
3
  commandsFor,
4
4
  detectProjectPackageManager
5
- } from "./chunk-qkqwkpte.js";
5
+ } from "./chunk-pv29h0wf.js";
6
6
  import {
7
7
  packageRoot,
8
8
  logger
9
9
  } from "./index.js";
10
10
  import {
11
11
  EJECTED_CONFIG_HEADER
12
- } from "./chunk-2hn4b8z7.js";
12
+ } from "./chunk-5m5nmvyq.js";
13
13
 
14
14
  // src/cli/eject-scripts.ts
15
15
  import { existsSync, readFileSync } from "node:fs";
@@ -64,16 +64,26 @@ var isEjectedProject = (root) => {
64
64
  const source = readFileSync(config, "utf-8");
65
65
  return source.startsWith(EJECTED_CONFIG_HEADER) || source.startsWith(BLUME_1_EJECTED_CONFIG_HEADER);
66
66
  };
67
- var refuseIfEjected = async (root, script) => {
67
+ var ejectedEquivalent = (pm, command) => {
68
+ const { build, dev, exec } = commandsFor(pm);
69
+ return {
70
+ build,
71
+ check: `${exec} astro check`,
72
+ dev,
73
+ preview: pm === "npm" ? "npm run preview" : `${pm} preview`,
74
+ sync: `${exec} astro sync`
75
+ }[command];
76
+ };
77
+ var refuseIfEjected = async (root, command) => {
68
78
  if (!isEjectedProject(root)) {
69
79
  return;
70
80
  }
71
- const commands = commandsFor(await detectProjectPackageManager(root));
72
- logger.error(`This project was ejected to a standalone Astro app, so \`blume ${script}\` would run a regenerated copy of the site instead of it. Run \`${commands[script]}\` instead.`);
81
+ const pm = await detectProjectPackageManager(root);
82
+ logger.error(`This project was ejected to a standalone Astro app, so \`blume ${command}\` would run a regenerated copy of the site instead of it. Run \`${ejectedEquivalent(pm, command)}\` instead.`);
73
83
  process.exit(1);
74
84
  };
75
85
 
76
86
  export { updatePackageScripts, isEjectedProject, refuseIfEjected };
77
87
 
78
- //# debugId=5D0834602D1CB35B64756E2164756E21
79
- //# sourceMappingURL=chunk-yt5n7ppj.js.map
88
+ //# debugId=F07EB9DD3957B57764756E2164756E21
89
+ //# sourceMappingURL=chunk-ey84smr6.js.map
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/cli/eject-scripts.ts"],
4
+ "sourcesContent": [
5
+ "import { existsSync, readFileSync } from \"node:fs\";\nimport { readFile, writeFile } from \"node:fs/promises\";\n\nimport { join } from \"pathe\";\n\nimport { EJECTED_CONFIG_HEADER } from \"../astro/templates.ts\";\nimport { packageRoot } from \"../core/package-root.ts\";\nimport { commandsFor, detectProjectPackageManager } from \"./init/scaffold.ts\";\nimport type { PackageManager } from \"./init/scaffold.ts\";\nimport { logger } from \"./log.ts\";\n\n/** A JSON value, as `JSON.parse` of a manifest can return. */\ntype JsonValue =\n | string\n | number\n | boolean\n | null\n | JsonValue[]\n | { [key: string]: JsonValue };\n\n/** The slice of package.json the rewrite touches; the rest rides along. */\ninterface PackageManifest {\n [key: string]: JsonValue | undefined;\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n optionalDependencies?: Record<string, string>;\n peerDependencies?: Record<string, string>;\n scripts?: Record<string, string>;\n}\n\n/** Package name → the semver range to depend on it at. */\nexport interface DependencyRanges {\n [name: string]: string;\n}\n\n/**\n * The version range Blume itself uses for each package it depends on or\n * accepts as a peer, plus `blume` at the installed version — what an ejected\n * app should pin so it keeps building against the same majors.\n */\nexport const blumeDependencyRanges = (): DependencyRanges => {\n // SAFETY: blume's own package.json, which declares its version and both\n // dependency maps; nothing else is read.\n const manifest = JSON.parse(\n readFileSync(join(packageRoot(), \"package.json\"), \"utf-8\")\n ) as {\n dependencies: Record<string, string>;\n peerDependencies: Record<string, string>;\n version: string;\n };\n return {\n ...manifest.peerDependencies,\n ...manifest.dependencies,\n blume: `^${manifest.version}`,\n };\n};\n\n/** Whether the manifest already lists `name` in any dependency field. */\nconst declares = (pkg: PackageManifest, name: string): boolean =>\n [\n pkg.dependencies,\n pkg.devDependencies,\n pkg.optionalDependencies,\n pkg.peerDependencies,\n ].some((field) => field !== undefined && Object.hasOwn(field, name));\n\n/**\n * Point the project's package.json at the ejected app. Its scripts run Astro\n * directly: after an eject the Blume CLI no longer manages the runtime, so\n * scaffolded scripts like `\"dev\": \"blume dev\"` would rebuild the removed\n * `.blume` tree instead of serving the ejected app. And every package the\n * ejected app imports by bare name (`dependencies`, from `eject()`) that the\n * project doesn't list yet becomes a dependency at the range Blume itself\n * uses (`ranges`).\n *\n * Returns the names it added, so the caller can ask for an install. A missing\n * or unreadable package.json is left alone.\n */\nexport const updatePackageScripts = async (\n root: string,\n dependencies: string[] = [],\n ranges: DependencyRanges = blumeDependencyRanges()\n): Promise<string[]> => {\n const pkgPath = join(root, \"package.json\");\n let pkg: PackageManifest;\n try {\n pkg = JSON.parse(await readFile(pkgPath, \"utf-8\"));\n } catch {\n return [];\n }\n const scripts = pkg.scripts ?? {};\n pkg.scripts = {\n ...scripts,\n build: \"astro build\",\n dev: \"astro dev\",\n preview: \"astro preview\",\n };\n const added = dependencies.filter((name) => !declares(pkg, name));\n if (added.length > 0) {\n // Sorted, the way package managers write the field.\n pkg.dependencies = Object.fromEntries(\n Object.entries({\n ...pkg.dependencies,\n ...Object.fromEntries(added.map((name) => [name, ranges[name] ?? \"*\"])),\n }).toSorted(([a], [b]) => (a < b ? -1 : 1))\n );\n }\n await writeFile(pkgPath, `${JSON.stringify(pkg, null, 2)}\\n`, \"utf-8\");\n return added;\n};\n\n/**\n * The first line Blume 1's `blume eject` wrote into the ejected\n * `astro.config.mjs` — the hidden runtime's own header, carried over. Blume 2's\n * hidden runtime keeps it under `.blume/`, never at the project root, so a root\n * config that opens with it is an app Blume 1 ejected.\n */\nconst BLUME_1_EJECTED_CONFIG_HEADER =\n \"// Generated by Blume. Do not edit; this file is recreated on each run.\";\n\n/**\n * Whether `root` holds an app `blume eject` already wrote: a root\n * `astro.config.mjs` whose first line is eject's header, or the header Blume 1\n * ejected with. The header is the only signal: a Blume project may keep its own\n * `astro.config.mjs` and a codegen `src/generated/` folder beside its content,\n * and neither makes it an ejected app.\n */\nexport const isEjectedProject = (root: string): boolean => {\n const config = join(root, \"astro.config.mjs\");\n if (!existsSync(config)) {\n return false;\n }\n const source = readFileSync(config, \"utf-8\");\n return (\n source.startsWith(EJECTED_CONFIG_HEADER) ||\n source.startsWith(BLUME_1_EJECTED_CONFIG_HEADER)\n );\n};\n\n/** The Blume commands that run the hidden `.blume/` copy of the site. */\nexport type RuntimeCommand = \"build\" | \"check\" | \"dev\" | \"preview\" | \"sync\";\n\n/**\n * What an ejected app runs in place of each {@link RuntimeCommand}: its own\n * `dev`/`build`/`preview` scripts (eject writes them), or Astro's CLI for the\n * check and the content sync.\n */\nconst ejectedEquivalent = (\n pm: PackageManager,\n command: RuntimeCommand\n): string => {\n const { build, dev, exec } = commandsFor(pm);\n return {\n build,\n check: `${exec} astro check`,\n dev,\n // Spelled like `dev`: npm runs a custom script only through `run`.\n preview: pm === \"npm\" ? \"npm run preview\" : `${pm} preview`,\n sync: `${exec} astro sync`,\n }[command];\n};\n\n/**\n * Stop a command that works on the hidden runtime in an ejected app. `dev`,\n * `build`, `check`, and `sync` would regenerate `.blume/` from\n * `blume.config.ts` and run that hidden copy, ignoring every edit made to the\n * app since eject, and `preview` would look for that copy's build; point at\n * the app's own command under the project's package manager instead.\n */\nexport const refuseIfEjected = async (\n root: string,\n command: RuntimeCommand\n): Promise<void> => {\n if (!isEjectedProject(root)) {\n return;\n }\n const pm = await detectProjectPackageManager(root);\n logger.error(\n `This project was ejected to a standalone Astro app, so \\`blume ${command}\\` would run a regenerated copy of the site instead of it. Run \\`${ejectedEquivalent(pm, command)}\\` instead.`\n );\n process.exit(1);\n};\n"
6
+ ],
7
+ "mappings": ";;;;;;;;;;;;;;AAAA;AACA;AAEA;AAqCO,IAAM,wBAAwB,MAAwB;AAAA,EAG3D,MAAM,WAAW,KAAK,MACpB,aAAa,KAAK,YAAY,GAAG,cAAc,GAAG,OAAO,CAC3D;AAAA,EAKA,OAAO;AAAA,OACF,SAAS;AAAA,OACT,SAAS;AAAA,IACZ,OAAO,IAAI,SAAS;AAAA,EACtB;AAAA;AAIF,IAAM,WAAW,CAAC,KAAsB,SACtC;AAAA,EACE,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AACN,EAAE,KAAK,CAAC,UAAU,UAAU,aAAa,OAAO,OAAO,OAAO,IAAI,CAAC;AAc9D,IAAM,uBAAuB,OAClC,MACA,eAAyB,CAAC,GAC1B,SAA2B,sBAAsB,MAC3B;AAAA,EACtB,MAAM,UAAU,KAAK,MAAM,cAAc;AAAA,EACzC,IAAI;AAAA,EACJ,IAAI;AAAA,IACF,MAAM,KAAK,MAAM,MAAM,SAAS,SAAS,OAAO,CAAC;AAAA,IACjD,MAAM;AAAA,IACN,OAAO,CAAC;AAAA;AAAA,EAEV,MAAM,UAAU,IAAI,WAAW,CAAC;AAAA,EAChC,IAAI,UAAU;AAAA,OACT;AAAA,IACH,OAAO;AAAA,IACP,KAAK;AAAA,IACL,SAAS;AAAA,EACX;AAAA,EACA,MAAM,QAAQ,aAAa,OAAO,CAAC,SAAS,CAAC,SAAS,KAAK,IAAI,CAAC;AAAA,EAChE,IAAI,MAAM,SAAS,GAAG;AAAA,IAEpB,IAAI,eAAe,OAAO,YACxB,OAAO,QAAQ;AAAA,SACV,IAAI;AAAA,SACJ,OAAO,YAAY,MAAM,IAAI,CAAC,SAAS,CAAC,MAAM,OAAO,SAAS,GAAG,CAAC,CAAC;AAAA,IACxE,CAAC,EAAE,SAAS,EAAE,KAAK,OAAQ,IAAI,IAAI,KAAK,CAAE,CAC5C;AAAA,EACF;AAAA,EACA,MAAM,UAAU,SAAS,GAAG,KAAK,UAAU,KAAK,MAAM,CAAC;AAAA,GAAO,OAAO;AAAA,EACrE,OAAO;AAAA;AAST,IAAM,gCACJ;AASK,IAAM,mBAAmB,CAAC,SAA0B;AAAA,EACzD,MAAM,SAAS,KAAK,MAAM,kBAAkB;AAAA,EAC5C,IAAI,CAAC,WAAW,MAAM,GAAG;AAAA,IACvB,OAAO;AAAA,EACT;AAAA,EACA,MAAM,SAAS,aAAa,QAAQ,OAAO;AAAA,EAC3C,OACE,OAAO,WAAW,qBAAqB,KACvC,OAAO,WAAW,6BAA6B;AAAA;AAYnD,IAAM,oBAAoB,CACxB,IACA,YACW;AAAA,EACX,QAAQ,OAAO,KAAK,SAAS,YAAY,EAAE;AAAA,EAC3C,OAAO;AAAA,IACL;AAAA,IACA,OAAO,GAAG;AAAA,IACV;AAAA,IAEA,SAAS,OAAO,QAAQ,oBAAoB,GAAG;AAAA,IAC/C,MAAM,GAAG;AAAA,EACX,EAAE;AAAA;AAUG,IAAM,kBAAkB,OAC7B,MACA,YACkB;AAAA,EAClB,IAAI,CAAC,iBAAiB,IAAI,GAAG;AAAA,IAC3B;AAAA,EACF;AAAA,EACA,MAAM,KAAK,MAAM,4BAA4B,IAAI;AAAA,EACjD,OAAO,MACL,kEAAkE,2EAA2E,kBAAkB,IAAI,OAAO,cAC5K;AAAA,EACA,QAAQ,KAAK,CAAC;AAAA;",
8
+ "debugId": "F07EB9DD3957B57764756E2164756E21",
9
+ "names": []
10
+ }
@@ -8,27 +8,26 @@ import {
8
8
  import {
9
9
  commandsFor,
10
10
  detectProjectPackageManager
11
- } from "./chunk-qkqwkpte.js";
12
- import"./chunk-6crbhc3x.js";
13
- import"./chunk-jts8mvcz.js";
14
- import"./chunk-2hn4b8z7.js";
15
- import"./chunk-wm7js3j9.js";
16
- import"./chunk-wgm7m9qk.js";
17
- import"./chunk-fs23ddbb.js";
18
- import"./chunk-vtk4a6dg.js";
11
+ } from "./chunk-pv29h0wf.js";
12
+ import"./chunk-3em5wd2y.js";
13
+ import"./chunk-c8chx29p.js";
14
+ import"./chunk-yfyb25rh.js";
15
+ import"./chunk-j85vccga.js";
16
+ import"./chunk-5m5nmvyq.js";
17
+ import"./chunk-b07cmahc.js";
18
+ import"./chunk-8ktnccpt.js";
19
19
  import"./chunk-jq5n4avg.js";
20
- import"./chunk-zxcczpyx.js";
21
- import"./chunk-82bbrxdn.js";
20
+ import"./chunk-r20tn01b.js";
22
21
  import {
23
22
  eject
24
- } from "./chunk-6hsn950k.js";
23
+ } from "./chunk-9t7a85s3.js";
25
24
  import {
26
25
  refuseIfDevRunning
27
- } from "./chunk-27g6wdth.js";
26
+ } from "./chunk-akbpwfxc.js";
28
27
  import {
29
28
  updatePackageScripts,
30
29
  isEjectedProject
31
- } from "./chunk-yt5n7ppj.js";
30
+ } from "./chunk-ey84smr6.js";
32
31
 
33
32
  // src/cli/commands/eject.ts
34
33
  import { defineCommand } from "citty";
@@ -93,5 +92,5 @@ export {
93
92
  ejectCommand
94
93
  };
95
94
 
96
- //# debugId=7CEB23581B9B638D64756E2164756E21
97
- //# sourceMappingURL=chunk-f2z5v128.js.map
95
+ //# debugId=3D94285342361B2D64756E2164756E21
96
+ //# sourceMappingURL=chunk-g4hq16wv.js.map
@@ -4,7 +4,7 @@
4
4
  "sourcesContent": [
5
5
  "import { defineCommand } from \"citty\";\nimport { relative } from \"pathe\";\n\nimport { BlumeError } from \"../../core/diagnostics.ts\";\nimport { eject } from \"../../registry/eject.ts\";\nimport { commandMeta } from \"../command-meta.ts\";\nimport { refuseIfDevRunning } from \"../dev-lock.ts\";\nimport { isEjectedProject, updatePackageScripts } from \"../eject-scripts.ts\";\nimport { commandsFor, detectProjectPackageManager } from \"../init/scaffold.ts\";\nimport { logger, reportDiagnostics } from \"../log.ts\";\n\n/**\n * Eject the project, reporting a config or `components.ts` error as the same\n * diagnostic other commands print (a Blume 1 config, say) instead of a stack.\n */\nconst ejectOrExit = async (\n root: string\n): Promise<Awaited<ReturnType<typeof eject>>> => {\n try {\n return await eject(root);\n } catch (error) {\n if (error instanceof BlumeError) {\n reportDiagnostics([error.diagnostic], root);\n process.exit(1);\n }\n throw error;\n }\n};\n\nexport const ejectCommand = defineCommand({\n args: {\n force: {\n description:\n \"Eject again over an already-ejected app, overwriting astro.config.mjs and src/.\",\n type: \"boolean\",\n },\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 // A second eject rewrites the app from blume.config.ts, discarding every\n // edit made to it since the first, so it takes an explicit --force.\n if (isEjectedProject(root) && !args.force) {\n logger.error(\n \"This project is already ejected: ejecting again would overwrite astro.config.mjs and src/ with a fresh copy, discarding your edits to them. Pass --force to overwrite them anyway.\"\n );\n process.exit(1);\n }\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, adds the packages the Astro app imports to its dependencies, 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 { dependencies, files, warnings } = await ejectOrExit(root);\n const added = await updatePackageScripts(root, dependencies);\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, install } = commandsFor(pm);\n // Newly added dependencies aren't installed yet, so install comes first.\n const run = added.length > 0 ? [install, dev, build] : [dev, build];\n const addedNote =\n added.length > 0 ? `Added to package.json: ${added.join(\", \")}.\\n\\n` : \"\";\n logger.box(\n `Your project is now a standalone Astro app.\\n\\n${addedNote}${run.map((command) => ` ${command}`).join(\"\\n\")}\\n\\nThe blume package remains importable.`\n );\n },\n});\n"
6
6
  ],
7
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AACA;AAcA,IAAM,cAAc,OAClB,SAC+C;AAAA,EAC/C,IAAI;AAAA,IACF,OAAO,MAAM,MAAM,IAAI;AAAA,IACvB,OAAO,OAAO;AAAA,IACd,IAAI,iBAAiB,YAAY;AAAA,MAC/B,kBAAkB,CAAC,MAAM,UAAU,GAAG,IAAI;AAAA,MAC1C,QAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,IACA,MAAM;AAAA;AAAA;AAIH,IAAM,eAAe,cAAc;AAAA,EACxC,MAAM;AAAA,IACJ,OAAO;AAAA,MACL,aACE;AAAA,MACF,MAAM;AAAA,IACR;AAAA,IACA,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,IAInC,IAAI,iBAAiB,IAAI,KAAK,CAAC,KAAK,OAAO;AAAA,MACzC,OAAO,MACL,oLACF;AAAA,MACA,QAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,IAEA,IAAI,CAAC,KAAK,KAAK;AAAA,MACb,OAAO,KACL,sPACF;AAAA,MACA,OAAO,KAAK,+BAA+B;AAAA,MAC3C;AAAA,IACF;AAAA,IAEA,QAAQ,cAAc,OAAO,aAAa,MAAM,YAAY,IAAI;AAAA,IAChE,MAAM,QAAQ,MAAM,qBAAqB,MAAM,YAAY;AAAA,IAI3D,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,KAAK,YAAY,YAAY,EAAE;AAAA,IAE9C,MAAM,MAAM,MAAM,SAAS,IAAI,CAAC,SAAS,KAAK,KAAK,IAAI,CAAC,KAAK,KAAK;AAAA,IAClE,MAAM,YACJ,MAAM,SAAS,IAAI,0BAA0B,MAAM,KAAK,IAAI;AAAA;AAAA,IAAW;AAAA,IACzE,OAAO,IACL;AAAA;AAAA,EAAkD,YAAY,IAAI,IAAI,CAAC,YAAY,KAAK,SAAS,EAAE,KAAK;AAAA,CAAI;AAAA;AAAA,sCAC9G;AAAA;AAEJ,CAAC;",
8
- "debugId": "7CEB23581B9B638D64756E2164756E21",
7
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AACA;AAcA,IAAM,cAAc,OAClB,SAC+C;AAAA,EAC/C,IAAI;AAAA,IACF,OAAO,MAAM,MAAM,IAAI;AAAA,IACvB,OAAO,OAAO;AAAA,IACd,IAAI,iBAAiB,YAAY;AAAA,MAC/B,kBAAkB,CAAC,MAAM,UAAU,GAAG,IAAI;AAAA,MAC1C,QAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,IACA,MAAM;AAAA;AAAA;AAIH,IAAM,eAAe,cAAc;AAAA,EACxC,MAAM;AAAA,IACJ,OAAO;AAAA,MACL,aACE;AAAA,MACF,MAAM;AAAA,IACR;AAAA,IACA,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,IAInC,IAAI,iBAAiB,IAAI,KAAK,CAAC,KAAK,OAAO;AAAA,MACzC,OAAO,MACL,oLACF;AAAA,MACA,QAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,IAEA,IAAI,CAAC,KAAK,KAAK;AAAA,MACb,OAAO,KACL,sPACF;AAAA,MACA,OAAO,KAAK,+BAA+B;AAAA,MAC3C;AAAA,IACF;AAAA,IAEA,QAAQ,cAAc,OAAO,aAAa,MAAM,YAAY,IAAI;AAAA,IAChE,MAAM,QAAQ,MAAM,qBAAqB,MAAM,YAAY;AAAA,IAI3D,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,KAAK,YAAY,YAAY,EAAE;AAAA,IAE9C,MAAM,MAAM,MAAM,SAAS,IAAI,CAAC,SAAS,KAAK,KAAK,IAAI,CAAC,KAAK,KAAK;AAAA,IAClE,MAAM,YACJ,MAAM,SAAS,IAAI,0BAA0B,MAAM,KAAK,IAAI;AAAA;AAAA,IAAW;AAAA,IACzE,OAAO,IACL;AAAA;AAAA,EAAkD,YAAY,IAAI,IAAI,CAAC,YAAY,KAAK,SAAS,EAAE,KAAK;AAAA,CAAI;AAAA;AAAA,sCAC9G;AAAA;AAEJ,CAAC;",
8
+ "debugId": "3D94285342361B2D64756E2164756E21",
9
9
  "names": []
10
10
  }
@@ -4,12 +4,12 @@
4
4
  var seconds = (ms) => `${(ms / 1000).toFixed(1)}s`;
5
5
  var money = (cost) => cost === undefined ? "" : `$${cost.toFixed(2)}`;
6
6
  var duration = (ms) => {
7
- if (ms < 60000) {
8
- return seconds(ms);
7
+ const tenths = Math.round(ms / 100);
8
+ if (tenths < 600) {
9
+ return `${(tenths / 10).toFixed(1)}s`;
9
10
  }
10
- const minutes = Math.floor(ms / 60000);
11
- const rest = Math.round(ms % 60000 / 1000);
12
- return `${minutes}m ${rest}s`;
11
+ const total = Math.round(ms / 1000);
12
+ return `${Math.floor(total / 60)}m ${total % 60}s`;
13
13
  };
14
14
 
15
15
  // src/eval/agents.ts
@@ -74,6 +74,7 @@ var runAgentHeadless = (bin, args, options) => new Promise((resolve, reject) =>
74
74
  resolve({ code: code ?? 1, stderr, stdout, timedOut });
75
75
  }
76
76
  });
77
+ child.stdin?.on("error", () => {});
77
78
  child.stdin?.end(options.prompt);
78
79
  });
79
80
  var writeMcpConfig = async (dir, snapshotPath, launcher) => {
@@ -234,7 +235,7 @@ var parseVerdict = (text) => {
234
235
  return result.success ? result.data : undefined;
235
236
  };
236
237
 
237
- export { seconds, money, duration, DISALLOWED_TOOLS, runAgentHeadless, writeMcpConfig, agentArgs, readAgentOutput, parseVerdict };
238
+ export { seconds, money, duration, DISALLOWED_TOOLS, runAgentHeadless, writeMcpConfig, CODEX_LOCKDOWN, agentArgs, readAgentOutput, parseVerdict };
238
239
 
239
- //# debugId=FE1BEE26F1BB6F4964756E2164756E21
240
- //# sourceMappingURL=chunk-fa25z98p.js.map
240
+ //# debugId=DE4C096172619DD564756E2164756E21
241
+ //# sourceMappingURL=chunk-ga0pf4aj.js.map
@@ -0,0 +1,11 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/cli/report-format.ts", "../src/eval/agents.ts"],
4
+ "sourcesContent": [
5
+ "/**\n * Number formatting shared by the translate and eval report renderers. The\n * `1.5s` / `4m 12s` shapes are asserted in both suites — change them in both\n * minds at once.\n */\n\n/** Milliseconds as `1.5s`. */\nexport const seconds = (ms: number): string => `${(ms / 1000).toFixed(1)}s`;\n\n/** A dollar cost as `$1.23`, or nothing when the run reported none. */\nexport const money = (cost: number | undefined): string =>\n cost === undefined ? \"\" : `$${cost.toFixed(2)}`;\n\n/**\n * Milliseconds as `12.3s` under a minute, `4m 12s` from there up. Rounding\n * happens before the split, so a value just under a boundary carries over\n * (`59_990` → `1m 0s`, `119_700` → `2m 0s`) instead of printing `60.0s` or\n * `1m 60s`.\n */\nexport const duration = (ms: number): string => {\n const tenths = Math.round(ms / 100);\n if (tenths < 600) {\n return `${(tenths / 10).toFixed(1)}s`;\n }\n const total = Math.round(ms / 1000);\n return `${Math.floor(total / 60)}m ${total % 60}s`;\n};\n",
6
+ "import { readFile, writeFile } from \"node:fs/promises\";\n\nimport spawn from \"cross-spawn\";\nimport { join } from \"pathe\";\nimport { z } from \"zod\";\n\nimport type { AgentKind } from \"../audit/agent.ts\";\n\n/** How long the SIGTERM on timeout gets to work before SIGKILL follows. */\nconst KILL_GRACE_MS = 5000;\n\n/** The MCP tools a reader run may use — nothing else. */\nexport const MCP_TOOL_NAMES = [\n \"search_docs\",\n \"get_page\",\n \"list_pages\",\n \"get_navigation\",\n] as const;\n\n/** The MCP server name in the generated config; tool ids derive from it. */\nconst MCP_SERVER_NAME = \"docs\";\n\n/**\n * Claude Code built-ins that would let the agent escape the docs-only\n * sandbox: the reader must not read the repo, run commands, or search the\n * web — it sees the documentation the way a stranger does, through MCP.\n */\nexport const DISALLOWED_TOOLS = [\n \"Bash\",\n \"Read\",\n \"Glob\",\n \"Grep\",\n \"Write\",\n \"Edit\",\n \"NotebookEdit\",\n \"WebFetch\",\n \"WebSearch\",\n \"Task\",\n];\n\n/** The captured outcome of one headless agent invocation. */\nexport interface HeadlessResult {\n code: number;\n stderr: string;\n stdout: string;\n timedOut: boolean;\n}\n\nexport interface HeadlessOptions {\n cwd: string;\n /** How long the SIGTERM gets before SIGKILL follows (default 5s). */\n killGraceMs?: number;\n prompt: string;\n timeoutMs: number;\n}\n\n/**\n * Run an agent CLI headlessly: prompt over stdin (dodging argv limits and\n * cmd.exe newline quoting alike), stdout and stderr captured, SIGTERM at the\n * deadline with a SIGKILL follow-up. Resolves with the captured result;\n * rejects only when the executable cannot be spawned at all (ENOENT).\n *\n * Spawned through cross-spawn, which runs npm's `.cmd` shims on Windows with\n * its own cmd.exe escaping — under the old `shell: true` launch, cmd.exe was\n * free to mangle the JSON carried by codex's `-c` arguments, and a missing\n * executable surfaced as exit code 9009 instead of an ENOENT rejection.\n * execa was evaluated and rejected here: it waits for the stdio streams to\n * close, and the `exit`-beats-`close` resolution below exists precisely\n * because a killed agent's own children (an MCP server, a shell) hold the\n * pipes open past the SIGTERM.\n */\nexport const runAgentHeadless = (\n bin: string,\n args: string[],\n options: HeadlessOptions\n): Promise<HeadlessResult> =>\n // oxlint-disable-next-line promise/avoid-new -- adapt spawn's event callbacks\n new Promise((resolve, reject) => {\n const child = spawn(bin, args, {\n cwd: options.cwd,\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n\n let stdout = \"\";\n let stderr = \"\";\n let timedOut = false;\n child.stdout?.on(\"data\", (chunk: Buffer) => {\n stdout += chunk.toString(\"utf-8\");\n });\n child.stderr?.on(\"data\", (chunk: Buffer) => {\n stderr += chunk.toString(\"utf-8\");\n });\n\n let hardKill: ReturnType<typeof setTimeout> | undefined;\n const deadline = setTimeout(() => {\n timedOut = true;\n child.kill(\"SIGTERM\");\n hardKill = setTimeout(\n () => child.kill(\"SIGKILL\"),\n options.killGraceMs ?? KILL_GRACE_MS\n );\n hardKill.unref();\n }, options.timeoutMs);\n deadline.unref();\n\n child.once(\"error\", (error) => {\n clearTimeout(deadline);\n reject(error);\n });\n child.once(\"close\", (code) => {\n clearTimeout(deadline);\n resolve({ code: code ?? 1, stderr, stdout, timedOut });\n });\n // `close` waits for the stdio pipes, which a killed agent's own children\n // (an MCP server, a shell) can hold open past the SIGTERM. A timed-out\n // run's output is discarded anyway, so the process dying is enough.\n child.once(\"exit\", (code) => {\n // Once the process is gone the SIGKILL follow-up has nothing to do, and\n // firing it later could signal an unrelated process that reused the pid.\n clearTimeout(hardKill);\n if (timedOut) {\n clearTimeout(deadline);\n resolve({ code: code ?? 1, stderr, stdout, timedOut });\n }\n });\n\n // An agent that exits before reading the whole prompt (it rejected a flag,\n // say) closes the pipe mid-write, and the resulting EPIPE would otherwise\n // be an uncaught exception that aborts the run. The exit itself is the\n // outcome: `close` resolves with the agent's code and stderr, which\n // `readAgentOutput` reports.\n child.stdin?.on(\"error\", () => {\n // Deliberately ignored — see above.\n });\n child.stdin?.end(options.prompt);\n });\n\n/** The spawn signature `runEval` accepts, injectable for tests. */\nexport type HeadlessRunner = typeof runAgentHeadless;\n\n/** How the eval reaches the MCP stdio bridge from a spawned agent. */\nexport interface McpLaunch {\n /** The generated MCP config file (claude's `--mcp-config`). */\n configPath: string;\n /** argv for the bridge process (codex's `-c mcp_servers` override). */\n serverArgs: string[];\n /** The executable launching the bridge. */\n serverCommand: string;\n}\n\n/**\n * Write the MCP config a reader run points its agent CLI at. The bridge is\n * this same CLI relaunched (`blume mcp-stdio`), which resolves correctly from\n * both a source checkout (bun + src/cli/index.ts) and an installed package\n * (node + bin/blume.mjs).\n */\nexport const writeMcpConfig = async (\n dir: string,\n snapshotPath: string,\n launcher?: { args: string[]; command: string }\n): Promise<McpLaunch> => {\n const resolved = launcher ?? {\n args: [process.argv[1] ?? \"\", \"mcp-stdio\", \"--data\", snapshotPath],\n command: process.execPath,\n };\n const configPath = join(dir, \"mcp-config.json\");\n const config = {\n mcpServers: {\n [MCP_SERVER_NAME]: { args: resolved.args, command: resolved.command },\n },\n };\n await writeFile(configPath, JSON.stringify(config, null, 2));\n return {\n configPath,\n serverArgs: resolved.args,\n serverCommand: resolved.command,\n };\n};\n\nexport interface InvocationContext {\n /** Where codex writes its final message; unused by claude. */\n lastMessagePath: string;\n /** The MCP bridge for reader runs; omitted for the judge. */\n mcp?: McpLaunch;\n}\n\nconst CLAUDE_READER_MAX_TURNS = \"25\";\nconst CLAUDE_JUDGE_MAX_TURNS = \"1\";\n\nconst claudeArgs = (context: InvocationContext): string[] => {\n const base = [\"-p\", \"--output-format\", \"json\", \"--strict-mcp-config\"];\n if (context.mcp) {\n const allowed = MCP_TOOL_NAMES.map(\n (tool) => `mcp__${MCP_SERVER_NAME}__${tool}`\n ).join(\",\");\n return [\n ...base,\n \"--mcp-config\",\n context.mcp.configPath,\n \"--allowedTools\",\n allowed,\n \"--disallowedTools\",\n DISALLOWED_TOOLS.join(\",\"),\n \"--max-turns\",\n CLAUDE_READER_MAX_TURNS,\n ];\n }\n return [\n ...base,\n \"--disallowedTools\",\n DISALLOWED_TOOLS.join(\",\"),\n \"--max-turns\",\n CLAUDE_JUDGE_MAX_TURNS,\n ];\n};\n\n/**\n * Codex config overrides that leave an eval run nothing but its prompt and the\n * docs MCP tools (and a `blume translate` run nothing but its prompt). `--sandbox read-only` blocks writes and the network but still\n * lets the shell tool read any file the user can, and the docs a reader\n * searches — or the answer a judge grades — can come from a remote source, so\n * an instruction planted there could otherwise pull a local secret into the\n * transcript sent to the model provider. With both command tools and the\n * local-image tool off, and any subprocess started with no inherited\n * environment, there is nothing on the machine for a run to read.\n */\nexport const CODEX_LOCKDOWN = [\n \"-c\",\n \"features.shell_tool=false\",\n \"-c\",\n \"features.unified_exec=false\",\n \"-c\",\n \"tools.view_image=false\",\n \"-c\",\n 'shell_environment_policy.inherit=\"none\"',\n];\n\nconst codexArgs = (context: InvocationContext): string[] => {\n const base = [\n \"exec\",\n \"--skip-git-repo-check\",\n \"--ignore-user-config\",\n \"--ephemeral\",\n \"--sandbox\",\n \"read-only\",\n ...CODEX_LOCKDOWN,\n \"--output-last-message\",\n context.lastMessagePath,\n ];\n if (context.mcp) {\n // `-c` values parse as TOML; JSON string/array literals are valid TOML\n // values, so JSON.stringify produces exactly the quoting codex expects.\n return [\n ...base,\n \"-c\",\n `mcp_servers.${MCP_SERVER_NAME}.command=${JSON.stringify(\n context.mcp.serverCommand\n )}`,\n \"-c\",\n `mcp_servers.${MCP_SERVER_NAME}.args=${JSON.stringify(\n context.mcp.serverArgs\n )}`,\n \"-\",\n ];\n }\n return [...base, \"-\"];\n};\n\n/** Build the argv for one headless run; pass `mcp` for the reader role. */\nexport const agentArgs = (\n kind: AgentKind,\n context: InvocationContext\n): string[] => (kind === \"claude\" ? claudeArgs(context) : codexArgs(context));\n\n/** What one headless run produced, normalized across agent CLIs. */\nexport interface AgentOutput {\n costUsd?: number;\n detail?: string;\n isError: boolean;\n text: string;\n}\n\nconst claudeResultSchema = z.object({\n is_error: z.boolean().default(false),\n result: z.string().default(\"\"),\n total_cost_usd: z.number().optional(),\n});\n\nconst tail = (value: string, max = 300): string => {\n const trimmed = value.trim();\n return trimmed.length > max ? trimmed.slice(-max) : trimmed;\n};\n\n/**\n * Normalize a finished run into the answer text. Claude prints one JSON\n * object on stdout (`--output-format json`); codex writes the final message\n * to `--output-last-message` because its stdout interleaves progress.\n */\nexport const readAgentOutput = async (\n kind: AgentKind,\n result: HeadlessResult,\n lastMessagePath: string\n): Promise<AgentOutput> => {\n if (result.timedOut) {\n return { detail: \"timed out\", isError: true, text: \"\" };\n }\n if (result.code !== 0) {\n return {\n detail: tail(result.stderr) || `exited with code ${result.code}`,\n isError: true,\n text: \"\",\n };\n }\n\n if (kind === \"claude\") {\n let parsed: unknown;\n try {\n parsed = JSON.parse(result.stdout);\n } catch {\n return {\n detail: \"unparseable --output-format json payload\",\n isError: true,\n text: \"\",\n };\n }\n const payload = claudeResultSchema.safeParse(parsed);\n if (!payload.success) {\n return {\n detail: \"unexpected --output-format json shape\",\n isError: true,\n text: \"\",\n };\n }\n return {\n costUsd: payload.data.total_cost_usd,\n isError: payload.data.is_error,\n text: payload.data.result,\n };\n }\n\n let text: string;\n try {\n const raw = await readFile(lastMessagePath, \"utf-8\");\n text = raw.trim();\n } catch {\n return { detail: \"no last message written\", isError: true, text: \"\" };\n }\n if (text === \"\") {\n return { detail: \"empty last message\", isError: true, text: \"\" };\n }\n return { isError: false, text };\n};\n\nconst verdictSchema = z.object({\n missing: z.array(z.string()).default([]),\n notes: z.string().default(\"\"),\n pass: z.boolean(),\n score: z.number().min(0).max(1).optional(),\n});\n\n/** The judge's grade for one answer. */\nexport type Verdict = z.infer<typeof verdictSchema>;\n\n/**\n * Extract the verdict JSON from a judge reply. Tolerates markdown fences and\n * surrounding prose; returns undefined when no valid verdict can be found.\n */\nexport const parseVerdict = (text: string): Verdict | undefined => {\n const start = text.indexOf(\"{\");\n const end = text.lastIndexOf(\"}\");\n if (start === -1 || end <= start) {\n return;\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(text.slice(start, end + 1));\n } catch {\n return;\n }\n const result = verdictSchema.safeParse(parsed);\n return result.success ? result.data : undefined;\n};\n"
7
+ ],
8
+ "mappings": "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",
9
+ "debugId": "DE4C096172619DD564756E2164756E21",
10
+ "names": []
11
+ }