blume 1.0.2 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # blume
2
2
 
3
+ ## 1.0.3
4
+
5
+ ### Patch Changes
6
+
7
+ - e2f902c: Render the Ask AI trigger from the shared header instead of wiring it up per page. Custom pages built on `PageLayout` (a landing page, most of all) never passed the header's `ask` slot, so the Ask AI button — and the search modal's hand-off to it — silently went missing on them while the generated docs, changelog, and reference pages had it. The header now owns the trigger and reads whether Ask AI is on from the config, so every page gets it; pass `askEnabled={false}` to opt a page out.
8
+ - 66b721b: Move the MCP server config under `ai` in `blume.config.ts`, alongside the other agent-facing features. Rename `mcp: { … }` to `ai: { mcp: { … } }` — the shape of the block is unchanged.
9
+ - c8ae77e: Fix `ERR_MODULE_NOT_FOUND` in a deployed server function. Surfacing an adapter's deploy bundle out of `.blume` resolved every traced dependency's symlink against the source dir, so the links pointed into a directory the same step then deleted — the function died on its first external import (`Cannot find package '@orama/orama'` with Ask AI or the MCP server enabled). The bundle is now copied verbatim, leaving those links relative and internal to it.
10
+
3
11
  ## 1.0.2
4
12
 
5
13
  ### Patch Changes
package/dist/cli/index.js CHANGED
@@ -676,10 +676,10 @@ var buildAgentReadability = (project) => {
676
676
  artifacts.llmsFullTxt = abs("/llms-full.txt");
677
677
  artifacts.llmsTxt = abs("/llms.txt");
678
678
  }
679
- if (config.mcp.enabled) {
679
+ if (config.ai.mcp.enabled) {
680
680
  artifacts.mcp = {
681
681
  discovery: abs("/.well-known/mcp.json"),
682
- url: abs(config.mcp.route)
682
+ url: abs(config.ai.mcp.route)
683
683
  };
684
684
  }
685
685
  if (config.ai.ask?.enabled) {
@@ -697,7 +697,7 @@ var buildAgentReadability = (project) => {
697
697
  artifacts,
698
698
  description: config.description,
699
699
  generator: version ? `blume@${version}` : undefined,
700
- name: config.mcp.name ?? config.title,
700
+ name: config.ai.mcp.name ?? config.title,
701
701
  site
702
702
  };
703
703
  const usage = usagePolicy(config.seo.contentSignals);
@@ -1225,7 +1225,7 @@ var serverFeatures = (config) => {
1225
1225
  if (config.ai.ask?.enabled) {
1226
1226
  features.push("Ask AI");
1227
1227
  }
1228
- if (config.mcp.enabled) {
1228
+ if (config.ai.mcp.enabled) {
1229
1229
  features.push("MCP server");
1230
1230
  }
1231
1231
  if (searchProviderMeta(config.search.provider).requiresServer) {
@@ -1269,7 +1269,7 @@ var surfaceAdapterOutput = async (config, context) => {
1269
1269
  }
1270
1270
  await mkdir2(dirname4(to), { recursive: true });
1271
1271
  await rm(to, { force: true, recursive: true });
1272
- await cp(from, to, { recursive: true });
1272
+ await cp(from, to, { recursive: true, verbatimSymlinks: true });
1273
1273
  await rm(from, { force: true, recursive: true });
1274
1274
  return { from, ignore: `${rel.split("/")[0]}/`, moved: true, to };
1275
1275
  };
@@ -4117,8 +4117,8 @@ var buildMcpData = async (project) => {
4117
4117
  route: doc.route,
4118
4118
  title: doc.title
4119
4119
  })),
4120
- instructions: config.mcp.instructions,
4121
- name: config.mcp.name ?? config.title,
4120
+ instructions: config.ai.mcp.instructions,
4121
+ name: config.ai.mcp.name ?? config.title,
4122
4122
  navigation: graph.navigation,
4123
4123
  pages,
4124
4124
  routes,
@@ -6377,6 +6377,12 @@ var askAiProviders = [
6377
6377
  "inkeep",
6378
6378
  "openai-compatible"
6379
6379
  ];
6380
+ var mcpConfigSchema = z2.strictObject({
6381
+ enabled: z2.boolean().default(false),
6382
+ instructions: z2.string().optional(),
6383
+ name: z2.string().optional(),
6384
+ route: z2.string().default("/mcp").transform(normalizeRoute)
6385
+ });
6380
6386
  var aiConfigSchema = z2.strictObject({
6381
6387
  ask: z2.strictObject({
6382
6388
  apiKeyEnv: z2.string().optional(),
@@ -6406,7 +6412,8 @@ var aiConfigSchema = z2.strictObject({
6406
6412
  ]).default(true).transform((value) => typeof value === "boolean" ? { enabled: value, openapi: true } : value),
6407
6413
  markdownComponents: z2.record(z2.string(), z2.custom((value) => typeof value === "function", {
6408
6414
  message: "Expected a serializer function."
6409
- })).default({})
6415
+ })).default({}),
6416
+ mcp: mcpConfigSchema.default({})
6410
6417
  });
6411
6418
  var featuredLinkSchema = z2.strictObject({
6412
6419
  href: z2.string(),
@@ -6433,12 +6440,6 @@ var exportConfigSchema = z2.union([
6433
6440
  pdf: z2.boolean().default(false)
6434
6441
  })
6435
6442
  ]).transform((value) => typeof value === "boolean" ? { epub: value, pdf: value } : value);
6436
- var mcpConfigSchema = z2.strictObject({
6437
- enabled: z2.boolean().default(false),
6438
- instructions: z2.string().optional(),
6439
- name: z2.string().optional(),
6440
- route: z2.string().default("/mcp").transform(normalizeRoute)
6441
- });
6442
6443
  var localeSchema = z2.strictObject({
6443
6444
  code: z2.string().min(1),
6444
6445
  dir: z2.enum(["ltr", "rtl"]).default("ltr"),
@@ -6625,7 +6626,6 @@ var blumeConfigSchema = z2.strictObject({
6625
6626
  lastModified: lastModifiedConfigSchema.default(false),
6626
6627
  logo: logoConfigSchema.optional(),
6627
6628
  markdown: markdownConfigSchema.default({}),
6628
- mcp: mcpConfigSchema.default({}),
6629
6629
  navigation: navigationConfigSchema.default({}),
6630
6630
  openapi: openapiConfigSchema.default({}),
6631
6631
  react: reactConfigSchema.default({}),
@@ -7748,6 +7748,7 @@ var reactIntegration = (compilerPath) => compilerPath ? `react({ babel: { plugin
7748
7748
  var astroConfigTemplate = (options) => {
7749
7749
  const { context, config, needsReact, pages, dataPath, themePath } = options;
7750
7750
  const {
7751
+ askPath,
7751
7752
  contentRoutes,
7752
7753
  examplesPath,
7753
7754
  examplesThemePath,
@@ -7867,6 +7868,7 @@ export default defineConfig({
7867
7868
  },
7868
7869
  resolve: {
7869
7870
  alias: {
7871
+ "blume:ask": ${JSON.stringify(askPath)},
7870
7872
  "blume:data": ${JSON.stringify(dataPath)},
7871
7873
  "blume:examples": ${JSON.stringify(examplesPath)},
7872
7874
  "blume:examples-theme": ${JSON.stringify(examplesThemePath)},
@@ -8038,6 +8040,22 @@ ${setup}
8038
8040
  ${handler}
8039
8041
  `;
8040
8042
  };
8043
+ var askComponentTemplate = (askEnabled) => askEnabled ? `---
8044
+ // Generated by Blume. Do not edit.
8045
+ import AskAI from "blume/components/islands/AskAI.astro";
8046
+ import data from "blume:data";
8047
+
8048
+ const { strings } = Astro.props;
8049
+ ---
8050
+
8051
+ <AskAI strings={strings ?? data.ui.ask} suggestions={data.config.ask?.suggestions ?? []} />
8052
+ ` : `---
8053
+ // Generated by Blume. Do not edit.
8054
+ // Ask AI is off (\`ai.ask.enabled\`), so the header's Ask trigger renders nothing.
8055
+ // Deliberately imports no React island, keeping the JSX renderer out of projects
8056
+ // that don't need it.
8057
+ ---
8058
+ `;
8041
8059
  var searchEndpointTemplate = () => `// Generated by Blume. Do not edit.
8042
8060
  import documents from "../generated/search.json";
8043
8061
 
@@ -8317,10 +8335,6 @@ const htmlLang = i18n ? i18n.defaultLocale : "en";
8317
8335
  </ReferenceLayout>
8318
8336
  `;
8319
8337
  var catchAllPageTemplate = (options) => {
8320
- const askImport = options.askEnabled ? `import AskAI from "blume/components/islands/AskAI.astro";
8321
- ` : "";
8322
- const askSlot = options.askEnabled ? `
8323
- <AskAI slot="ask" strings={ui.ask} suggestions={data.config.ask?.suggestions ?? []} />` : "";
8324
8338
  const mathImport = options.mathEnabled ? `import Math from "blume/components/content/Math.astro";
8325
8339
  ` : "";
8326
8340
  const mathEntry = options.mathEnabled ? `Math,
@@ -8333,7 +8347,6 @@ import { getEntry, render } from "astro:content";
8333
8347
  import RootLayout from "blume/components/layout/RootLayout.astro";
8334
8348
  import { withBase } from "blume/components/islands/base-path.ts";
8335
8349
  import { resolveSlot } from "blume/components/layout/overrides.ts";
8336
- ${askImport}
8337
8350
  import Accordion from "blume/components/content/Accordion.astro";
8338
8351
  import AccordionItem from "blume/components/content/AccordionItem.astro";
8339
8352
  import AutoTypeTable from "blume/components/content/AutoTypeTable.astro";
@@ -8570,7 +8583,6 @@ const LayoutComponent = resolveSlot(layoutOverrides.Layout, RootLayout);
8570
8583
  canonical={canonical}
8571
8584
  editUrl={editUrl}
8572
8585
  feedback={data.config.feedback}
8573
- askEnabled={${options.askEnabled}}
8574
8586
  exportPdf={${options.exportPdf}}
8575
8587
  exportEpub={${options.exportEpub}}
8576
8588
  feeds={data.feeds}
@@ -8580,7 +8592,7 @@ const LayoutComponent = resolveSlot(layoutOverrides.Layout, RootLayout);
8580
8592
  lastModified={lastModified}
8581
8593
  noindex={seo.noindex}
8582
8594
  structuredDataEnabled={data.config.structuredData}
8583
- >${askSlot}
8595
+ >
8584
8596
  <h1>{title}</h1>
8585
8597
  {frontmatter.description && <p class="text-lg text-muted-foreground">{frontmatter.description}</p>}
8586
8598
  <Content components={components} />
@@ -8588,10 +8600,6 @@ const LayoutComponent = resolveSlot(layoutOverrides.Layout, RootLayout);
8588
8600
  `;
8589
8601
  };
8590
8602
  var changelogIndexTemplate = (options) => {
8591
- const askImport = options.askEnabled ? `import AskAI from "blume/components/islands/AskAI.astro";
8592
- ` : "";
8593
- const askSlot = options.askEnabled ? `
8594
- <AskAI slot="ask" strings={data.ui.ask} suggestions={data.config.ask?.suggestions ?? []} />` : "";
8595
8603
  const clientData = options.needsReact ? `
8596
8604
  clientData={{ config: data.config, navigation: data.navigation, page: { route: "/changelog", title: pageTitle } }}` : "";
8597
8605
  const stagedSpread = options.staged ? `
@@ -8604,7 +8612,7 @@ import Update from "blume/components/content/Update.astro";
8604
8612
  import { withBase } from "blume/components/islands/base-path.ts";
8605
8613
  import { resolveSlot } from "blume/components/layout/overrides.ts";
8606
8614
  import { layoutOverrides } from "../generated/components.ts";
8607
- ${askImport}import data from "../generated/data.json";
8615
+ import data from "../generated/data.json";
8608
8616
 
8609
8617
  export const prerender = true;
8610
8618
 
@@ -8773,14 +8781,13 @@ const LayoutComponent = resolveSlot(layoutOverrides.Layout, RootLayout);
8773
8781
  ogImage={null}
8774
8782
  x={data.config.x}
8775
8783
  canonical={canonical}
8776
- askEnabled={${options.askEnabled}}
8777
8784
  exportPdf={${options.exportPdf}}
8778
8785
  exportEpub={${options.exportEpub}}
8779
8786
  feeds={data.feeds}
8780
8787
  siteUrl={data.config.site}
8781
8788
  noindex={false}
8782
8789
  structuredDataEnabled={data.config.structuredData}
8783
- >${askSlot}
8790
+ >
8784
8791
  <h1>{changelogTitle}</h1>
8785
8792
  {
8786
8793
  items.length === 0 ? (
@@ -9000,6 +9007,11 @@ const Example = entry.Component;
9000
9007
  var envTemplate = () => `/// <reference path="../.astro/types.d.ts" />
9001
9008
  /// <reference types="astro/client" />
9002
9009
 
9010
+ declare module "blume:ask" {
9011
+ const Ask: typeof import("blume/components/islands/AskAI.astro").default;
9012
+ export default Ask;
9013
+ }
9014
+
9003
9015
  declare module "blume:data" {
9004
9016
  const data: import("blume").BlumeData;
9005
9017
  export default data;
@@ -10547,7 +10559,10 @@ var buildRuntimeData = (project) => {
10547
10559
  } : null,
10548
10560
  imageZoom: config.markdown.imageZoom,
10549
10561
  logo: resolveLogo(project),
10550
- mcp: config.mcp.enabled ? { name: config.mcp.name ?? config.title, route: config.mcp.route } : null,
10562
+ mcp: config.ai.mcp.enabled ? {
10563
+ name: config.ai.mcp.name ?? config.title,
10564
+ route: config.ai.mcp.route
10565
+ } : null,
10551
10566
  og: { enabled: config.seo.og.enabled ?? false },
10552
10567
  repoUrl,
10553
10568
  search: {
@@ -10591,7 +10606,7 @@ var buildRuntimeData = (project) => {
10591
10606
  };
10592
10607
  var planMcp = (project, srcDir, userPages) => {
10593
10608
  const { config } = project;
10594
- const { route } = config.mcp;
10609
+ const { route } = config.ai.mcp;
10595
10610
  const dir = join22(srcDir, "blume-mcp");
10596
10611
  const base = {
10597
10612
  dir,
@@ -10601,14 +10616,14 @@ var planMcp = (project, srcDir, userPages) => {
10601
10616
  srcDir,
10602
10617
  warnings: []
10603
10618
  };
10604
- if (!config.mcp.enabled) {
10619
+ if (!config.ai.mcp.enabled) {
10605
10620
  return base;
10606
10621
  }
10607
10622
  if (routeIsTaken(userPages, project.graph.pages, route)) {
10608
10623
  return {
10609
10624
  ...base,
10610
10625
  warnings: [
10611
- `MCP server route "${route}" is already used by a content or custom page; the MCP server was not generated. Set a different "mcp.route" in blume.config.ts.`
10626
+ `MCP server route "${route}" is already used by a content or custom page; the MCP server was not generated. Set a different "ai.mcp.route" in blume.config.ts.`
10612
10627
  ]
10613
10628
  };
10614
10629
  }
@@ -10677,6 +10692,7 @@ var generateRuntime = async (project) => {
10677
10692
  const { context, config } = project;
10678
10693
  const out = context.outDir;
10679
10694
  const srcDir = join22(out, "src");
10695
+ const askPath = join22(srcDir, "generated", "Ask.astro");
10680
10696
  const dataPath = join22(srcDir, "generated", "data.json");
10681
10697
  const themePath = join22(srcDir, "generated", "app.css");
10682
10698
  const searchClientPath = join22(srcDir, "generated", "search-client.ts");
@@ -10735,6 +10751,7 @@ var generateRuntime = async (project) => {
10735
10751
  Promise.all([
10736
10752
  write(join22(out, "astro.config.mjs"), astroConfigTemplate({
10737
10753
  aliases: resolveTsconfigAliases(context.root),
10754
+ askPath,
10738
10755
  config,
10739
10756
  contentRoutes: project.manifest.routes.map((route) => route.path),
10740
10757
  context,
@@ -10761,12 +10778,12 @@ var generateRuntime = async (project) => {
10761
10778
  staged: hasStaged
10762
10779
  })),
10763
10780
  write(join22(srcDir, "pages", "[...slug].astro"), catchAllPageTemplate({
10764
- askEnabled,
10765
10781
  exportEpub,
10766
10782
  exportPdf,
10767
10783
  mathEnabled: usesMath,
10768
10784
  needsReact
10769
10785
  })),
10786
+ write(askPath, askComponentTemplate(askEnabled)),
10770
10787
  write(join22(srcDir, "generated", "components.ts"), slotPlan.module),
10771
10788
  write(join22(srcDir, "generated", "islands.ts"), islandMapTemplate(islandDiscovery.islands)),
10772
10789
  write(join22(srcDir, "generated", "examples.ts"), exampleMapTemplate(exampleDiscovery.examples, config.basePath)),
@@ -10796,7 +10813,6 @@ var generateRuntime = async (project) => {
10796
10813
  }
10797
10814
  if (hasGeneratedChangelog(project, pages)) {
10798
10815
  await write(join22(srcDir, "pages", "changelog.astro"), changelogIndexTemplate({
10799
- askEnabled,
10800
10816
  exportEpub,
10801
10817
  exportPdf,
10802
10818
  needsReact,
@@ -12531,7 +12547,7 @@ var askFiles = async (project, srcDir, genDir) => {
12531
12547
  }
12532
12548
  return files;
12533
12549
  };
12534
- var hostsMcp = (project, userPages) => project.config.mcp.enabled && !routeIsTaken(userPages, project.graph.pages, project.config.mcp.route);
12550
+ var hostsMcp = (project, userPages) => project.config.ai.mcp.enabled && !routeIsTaken(userPages, project.graph.pages, project.config.ai.mcp.route);
12535
12551
  var mcpDiscoveryPages = (project, userPages) => hostsMcp(project, userPages) ? [
12536
12552
  {
12537
12553
  entrypoint: "src/blume-mcp/discovery.ts",
@@ -12546,7 +12562,7 @@ var mcpFiles = async (project, userPages, srcDir, genDir) => {
12546
12562
  if (!hostsMcp(project, userPages)) {
12547
12563
  return [];
12548
12564
  }
12549
- const { route } = project.config.mcp;
12565
+ const { route } = project.config.ai.mcp;
12550
12566
  const data = await buildMcpData(project);
12551
12567
  const discoveryInput = {
12552
12568
  base: data.base,
@@ -12649,6 +12665,7 @@ var eject = async (root) => {
12649
12665
  const files = [
12650
12666
  {
12651
12667
  content: astroConfigTemplate({
12668
+ askPath: "./src/generated/Ask.astro",
12652
12669
  config,
12653
12670
  contentRoutes: project.manifest.routes.map((route) => route.path),
12654
12671
  context: relContext,
@@ -12682,7 +12699,6 @@ var eject = async (root) => {
12682
12699
  },
12683
12700
  {
12684
12701
  content: catchAllPageTemplate({
12685
- askEnabled,
12686
12702
  exportEpub,
12687
12703
  exportPdf,
12688
12704
  mathEnabled: usesMath,
@@ -12723,6 +12739,10 @@ var eject = async (root) => {
12723
12739
  path: join27(genDir, "app.css")
12724
12740
  },
12725
12741
  { content: buildRuntimeData(project), path: join27(genDir, "data.json") },
12742
+ {
12743
+ content: askComponentTemplate(askEnabled),
12744
+ path: join27(genDir, "Ask.astro")
12745
+ },
12726
12746
  {
12727
12747
  content: `${JSON.stringify(ejectOpenApiData(project))}
12728
12748
  `,
@@ -12752,7 +12772,6 @@ var eject = async (root) => {
12752
12772
  });
12753
12773
  }
12754
12774
  files.push(...await mcpFiles(project, pages, srcDir, genDir), ...changelogFiles(project, pages, srcDir, {
12755
- askEnabled,
12756
12775
  exportEpub,
12757
12776
  exportPdf,
12758
12777
  needsReact,
@@ -13847,5 +13866,5 @@ process.on("unhandledRejection", (error) => {
13847
13866
  });
13848
13867
  runMain(main);
13849
13868
 
13850
- //# debugId=5F5E50EAF35B586A64756E2164756E21
13869
+ //# debugId=C36C25DD63079AEA64756E2164756E21
13851
13870
  //# sourceMappingURL=index.js.map