blume 1.0.1 → 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,23 @@
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
+
11
+ ## 1.0.2
12
+
13
+ ### Patch Changes
14
+
15
+ - d62dbd0: Harden the pre-paint inline scripts and the route-normalizing regexes against the issues CodeQL flagged.
16
+
17
+ The theme and banner scripts in `<head>` used to be built by interpolating config values into JavaScript source with `JSON.stringify`. JSON escaping isn't a code-context escape — `</script>` and U+2028/U+2029 pass straight through it — so a crafted `banner.id` or theme value could break out of the script. Both scripts are now constants and take their values from `data-*` attributes on their own `<script>` tag, which Astro HTML-escapes. `ReferenceLayout` had drifted to its own inline copies of both scripts; it now shares the same module as `RootLayout` and `PageLayout`.
18
+
19
+ Route and slug normalization used `/^\/+|\/+$/`-style patterns to trim leading and trailing separators. Those take quadratic time on a long run of the trimmed character, and they run on values that come from outside Blume (configured routes, OpenAPI spec URLs, the site origin), so a pathological config could hang the build. They're replaced by linear trimming helpers in `core/trim.ts`; behavior is unchanged.
20
+
3
21
  ## 1.0.1
4
22
 
5
23
  ### Patch Changes
package/dist/cli/index.js CHANGED
@@ -536,7 +536,7 @@ var normalizeBasePath = (input) => {
536
536
  if (!input) {
537
537
  return "";
538
538
  }
539
- const trimmed = input.trim().replaceAll(/^\/+|\/+$/gu, "").replaceAll(/\/{2,}/gu, "/");
539
+ const trimmed = input.trim().split("/").filter(Boolean).join("/");
540
540
  return trimmed === "" ? "" : `/${trimmed}`;
541
541
  };
542
542
  var isInternalPath = (target) => target.startsWith("/") && !target.startsWith("//");
@@ -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,
@@ -4127,6 +4127,23 @@ var buildMcpData = async (project) => {
4127
4127
  };
4128
4128
  };
4129
4129
 
4130
+ // src/core/trim.ts
4131
+ var trimStart = (text, char) => {
4132
+ let start = 0;
4133
+ while (start < text.length && text[start] === char) {
4134
+ start += 1;
4135
+ }
4136
+ return text.slice(start);
4137
+ };
4138
+ var trimEnd = (text, char) => {
4139
+ let end = text.length;
4140
+ while (end > 0 && text[end - 1] === char) {
4141
+ end -= 1;
4142
+ }
4143
+ return text.slice(0, end);
4144
+ };
4145
+ var trimChar = (text, char) => trimEnd(trimStart(text, char), char);
4146
+
4130
4147
  // src/ai/mcp/tools.ts
4131
4148
  var READ_ONLY = { openWorldHint: false, readOnlyHint: true };
4132
4149
  var MCP_TOOLS = [
@@ -4159,7 +4176,7 @@ var MCP_TOOLS = [
4159
4176
  // src/ai/mcp/discovery.ts
4160
4177
  var serverUrl = (input) => {
4161
4178
  const path = withBasePath(input.base, input.route);
4162
- return input.site ? `${input.site.replace(/\/+$/u, "")}${path}` : path;
4179
+ return input.site ? `${trimEnd(input.site, "/")}${path}` : path;
4163
4180
  };
4164
4181
  var buildMcpDiscovery = (input) => ({
4165
4182
  servers: [
@@ -4829,17 +4846,14 @@ import { isAbsolute as isAbsolute5, join as join16, resolve as resolve5 } from "
4829
4846
 
4830
4847
  // src/openapi/references.ts
4831
4848
  var NON_SLUG = /[^a-z0-9]+/gu;
4832
- var SLUG_EDGES = /^-+|-+$/gu;
4833
- var ROUTE_EDGES = /^\/+|\/+$/gu;
4834
- var TRAILING_SLASH = /\/+$/u;
4835
- var slugify = (text) => text.toLowerCase().replace(NON_SLUG, "-").replace(SLUG_EDGES, "");
4849
+ var slugify = (text) => trimChar(text.toLowerCase().replace(NON_SLUG, "-"), "-");
4836
4850
  var normalizeRoute = (route) => {
4837
4851
  const trimmed = route.trim();
4838
4852
  const withSlash = trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
4839
- const noTrailing = withSlash.replace(TRAILING_SLASH, "");
4853
+ const noTrailing = trimEnd(withSlash, "/");
4840
4854
  return noTrailing === "" ? "/" : noTrailing;
4841
4855
  };
4842
- var routeSlug = (route) => slugify(route.replace(ROUTE_EDGES, "")) || "reference";
4856
+ var routeSlug = (route) => slugify(trimChar(route, "/")) || "reference";
4843
4857
  var sourcesOf = (block) => {
4844
4858
  const sources = [...block.sources];
4845
4859
  if (block.spec) {
@@ -5010,8 +5024,8 @@ var loadWithCache = async (name, cache, fetchEntries, refresh = true) => {
5010
5024
 
5011
5025
  // src/openapi/model.ts
5012
5026
  var NON_SLUG2 = /[^a-z0-9]+/gu;
5013
- var SLUG_EDGES2 = /^-+|-+$/gu;
5014
- var slugify2 = (text) => text.toLowerCase().replace(NON_SLUG2, "-").replace(SLUG_EDGES2, "");
5027
+ var SLUG_EDGES = /^-+|-+$/gu;
5028
+ var slugify2 = (text) => text.toLowerCase().replace(NON_SLUG2, "-").replace(SLUG_EDGES, "");
5015
5029
  var HTTP_METHODS = [
5016
5030
  "get",
5017
5031
  "put",
@@ -6363,6 +6377,12 @@ var askAiProviders = [
6363
6377
  "inkeep",
6364
6378
  "openai-compatible"
6365
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
+ });
6366
6386
  var aiConfigSchema = z2.strictObject({
6367
6387
  ask: z2.strictObject({
6368
6388
  apiKeyEnv: z2.string().optional(),
@@ -6392,7 +6412,8 @@ var aiConfigSchema = z2.strictObject({
6392
6412
  ]).default(true).transform((value) => typeof value === "boolean" ? { enabled: value, openapi: true } : value),
6393
6413
  markdownComponents: z2.record(z2.string(), z2.custom((value) => typeof value === "function", {
6394
6414
  message: "Expected a serializer function."
6395
- })).default({})
6415
+ })).default({}),
6416
+ mcp: mcpConfigSchema.default({})
6396
6417
  });
6397
6418
  var featuredLinkSchema = z2.strictObject({
6398
6419
  href: z2.string(),
@@ -6419,12 +6440,6 @@ var exportConfigSchema = z2.union([
6419
6440
  pdf: z2.boolean().default(false)
6420
6441
  })
6421
6442
  ]).transform((value) => typeof value === "boolean" ? { epub: value, pdf: value } : value);
6422
- var mcpConfigSchema = z2.strictObject({
6423
- enabled: z2.boolean().default(false),
6424
- instructions: z2.string().optional(),
6425
- name: z2.string().optional(),
6426
- route: z2.string().default("/mcp").transform(normalizeRoute)
6427
- });
6428
6443
  var localeSchema = z2.strictObject({
6429
6444
  code: z2.string().min(1),
6430
6445
  dir: z2.enum(["ltr", "rtl"]).default("ltr"),
@@ -6611,7 +6626,6 @@ var blumeConfigSchema = z2.strictObject({
6611
6626
  lastModified: lastModifiedConfigSchema.default(false),
6612
6627
  logo: logoConfigSchema.optional(),
6613
6628
  markdown: markdownConfigSchema.default({}),
6614
- mcp: mcpConfigSchema.default({}),
6615
6629
  navigation: navigationConfigSchema.default({}),
6616
6630
  openapi: openapiConfigSchema.default({}),
6617
6631
  react: reactConfigSchema.default({}),
@@ -7734,6 +7748,7 @@ var reactIntegration = (compilerPath) => compilerPath ? `react({ babel: { plugin
7734
7748
  var astroConfigTemplate = (options) => {
7735
7749
  const { context, config, needsReact, pages, dataPath, themePath } = options;
7736
7750
  const {
7751
+ askPath,
7737
7752
  contentRoutes,
7738
7753
  examplesPath,
7739
7754
  examplesThemePath,
@@ -7853,6 +7868,7 @@ export default defineConfig({
7853
7868
  },
7854
7869
  resolve: {
7855
7870
  alias: {
7871
+ "blume:ask": ${JSON.stringify(askPath)},
7856
7872
  "blume:data": ${JSON.stringify(dataPath)},
7857
7873
  "blume:examples": ${JSON.stringify(examplesPath)},
7858
7874
  "blume:examples-theme": ${JSON.stringify(examplesThemePath)},
@@ -8024,6 +8040,22 @@ ${setup}
8024
8040
  ${handler}
8025
8041
  `;
8026
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
+ `;
8027
8059
  var searchEndpointTemplate = () => `// Generated by Blume. Do not edit.
8028
8060
  import documents from "../generated/search.json";
8029
8061
 
@@ -8153,12 +8185,9 @@ export function GET({ props }) {
8153
8185
  });
8154
8186
  }
8155
8187
  `;
8156
- var mcpPageFile = (route) => {
8157
- const clean = route.replace(/^\/+/u, "").replace(/\/+$/u, "");
8158
- return `${clean}.ts`;
8159
- };
8188
+ var mcpPageFile = (route) => `${trimChar(route, "/")}.ts`;
8160
8189
  var mcpEndpointTemplate = (route) => {
8161
- const clean = route.replace(/^\/+/u, "").replace(/\/+$/u, "");
8190
+ const clean = trimChar(route, "/");
8162
8191
  const up = "../".repeat(clean.split("/").length);
8163
8192
  return `// Generated by Blume. Do not edit.
8164
8193
  import type { APIRoute } from "astro";
@@ -8306,10 +8335,6 @@ const htmlLang = i18n ? i18n.defaultLocale : "en";
8306
8335
  </ReferenceLayout>
8307
8336
  `;
8308
8337
  var catchAllPageTemplate = (options) => {
8309
- const askImport = options.askEnabled ? `import AskAI from "blume/components/islands/AskAI.astro";
8310
- ` : "";
8311
- const askSlot = options.askEnabled ? `
8312
- <AskAI slot="ask" strings={ui.ask} suggestions={data.config.ask?.suggestions ?? []} />` : "";
8313
8338
  const mathImport = options.mathEnabled ? `import Math from "blume/components/content/Math.astro";
8314
8339
  ` : "";
8315
8340
  const mathEntry = options.mathEnabled ? `Math,
@@ -8322,7 +8347,6 @@ import { getEntry, render } from "astro:content";
8322
8347
  import RootLayout from "blume/components/layout/RootLayout.astro";
8323
8348
  import { withBase } from "blume/components/islands/base-path.ts";
8324
8349
  import { resolveSlot } from "blume/components/layout/overrides.ts";
8325
- ${askImport}
8326
8350
  import Accordion from "blume/components/content/Accordion.astro";
8327
8351
  import AccordionItem from "blume/components/content/AccordionItem.astro";
8328
8352
  import AutoTypeTable from "blume/components/content/AutoTypeTable.astro";
@@ -8559,7 +8583,6 @@ const LayoutComponent = resolveSlot(layoutOverrides.Layout, RootLayout);
8559
8583
  canonical={canonical}
8560
8584
  editUrl={editUrl}
8561
8585
  feedback={data.config.feedback}
8562
- askEnabled={${options.askEnabled}}
8563
8586
  exportPdf={${options.exportPdf}}
8564
8587
  exportEpub={${options.exportEpub}}
8565
8588
  feeds={data.feeds}
@@ -8569,7 +8592,7 @@ const LayoutComponent = resolveSlot(layoutOverrides.Layout, RootLayout);
8569
8592
  lastModified={lastModified}
8570
8593
  noindex={seo.noindex}
8571
8594
  structuredDataEnabled={data.config.structuredData}
8572
- >${askSlot}
8595
+ >
8573
8596
  <h1>{title}</h1>
8574
8597
  {frontmatter.description && <p class="text-lg text-muted-foreground">{frontmatter.description}</p>}
8575
8598
  <Content components={components} />
@@ -8577,10 +8600,6 @@ const LayoutComponent = resolveSlot(layoutOverrides.Layout, RootLayout);
8577
8600
  `;
8578
8601
  };
8579
8602
  var changelogIndexTemplate = (options) => {
8580
- const askImport = options.askEnabled ? `import AskAI from "blume/components/islands/AskAI.astro";
8581
- ` : "";
8582
- const askSlot = options.askEnabled ? `
8583
- <AskAI slot="ask" strings={data.ui.ask} suggestions={data.config.ask?.suggestions ?? []} />` : "";
8584
8603
  const clientData = options.needsReact ? `
8585
8604
  clientData={{ config: data.config, navigation: data.navigation, page: { route: "/changelog", title: pageTitle } }}` : "";
8586
8605
  const stagedSpread = options.staged ? `
@@ -8593,7 +8612,7 @@ import Update from "blume/components/content/Update.astro";
8593
8612
  import { withBase } from "blume/components/islands/base-path.ts";
8594
8613
  import { resolveSlot } from "blume/components/layout/overrides.ts";
8595
8614
  import { layoutOverrides } from "../generated/components.ts";
8596
- ${askImport}import data from "../generated/data.json";
8615
+ import data from "../generated/data.json";
8597
8616
 
8598
8617
  export const prerender = true;
8599
8618
 
@@ -8762,14 +8781,13 @@ const LayoutComponent = resolveSlot(layoutOverrides.Layout, RootLayout);
8762
8781
  ogImage={null}
8763
8782
  x={data.config.x}
8764
8783
  canonical={canonical}
8765
- askEnabled={${options.askEnabled}}
8766
8784
  exportPdf={${options.exportPdf}}
8767
8785
  exportEpub={${options.exportEpub}}
8768
8786
  feeds={data.feeds}
8769
8787
  siteUrl={data.config.site}
8770
8788
  noindex={false}
8771
8789
  structuredDataEnabled={data.config.structuredData}
8772
- >${askSlot}
8790
+ >
8773
8791
  <h1>{changelogTitle}</h1>
8774
8792
  {
8775
8793
  items.length === 0 ? (
@@ -8989,6 +9007,11 @@ const Example = entry.Component;
8989
9007
  var envTemplate = () => `/// <reference path="../.astro/types.d.ts" />
8990
9008
  /// <reference types="astro/client" />
8991
9009
 
9010
+ declare module "blume:ask" {
9011
+ const Ask: typeof import("blume/components/islands/AskAI.astro").default;
9012
+ export default Ask;
9013
+ }
9014
+
8992
9015
  declare module "blume:data" {
8993
9016
  const data: import("blume").BlumeData;
8994
9017
  export default data;
@@ -9095,9 +9118,9 @@ ${dark}`;
9095
9118
 
9096
9119
  // src/openapi/scalar.ts
9097
9120
  var URL_SPEC2 = /^https?:\/\//u;
9098
- var ROUTE_EDGES2 = /^\/+|\/+$/gu;
9121
+ var ROUTE_EDGES = /^\/+|\/+$/gu;
9099
9122
  var referencePagePath = (route) => {
9100
- const segments = route.replace(ROUTE_EDGES2, "");
9123
+ const segments = route.replace(ROUTE_EDGES, "");
9101
9124
  return `${segments === "" ? "index" : segments}.astro`;
9102
9125
  };
9103
9126
  var darkModeConfig = (mode) => {
@@ -10536,7 +10559,10 @@ var buildRuntimeData = (project) => {
10536
10559
  } : null,
10537
10560
  imageZoom: config.markdown.imageZoom,
10538
10561
  logo: resolveLogo(project),
10539
- 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,
10540
10566
  og: { enabled: config.seo.og.enabled ?? false },
10541
10567
  repoUrl,
10542
10568
  search: {
@@ -10580,7 +10606,7 @@ var buildRuntimeData = (project) => {
10580
10606
  };
10581
10607
  var planMcp = (project, srcDir, userPages) => {
10582
10608
  const { config } = project;
10583
- const { route } = config.mcp;
10609
+ const { route } = config.ai.mcp;
10584
10610
  const dir = join22(srcDir, "blume-mcp");
10585
10611
  const base = {
10586
10612
  dir,
@@ -10590,14 +10616,14 @@ var planMcp = (project, srcDir, userPages) => {
10590
10616
  srcDir,
10591
10617
  warnings: []
10592
10618
  };
10593
- if (!config.mcp.enabled) {
10619
+ if (!config.ai.mcp.enabled) {
10594
10620
  return base;
10595
10621
  }
10596
10622
  if (routeIsTaken(userPages, project.graph.pages, route)) {
10597
10623
  return {
10598
10624
  ...base,
10599
10625
  warnings: [
10600
- `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.`
10601
10627
  ]
10602
10628
  };
10603
10629
  }
@@ -10666,6 +10692,7 @@ var generateRuntime = async (project) => {
10666
10692
  const { context, config } = project;
10667
10693
  const out = context.outDir;
10668
10694
  const srcDir = join22(out, "src");
10695
+ const askPath = join22(srcDir, "generated", "Ask.astro");
10669
10696
  const dataPath = join22(srcDir, "generated", "data.json");
10670
10697
  const themePath = join22(srcDir, "generated", "app.css");
10671
10698
  const searchClientPath = join22(srcDir, "generated", "search-client.ts");
@@ -10724,6 +10751,7 @@ var generateRuntime = async (project) => {
10724
10751
  Promise.all([
10725
10752
  write(join22(out, "astro.config.mjs"), astroConfigTemplate({
10726
10753
  aliases: resolveTsconfigAliases(context.root),
10754
+ askPath,
10727
10755
  config,
10728
10756
  contentRoutes: project.manifest.routes.map((route) => route.path),
10729
10757
  context,
@@ -10750,12 +10778,12 @@ var generateRuntime = async (project) => {
10750
10778
  staged: hasStaged
10751
10779
  })),
10752
10780
  write(join22(srcDir, "pages", "[...slug].astro"), catchAllPageTemplate({
10753
- askEnabled,
10754
10781
  exportEpub,
10755
10782
  exportPdf,
10756
10783
  mathEnabled: usesMath,
10757
10784
  needsReact
10758
10785
  })),
10786
+ write(askPath, askComponentTemplate(askEnabled)),
10759
10787
  write(join22(srcDir, "generated", "components.ts"), slotPlan.module),
10760
10788
  write(join22(srcDir, "generated", "islands.ts"), islandMapTemplate(islandDiscovery.islands)),
10761
10789
  write(join22(srcDir, "generated", "examples.ts"), exampleMapTemplate(exampleDiscovery.examples, config.basePath)),
@@ -10785,7 +10813,6 @@ var generateRuntime = async (project) => {
10785
10813
  }
10786
10814
  if (hasGeneratedChangelog(project, pages)) {
10787
10815
  await write(join22(srcDir, "pages", "changelog.astro"), changelogIndexTemplate({
10788
- askEnabled,
10789
10816
  exportEpub,
10790
10817
  exportPdf,
10791
10818
  needsReact,
@@ -12520,7 +12547,7 @@ var askFiles = async (project, srcDir, genDir) => {
12520
12547
  }
12521
12548
  return files;
12522
12549
  };
12523
- 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);
12524
12551
  var mcpDiscoveryPages = (project, userPages) => hostsMcp(project, userPages) ? [
12525
12552
  {
12526
12553
  entrypoint: "src/blume-mcp/discovery.ts",
@@ -12535,7 +12562,7 @@ var mcpFiles = async (project, userPages, srcDir, genDir) => {
12535
12562
  if (!hostsMcp(project, userPages)) {
12536
12563
  return [];
12537
12564
  }
12538
- const { route } = project.config.mcp;
12565
+ const { route } = project.config.ai.mcp;
12539
12566
  const data = await buildMcpData(project);
12540
12567
  const discoveryInput = {
12541
12568
  base: data.base,
@@ -12638,6 +12665,7 @@ var eject = async (root) => {
12638
12665
  const files = [
12639
12666
  {
12640
12667
  content: astroConfigTemplate({
12668
+ askPath: "./src/generated/Ask.astro",
12641
12669
  config,
12642
12670
  contentRoutes: project.manifest.routes.map((route) => route.path),
12643
12671
  context: relContext,
@@ -12671,7 +12699,6 @@ var eject = async (root) => {
12671
12699
  },
12672
12700
  {
12673
12701
  content: catchAllPageTemplate({
12674
- askEnabled,
12675
12702
  exportEpub,
12676
12703
  exportPdf,
12677
12704
  mathEnabled: usesMath,
@@ -12712,6 +12739,10 @@ var eject = async (root) => {
12712
12739
  path: join27(genDir, "app.css")
12713
12740
  },
12714
12741
  { content: buildRuntimeData(project), path: join27(genDir, "data.json") },
12742
+ {
12743
+ content: askComponentTemplate(askEnabled),
12744
+ path: join27(genDir, "Ask.astro")
12745
+ },
12715
12746
  {
12716
12747
  content: `${JSON.stringify(ejectOpenApiData(project))}
12717
12748
  `,
@@ -12741,7 +12772,6 @@ var eject = async (root) => {
12741
12772
  });
12742
12773
  }
12743
12774
  files.push(...await mcpFiles(project, pages, srcDir, genDir), ...changelogFiles(project, pages, srcDir, {
12744
- askEnabled,
12745
12775
  exportEpub,
12746
12776
  exportPdf,
12747
12777
  needsReact,
@@ -13836,5 +13866,5 @@ process.on("unhandledRejection", (error) => {
13836
13866
  });
13837
13867
  runMain(main);
13838
13868
 
13839
- //# debugId=066FB7264FFC708364756E2164756E21
13869
+ //# debugId=C36C25DD63079AEA64756E2164756E21
13840
13870
  //# sourceMappingURL=index.js.map