create-fornix 0.0.3 → 0.0.5

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/dist/index.js CHANGED
@@ -8,9 +8,9 @@ import { defineCommand as defineCommand8 } from "citty";
8
8
 
9
9
  // src/cli/commands/create.ts
10
10
  import { defineCommand } from "citty";
11
- import { resolve, basename as basename2 } from "path";
12
- import { mkdirSync as mkdirSync2, writeFileSync as writeFileSync2 } from "fs";
13
- import { join as join4 } from "path";
11
+ import { resolve as resolve2, basename as basename2 } from "path";
12
+ import { mkdirSync as mkdirSync4, writeFileSync as writeFileSync3 } from "fs";
13
+ import { join as join6 } from "path";
14
14
  import * as p2 from "@clack/prompts";
15
15
  import pc3 from "picocolors";
16
16
 
@@ -213,7 +213,7 @@ function topologicalSort(blocks, manifests) {
213
213
  }
214
214
 
215
215
  // src/scaffold/structure-generator.ts
216
- function generateStructure(config) {
216
+ function generateStructure(config, manifests = []) {
217
217
  const files = {};
218
218
  const adapterDeps = getAdapterDependencies(config);
219
219
  const pkg = {
@@ -278,16 +278,35 @@ pnpm-debug.log*
278
278
  .DS_Store
279
279
  Thumbs.db
280
280
  `.trim() + "\n";
281
- files["src/pages/index.astro"] = `
281
+ const blockImports = [];
282
+ const blockComponents = [];
283
+ if (manifests.length > 0) {
284
+ for (const manifest2 of manifests) {
285
+ if (manifest2.type !== "section") continue;
286
+ const mainFile = manifest2.files.find((f) => f.destination.endsWith(".astro") || f.destination.endsWith(".tsx"));
287
+ if (mainFile) {
288
+ const componentName = manifest2.name.split("-").map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
289
+ let importPath = mainFile.destination;
290
+ if (importPath.startsWith("src/")) {
291
+ importPath = "../" + importPath.substring(4);
292
+ }
293
+ blockImports.push(`import ${componentName} from '${importPath}';`);
294
+ blockComponents.push(` <${componentName} />`);
295
+ }
296
+ }
297
+ }
298
+ const indexAstroContent = `
282
299
  ---
283
300
  import Layout from '../layouts/Layout.astro';
301
+ ${blockImports.join("\n")}
284
302
  ---
285
- <Layout title="Welcome to Astro.">
303
+ <Layout title="Welcome to ${config.projectName}.">
286
304
  <main>
287
- <h1>Welcome to <span class="text-gradient">${config.projectName}</span></h1>
305
+ ${blockComponents.length > 0 ? blockComponents.join("\n") : ` <h1>Welcome to <span class="text-gradient">${config.projectName}</span></h1>`}
288
306
  </main>
289
307
  </Layout>
290
- `.trim() + "\n";
308
+ `.trim() + "\\n";
309
+ files["src/pages/index.astro"] = indexAstroContent;
291
310
  files["src/layouts/Layout.astro"] = `
292
311
  ---
293
312
  interface Props {
@@ -584,11 +603,12 @@ function generateContentConfig(blocks) {
584
603
  'import { defineCollection, z } from "astro:content";'
585
604
  ];
586
605
  const collections = [];
606
+ const dataCollections = /* @__PURE__ */ new Map();
587
607
  for (const block of blocks) {
588
608
  if (block.collections && block.collections.length > 0) {
589
609
  for (const col of block.collections) {
590
610
  const importName = `${block.name.replace(/-/g, "")}${col.name}Schema`;
591
- const importPath = col.schemaSource.replace(/\.ts$/, "");
611
+ const importPath = col.schemaSource.replace(/\\.ts$/, "");
592
612
  imports.push(`import { schema as ${importName} } from "${importPath}";`);
593
613
  collections.push(
594
614
  ` "${col.name}": defineCollection({
@@ -600,17 +620,30 @@ function generateContentConfig(blocks) {
600
620
  }
601
621
  const slots = block.ai?.contentSlots;
602
622
  if (slots && Object.keys(slots).length > 0) {
603
- const schemaFields = Object.entries(slots).map(([name, slot]) => ` ${name}: ${zodTypeForSlot(slot)},`).join("\n");
604
- collections.push(
605
- ` "${block.name}": defineCollection({
606
- type: "data",
607
- schema: z.object({
623
+ const schemaFields = Object.entries(slots).map(([name, slot]) => ` ${name}: ${zodTypeForSlot(slot)}.optional(),`).join("\n");
624
+ const subdirectory = TYPE_DIRECTORY[block.type] ?? block.type;
625
+ if (!dataCollections.has(subdirectory)) {
626
+ dataCollections.set(subdirectory, []);
627
+ }
628
+ dataCollections.get(subdirectory).push(
629
+ ` // ${block.name}
630
+ z.object({
608
631
  ${schemaFields}
609
- }),
610
- })`
632
+ })`
611
633
  );
612
634
  }
613
635
  }
636
+ for (const [colName, schemas] of dataCollections.entries()) {
637
+ const schemaStr = schemas.length === 1 ? schemas[0] : `z.union([
638
+ ${schemas.join(",\n")}
639
+ ])`;
640
+ collections.push(
641
+ ` "${colName}": defineCollection({
642
+ type: "data",
643
+ schema: ${schemaStr},
644
+ })`
645
+ );
646
+ }
614
647
  const lines = [
615
648
  ...imports,
616
649
  "",
@@ -789,13 +822,13 @@ function scaffold(input) {
789
822
  const selectedBlockNames = config.blocks.map((block) => block.name);
790
823
  const dependencyResult = resolveDependencies(selectedBlockNames, manifests);
791
824
  if (!isOk(dependencyResult)) {
792
- return err(new Error(`Dependency resolution failed: ${dependencyResult.error.message}`));
825
+ return err(Object.assign(new Error(dependencyResult.error.message), dependencyResult.error));
793
826
  }
794
827
  const resolvedBlockNames = dependencyResult.value;
795
828
  const files = {};
796
- const structureFiles = generateStructure(config);
797
- Object.assign(files, structureFiles);
798
829
  const resolvedManifests = resolvedBlockNames.filter((name) => manifests[name] !== void 0).map((name) => manifests[name]);
830
+ const structureFiles = generateStructure(config, resolvedManifests);
831
+ Object.assign(files, structureFiles);
799
832
  const astroConfigResult = generateAstroConfig(config, resolvedManifests);
800
833
  if (!isOk(astroConfigResult)) {
801
834
  return err(astroConfigResult.error);
@@ -1735,7 +1768,6 @@ export function getStaticPaths() { return [{ params: { slug: '1' } }]; }
1735
1768
  "cta-newsletter": { "cta-newsletter.astro": "<section>CTA</section>\n" },
1736
1769
  "header-sticky": { "header-sticky.astro": "<header>Sticky</header>\n" }
1737
1770
  };
1738
- var FIXTURE_DEFAULT_CONTENT = {};
1739
1771
  function loadAllPalettes() {
1740
1772
  if (BUILTIN_PALETTES.length > 0) {
1741
1773
  return [...BUILTIN_PALETTES];
@@ -1769,6 +1801,202 @@ function findRegistryPalettesDir() {
1769
1801
  }
1770
1802
  }
1771
1803
 
1804
+ // src/registry/registry-fetcher.ts
1805
+ import { existsSync, readFileSync as readFileSync2, mkdirSync, writeFileSync, statSync } from "fs";
1806
+ import { join as join2 } from "path";
1807
+ import { homedir } from "os";
1808
+ var DEFAULT_CONFIG = {
1809
+ registryUrl: process.env.FORNIX_REGISTRY_URL || "https://raw.githubusercontent.com/kamsqe/fornix/main/packages/fornix-registry/registry.json",
1810
+ cacheDir: join2(homedir(), ".cache", "fornix"),
1811
+ force: process.env.FORNIX_NO_CACHE === "true",
1812
+ maxCacheAge: 24 * 60 * 60 * 1e3
1813
+ // 24 hours
1814
+ };
1815
+ async function fetchRegistryIndex(config = {}) {
1816
+ if (process.env.FORNIX_E2E_MOCK === "true") {
1817
+ return ok({ blocks: FIXTURE_MANIFESTS, palettes: BUILTIN_PALETTES });
1818
+ }
1819
+ const cfg = { ...DEFAULT_CONFIG, ...config };
1820
+ const cacheFile = join2(cfg.cacheDir, "registry.json");
1821
+ const mapDataToIndex = (data) => {
1822
+ const blocksArray = Array.isArray(data.blocks) ? data.blocks : [];
1823
+ const blocksRecord = {};
1824
+ for (const block of blocksArray) {
1825
+ if (block.name) {
1826
+ blocksRecord[block.name] = block;
1827
+ }
1828
+ }
1829
+ return {
1830
+ blocks: blocksRecord,
1831
+ palettes: Array.isArray(data.palettes) ? data.palettes : []
1832
+ };
1833
+ };
1834
+ if (!cfg.force && isCacheValid(cacheFile, cfg.maxCacheAge)) {
1835
+ const cached = loadFromCache(cacheFile);
1836
+ if (cached) return ok(mapDataToIndex(cached));
1837
+ }
1838
+ try {
1839
+ const response = await fetch(cfg.registryUrl);
1840
+ if (!response.ok) {
1841
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
1842
+ }
1843
+ const data = await response.json();
1844
+ mkdirSync(cfg.cacheDir, { recursive: true });
1845
+ writeFileSync(cacheFile, JSON.stringify(data, null, 2));
1846
+ return ok(mapDataToIndex(data));
1847
+ } catch (error) {
1848
+ const cached = loadFromCache(cacheFile);
1849
+ if (cached) {
1850
+ return ok(mapDataToIndex(cached));
1851
+ }
1852
+ const message = error instanceof Error ? error.message : String(error);
1853
+ return err({
1854
+ kind: "RegistryFetchError",
1855
+ message: `Failed to fetch registry from ${cfg.registryUrl}: ${message}`
1856
+ });
1857
+ }
1858
+ }
1859
+ function isCacheValid(cachePath, maxAge) {
1860
+ if (!existsSync(cachePath)) {
1861
+ return false;
1862
+ }
1863
+ try {
1864
+ const stat = statSync(cachePath);
1865
+ const age = Date.now() - stat.mtimeMs;
1866
+ return age < maxAge;
1867
+ } catch {
1868
+ return false;
1869
+ }
1870
+ }
1871
+ function loadFromCache(cachePath) {
1872
+ try {
1873
+ if (!existsSync(cachePath)) return null;
1874
+ const raw = readFileSync2(cachePath, "utf-8");
1875
+ return JSON.parse(raw);
1876
+ } catch {
1877
+ return null;
1878
+ }
1879
+ }
1880
+
1881
+ // src/registry/block-fetcher.ts
1882
+ import { downloadTemplate } from "giget";
1883
+ import {
1884
+ existsSync as existsSync2,
1885
+ readFileSync as readFileSync3,
1886
+ readdirSync as readdirSync2,
1887
+ mkdirSync as mkdirSync2,
1888
+ statSync as statSync2
1889
+ } from "fs";
1890
+ import { join as join3 } from "path";
1891
+ import { homedir as homedir2 } from "os";
1892
+ var DEFAULT_CONFIG2 = {
1893
+ repo: "kamsqe/fornix",
1894
+ ref: "main",
1895
+ cacheDir: join3(homedir2(), ".cache", "fornix", "blocks"),
1896
+ blocksPrefix: "packages/fornix-blocks/blocks",
1897
+ force: process.env.FORNIX_NO_CACHE === "true",
1898
+ maxCacheAge: 24 * 60 * 60 * 1e3
1899
+ // 24 hours
1900
+ };
1901
+ async function fetchBlock(blockName, config = {}) {
1902
+ if (process.env.FORNIX_E2E_MOCK === "true") {
1903
+ const manifest2 = FIXTURE_MANIFESTS[blockName];
1904
+ const files = FIXTURE_BLOCK_SOURCES[blockName];
1905
+ if (!manifest2 || !files) {
1906
+ return err({
1907
+ kind: "FetchError",
1908
+ blockName,
1909
+ message: `Mock block not found: ${blockName}`
1910
+ });
1911
+ }
1912
+ return ok({ manifest: manifest2, files, fromCache: true });
1913
+ }
1914
+ const cfg = { ...DEFAULT_CONFIG2, ...config };
1915
+ const blockCacheDir = join3(cfg.cacheDir, blockName);
1916
+ if (!cfg.force && isCacheValid2(blockCacheDir, cfg.maxCacheAge)) {
1917
+ return loadFromCache2(blockName, blockCacheDir);
1918
+ }
1919
+ try {
1920
+ const source = `gh:${cfg.repo}/${cfg.blocksPrefix}/${blockName}#${cfg.ref}`;
1921
+ mkdirSync2(cfg.cacheDir, { recursive: true });
1922
+ await downloadTemplate(source, {
1923
+ dir: blockCacheDir,
1924
+ force: true
1925
+ // overwrite cache
1926
+ });
1927
+ return loadFromCache2(blockName, blockCacheDir);
1928
+ } catch (error) {
1929
+ if (existsSync2(join3(blockCacheDir, "block.json"))) {
1930
+ return loadFromCache2(blockName, blockCacheDir);
1931
+ }
1932
+ const message = error instanceof Error ? error.message : String(error);
1933
+ return err({
1934
+ kind: "FetchError",
1935
+ blockName,
1936
+ message: `Failed to fetch block '${blockName}': ${message}`
1937
+ });
1938
+ }
1939
+ }
1940
+ async function fetchBlocks(blockNames, config = {}) {
1941
+ return Promise.all(blockNames.map((name) => fetchBlock(name, config)));
1942
+ }
1943
+ function isCacheValid2(blockCacheDir, maxAge) {
1944
+ const manifestPath = join3(blockCacheDir, "block.json");
1945
+ if (!existsSync2(manifestPath)) {
1946
+ return false;
1947
+ }
1948
+ try {
1949
+ const stat = statSync2(manifestPath);
1950
+ const age = Date.now() - stat.mtimeMs;
1951
+ return age < maxAge;
1952
+ } catch {
1953
+ return false;
1954
+ }
1955
+ }
1956
+ function loadFromCache2(blockName, blockCacheDir) {
1957
+ try {
1958
+ const manifestPath = join3(blockCacheDir, "block.json");
1959
+ if (!existsSync2(manifestPath)) {
1960
+ return err({
1961
+ kind: "FetchError",
1962
+ blockName,
1963
+ message: `Cache miss: no block.json found in ${blockCacheDir}`
1964
+ });
1965
+ }
1966
+ const raw = readFileSync3(manifestPath, "utf-8");
1967
+ const parsed = JSON.parse(raw);
1968
+ const result = BlockManifestSchema.safeParse(parsed);
1969
+ if (!result.success) {
1970
+ const issues = result.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join(", ");
1971
+ return err({
1972
+ kind: "FetchError",
1973
+ blockName,
1974
+ message: `Invalid manifest in cache: ${issues}`
1975
+ });
1976
+ }
1977
+ const files = {};
1978
+ const entries = readdirSync2(blockCacheDir);
1979
+ for (const entry of entries) {
1980
+ const fullPath = join3(blockCacheDir, entry);
1981
+ if (statSync2(fullPath).isFile() && entry !== "block.json") {
1982
+ files[entry] = readFileSync3(fullPath, "utf-8");
1983
+ }
1984
+ }
1985
+ return ok({
1986
+ manifest: result.data,
1987
+ files,
1988
+ fromCache: true
1989
+ });
1990
+ } catch (error) {
1991
+ const message = error instanceof Error ? error.message : String(error);
1992
+ return err({
1993
+ kind: "FetchError",
1994
+ blockName,
1995
+ message: `Failed to load block from cache: ${message}`
1996
+ });
1997
+ }
1998
+ }
1999
+
1772
2000
  // src/prompts/manual-flow.ts
1773
2001
  import * as p from "@clack/prompts";
1774
2002
  import pc from "picocolors";
@@ -1959,8 +2187,8 @@ function buildSummary(config, blockNames, palette) {
1959
2187
 
1960
2188
  // src/scaffold/post-scaffold.ts
1961
2189
  import { execSync } from "child_process";
1962
- import { writeFileSync } from "fs";
1963
- import { join as join2, basename } from "path";
2190
+ import { writeFileSync as writeFileSync2 } from "fs";
2191
+ import { join as join4, basename } from "path";
1964
2192
  import pc2 from "picocolors";
1965
2193
  function runPostScaffold(input, callbacks) {
1966
2194
  const log = callbacks?.onLog ?? ((msg) => console.log(msg));
@@ -2126,7 +2354,7 @@ function generateClaudeMd(projectDir, config, blockNames) {
2126
2354
  lines.push("```");
2127
2355
  lines.push("");
2128
2356
  const content = lines.join("\n");
2129
- writeFileSync(join2(projectDir, "CLAUDE.md"), content, "utf-8");
2357
+ writeFileSync2(join4(projectDir, "CLAUDE.md"), content, "utf-8");
2130
2358
  }
2131
2359
 
2132
2360
  // src/ai/prompt-builder.ts
@@ -2154,7 +2382,8 @@ Your job:
2154
2382
 
2155
2383
  You MUST only select blocks that exist in the catalog below. Never invent block names.`;
2156
2384
  }
2157
- function buildBlocksCatalog(blocks) {
2385
+ function buildBlocksCatalog(blocksRecord) {
2386
+ const blocks = Object.values(blocksRecord);
2158
2387
  const lines = ["# Available Blocks\n"];
2159
2388
  const grouped = /* @__PURE__ */ new Map();
2160
2389
  for (const block of blocks) {
@@ -2234,7 +2463,8 @@ function buildPalettesCatalog(palettes) {
2234
2463
  }
2235
2464
  return lines.join("\n");
2236
2465
  }
2237
- function buildConstraintRules(blocks) {
2466
+ function buildConstraintRules(blocksRecord) {
2467
+ const blocks = Object.values(blocksRecord);
2238
2468
  const lines = ["# Constraint Rules\n"];
2239
2469
  lines.push("## Render Modes");
2240
2470
  lines.push("- `static` \u2014 Pre-rendered HTML, no server. Best for blogs, docs, landing pages.");
@@ -2960,8 +3190,8 @@ function createCloudflareProvider(opts = {}) {
2960
3190
  }
2961
3191
 
2962
3192
  // src/ai/providers/mock-provider.ts
2963
- import { readFileSync as readFileSync2, existsSync } from "fs";
2964
- import { join as join3, dirname as dirname2 } from "path";
3193
+ import { readFileSync as readFileSync4, existsSync as existsSync3 } from "fs";
3194
+ import { join as join5, dirname as dirname2 } from "path";
2965
3195
  import { fileURLToPath as fileURLToPath2 } from "url";
2966
3196
  var FIXTURE_ENTRIES = [
2967
3197
  {
@@ -3001,9 +3231,9 @@ function createMockProvider() {
3001
3231
  });
3002
3232
  }
3003
3233
  const fixtureDir = resolveFixtureDir();
3004
- const filePath = join3(fixtureDir, match.filename);
3234
+ const filePath = join5(fixtureDir, match.filename);
3005
3235
  try {
3006
- const raw = readFileSync2(filePath, "utf-8");
3236
+ const raw = readFileSync4(filePath, "utf-8");
3007
3237
  const parsed = JSON.parse(raw);
3008
3238
  const validated = IntentSchema.parse(parsed);
3009
3239
  return ok(validated);
@@ -3020,10 +3250,10 @@ function createMockProvider() {
3020
3250
  }
3021
3251
  function resolveFixtureDir() {
3022
3252
  const thisDir = dirname2(fileURLToPath2(import.meta.url));
3023
- const fromSource = join3(thisDir, "..", "..", "..", "tests", "fixtures", "ai-responses");
3024
- if (existsSync(fromSource)) return fromSource;
3025
- const fromDist = join3(thisDir, "..", "tests", "fixtures", "ai-responses");
3026
- if (existsSync(fromDist)) return fromDist;
3253
+ const fromSource = join5(thisDir, "..", "..", "..", "tests", "fixtures", "ai-responses");
3254
+ if (existsSync3(fromSource)) return fromSource;
3255
+ const fromDist = join5(thisDir, "..", "tests", "fixtures", "ai-responses");
3256
+ if (existsSync3(fromDist)) return fromDist;
3027
3257
  return fromSource;
3028
3258
  }
3029
3259
 
@@ -3330,30 +3560,37 @@ var createCommand = defineCommand({
3330
3560
  }
3331
3561
  },
3332
3562
  async run({ args: args2 }) {
3333
- const allPalettes = loadAllPalettes();
3563
+ const registryResult = await fetchRegistryIndex();
3564
+ if (!isOk(registryResult)) {
3565
+ console.error(pc3.red(`\u2716 Failed to fetch block registry: ${registryResult.error.message}`));
3566
+ process.exitCode = 1;
3567
+ return;
3568
+ }
3569
+ const manifests = registryResult.value.blocks;
3570
+ const allPalettes = registryResult.value.palettes.length > 0 ? registryResult.value.palettes : loadAllPalettes();
3334
3571
  const hasExplicitFlags = !!(args2.render || args2.deploy || args2.blocks || args2.database || args2.css || args2.locales || args2.palette || args2.recipe);
3335
3572
  if (args2.manual && !args2.yes) {
3336
- const defaultProjectName = args2.dir ? basename2(resolve(args2.dir)) : "my-project";
3573
+ const defaultProjectName = args2.dir ? basename2(resolve2(args2.dir)) : "my-project";
3337
3574
  const config = await runManualFlow({
3338
3575
  defaultProjectName,
3339
- manifests: FIXTURE_MANIFESTS,
3576
+ manifests,
3340
3577
  allPalettes
3341
3578
  });
3342
3579
  if (!config) {
3343
3580
  process.exitCode = 0;
3344
3581
  return;
3345
3582
  }
3346
- const projectDir = args2.dir ? resolve(args2.dir) : resolve(config.projectDir);
3583
+ const projectDir = args2.dir ? resolve2(args2.dir) : resolve2(config.projectDir);
3347
3584
  const finalConfig = { ...config, projectDir };
3348
- return runScaffold(finalConfig, allPalettes, args2["dry-run"] ?? false, args2.verbose ?? false, !(args2.install ?? true), !(args2.git ?? true));
3585
+ return runScaffold(finalConfig, manifests, allPalettes, args2["dry-run"] ?? false, args2.verbose ?? false, !(args2.install ?? true), !(args2.git ?? true));
3349
3586
  }
3350
3587
  if (args2.manual || hasExplicitFlags) {
3351
- return runFlagDrivenMode(args2, allPalettes);
3588
+ return runFlagDrivenMode(args2, manifests, allPalettes);
3352
3589
  }
3353
- return runAIMode(args2, allPalettes);
3590
+ return runAIMode(args2, manifests, allPalettes);
3354
3591
  }
3355
3592
  });
3356
- async function runAIMode(args2, allPalettes) {
3593
+ async function runAIMode(args2, manifests, allPalettes) {
3357
3594
  const providerName = parseProviderName(args2.provider);
3358
3595
  if (args2.provider && !providerName) {
3359
3596
  console.error(pc3.red(`\u2716 Unknown provider: ${String(args2.provider)}`));
@@ -3377,10 +3614,10 @@ async function runAIMode(args2, allPalettes) {
3377
3614
  return;
3378
3615
  }
3379
3616
  const registry = {
3380
- blocks: Object.values(FIXTURE_MANIFESTS),
3617
+ blocks: Object.values(manifests),
3381
3618
  palettes: [...allPalettes]
3382
3619
  };
3383
- const projectDir = resolve(String(args2.dir ?? "."));
3620
+ const projectDir = resolve2(String(args2.dir ?? "."));
3384
3621
  const projectName = basename2(projectDir);
3385
3622
  const nameResult = validateProjectName(projectName);
3386
3623
  if (!nameResult.ok) {
@@ -3415,6 +3652,7 @@ async function runAIMode(args2, allPalettes) {
3415
3652
  }
3416
3653
  return runScaffold(
3417
3654
  config,
3655
+ manifests,
3418
3656
  allPalettes,
3419
3657
  (args2["dry-run"] ?? false) === true,
3420
3658
  (args2.verbose ?? false) === true,
@@ -3422,8 +3660,8 @@ async function runAIMode(args2, allPalettes) {
3422
3660
  !((args2.git ?? true) === true)
3423
3661
  );
3424
3662
  }
3425
- function runFlagDrivenMode(args2, allPalettes) {
3426
- const projectDir = resolve(String(args2.dir ?? "."));
3663
+ function runFlagDrivenMode(args2, manifests, allPalettes) {
3664
+ const projectDir = resolve2(String(args2.dir ?? "."));
3427
3665
  const projectName = basename2(projectDir);
3428
3666
  const nameResult = validateProjectName(projectName);
3429
3667
  if (!nameResult.ok) {
@@ -3506,6 +3744,7 @@ function runFlagDrivenMode(args2, allPalettes) {
3506
3744
  };
3507
3745
  return runScaffold(
3508
3746
  config,
3747
+ manifests,
3509
3748
  allPalettes,
3510
3749
  (args2["dry-run"] ?? false) === true,
3511
3750
  (args2.verbose ?? false) === true,
@@ -3513,12 +3752,36 @@ function runFlagDrivenMode(args2, allPalettes) {
3513
3752
  !((args2.git ?? true) === true)
3514
3753
  );
3515
3754
  }
3516
- function runScaffold(config, allPalettes, dryRun, verbose, skipInstall, skipGit) {
3755
+ async function runScaffold(config, manifests, allPalettes, dryRun, verbose, skipInstall, skipGit) {
3756
+ const spinner2 = p2.spinner();
3757
+ spinner2.start("Fetching blocks from registry...");
3758
+ const blockNames = config.blocks.map((b) => b.name);
3759
+ const blockResults = await fetchBlocks(blockNames);
3760
+ const blockSources = {};
3761
+ const blockDefaultContent = {};
3762
+ for (const result2 of blockResults) {
3763
+ if (!isOk(result2)) {
3764
+ spinner2.stop(`Failed to fetch block '${result2.error.blockName}'`, 1);
3765
+ console.error(pc3.red(`\u2716 ${result2.error.message}`));
3766
+ process.exitCode = 1;
3767
+ return;
3768
+ }
3769
+ const { manifest: manifest2, files: files2 } = result2.value;
3770
+ blockSources[manifest2.name] = files2;
3771
+ try {
3772
+ if (files2["default-content.json"]) {
3773
+ blockDefaultContent[manifest2.name] = JSON.parse(files2["default-content.json"]);
3774
+ }
3775
+ } catch (e) {
3776
+ console.error(pc3.yellow(`\u26A0 Warning: Failed to parse default-content.json for block '${manifest2.name}'`));
3777
+ }
3778
+ }
3779
+ spinner2.stop("Blocks fetched successfully.");
3517
3780
  const input = {
3518
3781
  config,
3519
- manifests: FIXTURE_MANIFESTS,
3520
- blockSources: FIXTURE_BLOCK_SOURCES,
3521
- blockDefaultContent: FIXTURE_DEFAULT_CONTENT,
3782
+ manifests,
3783
+ blockSources: Object.freeze(blockSources),
3784
+ blockDefaultContent: Object.freeze(blockDefaultContent),
3522
3785
  allPalettes
3523
3786
  };
3524
3787
  const result = scaffold(input);
@@ -3552,10 +3815,10 @@ function runScaffold(config, allPalettes, dryRun, verbose, skipInstall, skipGit)
3552
3815
  const files = result.value.files;
3553
3816
  let filesWritten = 0;
3554
3817
  for (const [relativePath, content] of Object.entries(files)) {
3555
- const fullPath = join4(config.projectDir, relativePath);
3556
- const parentDir = join4(fullPath, "..");
3557
- mkdirSync2(parentDir, { recursive: true });
3558
- writeFileSync2(fullPath, content, "utf-8");
3818
+ const fullPath = join6(config.projectDir, relativePath);
3819
+ const parentDir = join6(fullPath, "..");
3820
+ mkdirSync4(parentDir, { recursive: true });
3821
+ writeFileSync3(fullPath, content, "utf-8");
3559
3822
  filesWritten++;
3560
3823
  if (verbose) {
3561
3824
  console.log(pc3.dim(` created ${relativePath}`));
@@ -3644,8 +3907,8 @@ function showNoProviderGuide() {
3644
3907
  // src/cli/commands/add.ts
3645
3908
  import { defineCommand as defineCommand2 } from "citty";
3646
3909
  import pc4 from "picocolors";
3647
- import { readFileSync as readFileSync3, writeFileSync as writeFileSync3, existsSync as existsSync2, mkdirSync as mkdirSync3 } from "fs";
3648
- import { join as join5, dirname as dirname3 } from "path";
3910
+ import { readFileSync as readFileSync5, writeFileSync as writeFileSync4, existsSync as existsSync4, mkdirSync as mkdirSync5 } from "fs";
3911
+ import { join as join7, dirname as dirname3 } from "path";
3649
3912
  var addCommand = defineCommand2({
3650
3913
  meta: {
3651
3914
  name: "add",
@@ -3673,28 +3936,36 @@ var addCommand = defineCommand2({
3673
3936
  default: false
3674
3937
  }
3675
3938
  },
3676
- run({ args: args2 }) {
3939
+ async run({ args: args2 }) {
3677
3940
  const typedArgs = args2;
3678
3941
  const cwd = process.cwd();
3679
- const manifestPath = join5(cwd, "fornix.json");
3680
- if (!existsSync2(manifestPath)) {
3942
+ const manifestPath = join7(cwd, "fornix.json");
3943
+ if (!existsSync4(manifestPath)) {
3681
3944
  console.error(
3682
3945
  pc4.red("\u2717 No fornix.json found. Are you in a Fornix project?")
3683
3946
  );
3684
3947
  process.exit(1);
3685
3948
  }
3686
- const manifestRaw = readFileSync3(manifestPath, "utf-8");
3949
+ const manifestRaw = readFileSync5(manifestPath, "utf-8");
3687
3950
  const manifest2 = JSON.parse(manifestRaw);
3951
+ const registryResult = await fetchRegistryIndex();
3952
+ if (!isOk(registryResult)) {
3953
+ console.error(pc4.red(`\u2716 Failed to fetch block registry: ${registryResult.error.message}`));
3954
+ process.exitCode = 1;
3955
+ return;
3956
+ }
3957
+ const manifests = registryResult.value.blocks;
3688
3958
  const blockName = typedArgs.block;
3689
- const blockManifest = FIXTURE_MANIFESTS[blockName];
3959
+ const blockManifest = manifests[blockName];
3690
3960
  if (!blockManifest) {
3691
3961
  console.error(pc4.red(`\u2717 Block '${blockName}' not found in registry.`));
3692
3962
  console.error(
3693
3963
  pc4.dim(
3694
- ` Available: ${Object.keys(FIXTURE_MANIFESTS).join(", ")}`
3964
+ ` Available: ${Object.keys(manifests).join(", ")}`
3695
3965
  )
3696
3966
  );
3697
- process.exit(1);
3967
+ process.exitCode = 1;
3968
+ return;
3698
3969
  }
3699
3970
  const installedNames = new Set(manifest2.blocks.map((b) => b.name));
3700
3971
  if (installedNames.has(blockName)) {
@@ -3703,26 +3974,32 @@ var addCommand = defineCommand2({
3703
3974
  );
3704
3975
  return;
3705
3976
  }
3706
- const blocksToAdd = resolveDependencies2(blockName, installedNames);
3977
+ const blocksToAdd = resolveDependencies2(blockName, installedNames, manifests);
3707
3978
  for (const name of blocksToAdd) {
3708
- const m = FIXTURE_MANIFESTS[name];
3979
+ const m = manifests[name];
3709
3980
  if (m?.requiredMode && manifest2.renderMode !== m.requiredMode) {
3710
3981
  console.error(
3711
3982
  pc4.red(
3712
3983
  `\u2717 Block '${name}' requires '${m.requiredMode}' mode, but project uses '${manifest2.renderMode}'.`
3713
3984
  )
3714
3985
  );
3715
- process.exit(1);
3986
+ process.exitCode = 1;
3987
+ return;
3716
3988
  }
3717
3989
  }
3990
+ console.log(pc4.dim("Fetching blocks..."));
3991
+ const blockResults = await fetchBlocks(blocksToAdd);
3718
3992
  const filesToWrite = [];
3719
- for (const name of blocksToAdd) {
3720
- const bManifest = FIXTURE_MANIFESTS[name];
3721
- const sources = FIXTURE_BLOCK_SOURCES[name];
3722
- if (!bManifest || !sources) {
3723
- console.error(pc4.red(`\u2717 Source files not found for block '${name}'.`));
3724
- process.exit(1);
3993
+ for (let i = 0; i < blocksToAdd.length; i++) {
3994
+ const name = blocksToAdd[i];
3995
+ const result = blockResults[i];
3996
+ if (!result || !isOk(result)) {
3997
+ console.error(pc4.red(`\u2717 Failed to fetch files for block '${name}'.`));
3998
+ process.exitCode = 1;
3999
+ return;
3725
4000
  }
4001
+ const bManifest = result.value.manifest;
4002
+ const sources = result.value.files;
3726
4003
  for (const file of bManifest.files) {
3727
4004
  const content = sources[file.source];
3728
4005
  if (content === void 0) {
@@ -3731,10 +4008,11 @@ var addCommand = defineCommand2({
3731
4008
  `\u2717 Source file '${file.source}' not found for block '${name}'.`
3732
4009
  )
3733
4010
  );
3734
- process.exit(1);
4011
+ process.exitCode = 1;
4012
+ return;
3735
4013
  }
3736
4014
  filesToWrite.push({
3737
- path: join5(cwd, file.destination),
4015
+ path: join7(cwd, file.destination),
3738
4016
  content
3739
4017
  });
3740
4018
  }
@@ -3755,15 +4033,15 @@ var addCommand = defineCommand2({
3755
4033
  return;
3756
4034
  }
3757
4035
  for (const file of filesToWrite) {
3758
- mkdirSync3(dirname3(file.path), { recursive: true });
3759
- writeFileSync3(file.path, file.content);
4036
+ mkdirSync5(dirname3(file.path), { recursive: true });
4037
+ writeFileSync4(file.path, file.content);
3760
4038
  if (typedArgs.verbose) {
3761
4039
  console.log(` ${pc4.dim("\u2192")} ${file.path}`);
3762
4040
  }
3763
4041
  }
3764
4042
  const now = (/* @__PURE__ */ new Date()).toISOString();
3765
4043
  for (const name of blocksToAdd) {
3766
- const bManifest = FIXTURE_MANIFESTS[name];
4044
+ const bManifest = manifests[name];
3767
4045
  if (!bManifest) continue;
3768
4046
  manifest2.blocks.push({
3769
4047
  name,
@@ -3772,7 +4050,7 @@ var addCommand = defineCommand2({
3772
4050
  installedAt: now
3773
4051
  });
3774
4052
  }
3775
- writeFileSync3(manifestPath, JSON.stringify(manifest2, null, 2) + "\n");
4053
+ writeFileSync4(manifestPath, JSON.stringify(manifest2, null, 2) + "\n");
3776
4054
  console.log();
3777
4055
  for (const name of blocksToAdd) {
3778
4056
  const isDep = name !== blockName;
@@ -3793,13 +4071,13 @@ var addCommand = defineCommand2({
3793
4071
  console.log();
3794
4072
  }
3795
4073
  });
3796
- function resolveDependencies2(blockName, installedNames) {
4074
+ function resolveDependencies2(blockName, installedNames, manifests) {
3797
4075
  const result = [];
3798
4076
  const visited = /* @__PURE__ */ new Set();
3799
4077
  function walk(name) {
3800
4078
  if (visited.has(name) || installedNames.has(name)) return;
3801
4079
  visited.add(name);
3802
- const manifest2 = FIXTURE_MANIFESTS[name];
4080
+ const manifest2 = manifests[name];
3803
4081
  if (!manifest2) return;
3804
4082
  for (const dep of manifest2.requires) {
3805
4083
  walk(dep);
@@ -3813,8 +4091,8 @@ function resolveDependencies2(blockName, installedNames) {
3813
4091
  // src/cli/commands/remove.ts
3814
4092
  import { defineCommand as defineCommand3 } from "citty";
3815
4093
  import pc5 from "picocolors";
3816
- import { readFileSync as readFileSync4, writeFileSync as writeFileSync4, existsSync as existsSync3, unlinkSync, readdirSync as readdirSync2, rmdirSync } from "fs";
3817
- import { join as join6, dirname as dirname4 } from "path";
4094
+ import { readFileSync as readFileSync6, writeFileSync as writeFileSync5, existsSync as existsSync5, unlinkSync, readdirSync as readdirSync3, rmdirSync } from "fs";
4095
+ import { join as join8, dirname as dirname4 } from "path";
3818
4096
  var removeCommand = defineCommand3({
3819
4097
  meta: {
3820
4098
  name: "remove",
@@ -3842,18 +4120,25 @@ var removeCommand = defineCommand3({
3842
4120
  default: false
3843
4121
  }
3844
4122
  },
3845
- run({ args: args2 }) {
4123
+ async run({ args: args2 }) {
3846
4124
  const typedArgs = args2;
3847
4125
  const cwd = process.cwd();
3848
- const manifestPath = join6(cwd, "fornix.json");
3849
- if (!existsSync3(manifestPath)) {
4126
+ const manifestPath = join8(cwd, "fornix.json");
4127
+ if (!existsSync5(manifestPath)) {
3850
4128
  console.error(
3851
4129
  pc5.red("\u2717 No fornix.json found. Are you in a Fornix project?")
3852
4130
  );
3853
4131
  process.exit(1);
3854
4132
  }
3855
- const manifestRaw = readFileSync4(manifestPath, "utf-8");
4133
+ const manifestRaw = readFileSync6(manifestPath, "utf-8");
3856
4134
  const manifest2 = JSON.parse(manifestRaw);
4135
+ const registryResult = await fetchRegistryIndex();
4136
+ if (!isOk(registryResult)) {
4137
+ console.error(pc5.red(`\u2716 Failed to fetch block registry: ${registryResult.error.message}`));
4138
+ process.exitCode = 1;
4139
+ return;
4140
+ }
4141
+ const manifests = registryResult.value.blocks;
3857
4142
  const blockName = typedArgs.block;
3858
4143
  const installedNames = new Set(manifest2.blocks.map((b) => b.name));
3859
4144
  if (!installedNames.has(blockName)) {
@@ -3862,7 +4147,7 @@ var removeCommand = defineCommand3({
3862
4147
  );
3863
4148
  return;
3864
4149
  }
3865
- const dependents = findDependents(blockName, installedNames);
4150
+ const dependents = findDependents(blockName, installedNames, manifests);
3866
4151
  if (dependents.length > 0 && !typedArgs.force) {
3867
4152
  console.log(
3868
4153
  pc5.yellow(
@@ -3874,12 +4159,12 @@ var removeCommand = defineCommand3({
3874
4159
  );
3875
4160
  return;
3876
4161
  }
3877
- const blockManifest = FIXTURE_MANIFESTS[blockName];
4162
+ const blockManifest = manifests[blockName];
3878
4163
  const filesToRemove = [];
3879
4164
  if (blockManifest) {
3880
4165
  for (const file of blockManifest.files) {
3881
- const filePath = join6(cwd, file.destination);
3882
- if (existsSync3(filePath)) {
4166
+ const filePath = join8(cwd, file.destination);
4167
+ if (existsSync5(filePath)) {
3883
4168
  filesToRemove.push(filePath);
3884
4169
  }
3885
4170
  }
@@ -3901,7 +4186,7 @@ var removeCommand = defineCommand3({
3901
4186
  tryRemoveEmptyDir(dirname4(filePath), cwd);
3902
4187
  }
3903
4188
  manifest2.blocks = manifest2.blocks.filter((b) => b.name !== blockName);
3904
- writeFileSync4(manifestPath, JSON.stringify(manifest2, null, 2) + "\n");
4189
+ writeFileSync5(manifestPath, JSON.stringify(manifest2, null, 2) + "\n");
3905
4190
  console.log();
3906
4191
  console.log(` ${pc5.red("-")} ${pc5.bold(blockName)} removed`);
3907
4192
  if (dependents.length > 0) {
@@ -3920,10 +4205,10 @@ var removeCommand = defineCommand3({
3920
4205
  console.log();
3921
4206
  }
3922
4207
  });
3923
- function findDependents(blockName, installedNames) {
4208
+ function findDependents(blockName, installedNames, manifests) {
3924
4209
  const dependents = [];
3925
4210
  for (const name of installedNames) {
3926
- const manifest2 = FIXTURE_MANIFESTS[name];
4211
+ const manifest2 = manifests[name];
3927
4212
  if (manifest2 && manifest2.requires.includes(blockName)) {
3928
4213
  dependents.push(name);
3929
4214
  }
@@ -3933,7 +4218,7 @@ function findDependents(blockName, installedNames) {
3933
4218
  function tryRemoveEmptyDir(dirPath, rootPath) {
3934
4219
  if (dirPath === rootPath || !dirPath.startsWith(rootPath)) return;
3935
4220
  try {
3936
- const entries = readdirSync2(dirPath);
4221
+ const entries = readdirSync3(dirPath);
3937
4222
  if (entries.length === 0) {
3938
4223
  rmdirSync(dirPath);
3939
4224
  tryRemoveEmptyDir(dirname4(dirPath), rootPath);
@@ -3970,9 +4255,16 @@ var listCommand = defineCommand4({
3970
4255
  default: false
3971
4256
  }
3972
4257
  },
3973
- run({ args: args2 }) {
4258
+ async run({ args: args2 }) {
3974
4259
  const typedArgs = args2;
3975
- const blocks = getFilteredBlocks(typedArgs);
4260
+ const registryResult = await fetchRegistryIndex();
4261
+ if (!isOk(registryResult)) {
4262
+ console.error(pc6.red(`\u2716 Failed to fetch block registry: ${registryResult.error.message}`));
4263
+ process.exitCode = 1;
4264
+ return;
4265
+ }
4266
+ const manifests = registryResult.value.blocks;
4267
+ const blocks = getFilteredBlocks(typedArgs, manifests);
3976
4268
  if (blocks.length === 0) {
3977
4269
  console.log(pc6.yellow("No blocks found matching your filters."));
3978
4270
  return;
@@ -3984,8 +4276,8 @@ var listCommand = defineCommand4({
3984
4276
  }
3985
4277
  }
3986
4278
  });
3987
- function getFilteredBlocks(args2) {
3988
- let blocks = Object.values(FIXTURE_MANIFESTS);
4279
+ function getFilteredBlocks(args2, manifests) {
4280
+ let blocks = Object.values(manifests);
3989
4281
  if (args2.type) {
3990
4282
  const filterType = args2.type.toLowerCase();
3991
4283
  blocks = blocks.filter((b) => b.type === filterType);
@@ -4066,8 +4358,8 @@ function printFormatted(blocks, verbose) {
4066
4358
  // src/cli/commands/status.ts
4067
4359
  import { defineCommand as defineCommand5 } from "citty";
4068
4360
  import pc7 from "picocolors";
4069
- import { readFileSync as readFileSync5, existsSync as existsSync4 } from "fs";
4070
- import { join as join7 } from "path";
4361
+ import { readFileSync as readFileSync7, existsSync as existsSync6 } from "fs";
4362
+ import { join as join9 } from "path";
4071
4363
  var statusCommand = defineCommand5({
4072
4364
  meta: {
4073
4365
  name: "status",
@@ -4088,8 +4380,8 @@ var statusCommand = defineCommand5({
4088
4380
  run({ args: args2 }) {
4089
4381
  const typedArgs = args2;
4090
4382
  const cwd = process.cwd();
4091
- const manifestPath = join7(cwd, "fornix.json");
4092
- if (!existsSync4(manifestPath)) {
4383
+ const manifestPath = join9(cwd, "fornix.json");
4384
+ if (!existsSync6(manifestPath)) {
4093
4385
  console.error(
4094
4386
  pc7.red("\u2717 No fornix.json found in the current directory.")
4095
4387
  );
@@ -4102,7 +4394,7 @@ var statusCommand = defineCommand5({
4102
4394
  }
4103
4395
  let manifest2;
4104
4396
  try {
4105
- const raw = readFileSync5(manifestPath, "utf-8");
4397
+ const raw = readFileSync7(manifestPath, "utf-8");
4106
4398
  manifest2 = JSON.parse(raw);
4107
4399
  } catch {
4108
4400
  console.error(pc7.red("\u2717 Failed to parse fornix.json."));
@@ -4183,8 +4475,8 @@ function printStatus(manifest2, verbose) {
4183
4475
  // src/cli/commands/doctor.ts
4184
4476
  import { defineCommand as defineCommand6 } from "citty";
4185
4477
  import pc8 from "picocolors";
4186
- import { readFileSync as readFileSync6, existsSync as existsSync5 } from "fs";
4187
- import { join as join8 } from "path";
4478
+ import { readFileSync as readFileSync8, existsSync as existsSync7 } from "fs";
4479
+ import { join as join10 } from "path";
4188
4480
  var doctorCommand = defineCommand6({
4189
4481
  meta: {
4190
4482
  name: "doctor",
@@ -4197,9 +4489,9 @@ var doctorCommand = defineCommand6({
4197
4489
  default: false
4198
4490
  }
4199
4491
  },
4200
- run({ args: args2 }) {
4492
+ async run({ args: args2 }) {
4201
4493
  const cwd = process.cwd();
4202
- const manifestPath = join8(cwd, "fornix.json");
4494
+ const manifestPath = join10(cwd, "fornix.json");
4203
4495
  let hasErrors = false;
4204
4496
  const errors = [];
4205
4497
  function reportError(msg) {
@@ -4209,7 +4501,7 @@ var doctorCommand = defineCommand6({
4209
4501
  console.error(pc8.red(`\u2717 ${msg}`));
4210
4502
  }
4211
4503
  }
4212
- if (!existsSync5(manifestPath)) {
4504
+ if (!existsSync7(manifestPath)) {
4213
4505
  reportError("No fornix.json found in the current directory.");
4214
4506
  if (args2.json) {
4215
4507
  console.log(JSON.stringify({ healthy: false, errors }));
@@ -4218,7 +4510,7 @@ var doctorCommand = defineCommand6({
4218
4510
  }
4219
4511
  let manifest2;
4220
4512
  try {
4221
- const raw = readFileSync6(manifestPath, "utf-8");
4513
+ const raw = readFileSync8(manifestPath, "utf-8");
4222
4514
  manifest2 = JSON.parse(raw);
4223
4515
  } catch {
4224
4516
  reportError("Failed to parse fornix.json.");
@@ -4227,24 +4519,34 @@ var doctorCommand = defineCommand6({
4227
4519
  }
4228
4520
  process.exit(1);
4229
4521
  }
4522
+ const registryResult = await fetchRegistryIndex();
4523
+ if (!isOk(registryResult)) {
4524
+ reportError(`Failed to fetch block registry: ${registryResult.error.message}`);
4525
+ if (args2.json) {
4526
+ console.log(JSON.stringify({ healthy: false, errors }));
4527
+ }
4528
+ process.exitCode = 1;
4529
+ return;
4530
+ }
4531
+ const manifests = registryResult.value.blocks;
4230
4532
  const isMultiLocale = manifest2.locales && manifest2.locales.length >= 2;
4231
4533
  const locales = isMultiLocale ? manifest2.locales : [""];
4232
4534
  const installedBlocks = new Set(manifest2.blocks.map((b) => b.name));
4233
4535
  for (const block of manifest2.blocks) {
4234
- const bManifest = FIXTURE_MANIFESTS[block.name];
4536
+ const bManifest = manifests[block.name];
4235
4537
  if (bManifest) {
4236
4538
  for (const file of bManifest.files) {
4237
- const filePath = join8(cwd, file.destination);
4238
- if (!existsSync5(filePath)) {
4539
+ const filePath = join10(cwd, file.destination);
4540
+ if (!existsSync7(filePath)) {
4239
4541
  reportError(`Missing expected file for installed block '${block.name}': ${file.destination}`);
4240
4542
  }
4241
4543
  }
4242
4544
  }
4243
4545
  }
4244
- for (const [name, bManifest] of Object.entries(FIXTURE_MANIFESTS)) {
4546
+ for (const [name, bManifest] of Object.entries(manifests)) {
4245
4547
  if (!installedBlocks.has(name)) {
4246
4548
  const foundOrphaned = bManifest.files.some((file) => {
4247
- return existsSync5(join8(cwd, file.destination));
4549
+ return existsSync7(join10(cwd, file.destination));
4248
4550
  });
4249
4551
  if (foundOrphaned) {
4250
4552
  reportError(`Orphaned block files detected for '${name}'. The block is not in fornix.json.`);
@@ -4254,7 +4556,7 @@ var doctorCommand = defineCommand6({
4254
4556
  let requiresContentConfig = false;
4255
4557
  const missingContentFiles = [];
4256
4558
  for (const block of manifest2.blocks) {
4257
- const bManifest = FIXTURE_MANIFESTS[block.name];
4559
+ const bManifest = manifests[block.name];
4258
4560
  if (!bManifest) continue;
4259
4561
  const hasContentSlots = bManifest.ai?.contentSlots && Object.keys(bManifest.ai.contentSlots).length > 0;
4260
4562
  const hasCollections = bManifest.collections && bManifest.collections.length > 0;
@@ -4268,14 +4570,14 @@ var doctorCommand = defineCommand6({
4268
4570
  if (locale !== "") {
4269
4571
  pathFragment = `src/content/${locale}/${subdirectory}/${bManifest.name}.json`;
4270
4572
  }
4271
- if (!existsSync5(join8(cwd, pathFragment))) {
4573
+ if (!existsSync7(join10(cwd, pathFragment))) {
4272
4574
  missingContentFiles.push(pathFragment);
4273
4575
  }
4274
4576
  }
4275
4577
  }
4276
4578
  }
4277
4579
  if (requiresContentConfig) {
4278
- if (!existsSync5(join8(cwd, "src/content/config.ts"))) {
4580
+ if (!existsSync7(join10(cwd, "src/content/config.ts"))) {
4279
4581
  reportError("Missing expected file: src/content/config.ts");
4280
4582
  }
4281
4583
  }
@@ -4328,57 +4630,71 @@ import {
4328
4630
  } from "@modelcontextprotocol/sdk/types.js";
4329
4631
 
4330
4632
  // src/mcp/tools/list-blocks.ts
4331
- function listBlocks(input) {
4332
- let blocks = Object.values(FIXTURE_MANIFESTS);
4333
- if (input.type) {
4334
- const filterType = input.type.toLowerCase();
4335
- blocks = blocks.filter((block) => block.type === filterType);
4336
- }
4337
- if (input.category) {
4338
- const filterCategory = input.category.toLowerCase();
4339
- blocks = blocks.filter((block) => block.category === filterCategory);
4340
- }
4341
- if (input.search) {
4342
- const searchTerm = input.search.toLowerCase();
4343
- blocks = blocks.filter(
4344
- (block) => block.name.includes(searchTerm) || block.description.toLowerCase().includes(searchTerm) || block.tags.some((tag) => tag.includes(searchTerm))
4345
- );
4633
+ async function listBlocksHandler(args2) {
4634
+ const result = await fetchRegistryIndex();
4635
+ if (!isOk(result)) {
4636
+ throw new Error(`Failed to fetch block registry: ${result.error.message}`);
4637
+ }
4638
+ const manifests = result.value.blocks;
4639
+ const typedArgs = args2;
4640
+ let blocks = Object.values(manifests);
4641
+ if (typedArgs?.type) {
4642
+ blocks = blocks.filter((b) => b.type === typedArgs.type);
4346
4643
  }
4347
- const entries = blocks.map((block) => ({
4348
- name: block.name,
4349
- type: block.type,
4350
- category: block.category,
4351
- description: block.description,
4352
- tags: block.tags,
4353
- requiredMode: block.requiredMode,
4354
- requires: block.requires
4355
- })).sort((a, b) => a.name.localeCompare(b.name));
4356
- return ok(entries);
4644
+ if (typedArgs?.category) {
4645
+ blocks = blocks.filter((b) => b.category === typedArgs.category);
4646
+ }
4647
+ return {
4648
+ content: [
4649
+ {
4650
+ type: "text",
4651
+ text: JSON.stringify(
4652
+ blocks.map((b) => ({
4653
+ name: b.name,
4654
+ description: b.description,
4655
+ type: b.type,
4656
+ category: b.category,
4657
+ requiredMode: b.requiredMode,
4658
+ requires: b.requires,
4659
+ conflicts: b.conflicts,
4660
+ envVars: b.envVars
4661
+ })),
4662
+ null,
4663
+ 2
4664
+ )
4665
+ }
4666
+ ]
4667
+ };
4357
4668
  }
4358
4669
 
4359
4670
  // src/mcp/tools/add-block.ts
4360
- import { readFileSync as readFileSync7, writeFileSync as writeFileSync5, existsSync as existsSync6, mkdirSync as mkdirSync4 } from "fs";
4361
- import { join as join9, dirname as dirname5 } from "path";
4362
- function addBlock2(input) {
4671
+ import { readFileSync as readFileSync9, writeFileSync as writeFileSync6, existsSync as existsSync8, mkdirSync as mkdirSync6 } from "fs";
4672
+ import { join as join11, dirname as dirname5 } from "path";
4673
+ async function addBlock2(input) {
4363
4674
  const { name, variant = "default", projectDirectory } = input;
4364
- const manifestPath = join9(projectDirectory, "fornix.json");
4365
- if (!existsSync6(manifestPath)) {
4675
+ const manifestPath = join11(projectDirectory, "fornix.json");
4676
+ if (!existsSync8(manifestPath)) {
4366
4677
  return err(
4367
4678
  new Error("No fornix.json found. Not a Fornix project directory.")
4368
4679
  );
4369
4680
  }
4370
4681
  let manifest2;
4371
4682
  try {
4372
- const raw = readFileSync7(manifestPath, "utf-8");
4683
+ const raw = readFileSync9(manifestPath, "utf-8");
4373
4684
  manifest2 = JSON.parse(raw);
4374
4685
  } catch {
4375
4686
  return err(new Error("Failed to parse fornix.json."));
4376
4687
  }
4377
- const blockManifest = FIXTURE_MANIFESTS[name];
4688
+ const registryResult = await fetchRegistryIndex();
4689
+ if (!isOk(registryResult)) {
4690
+ return err(new Error(`Failed to fetch block registry: ${registryResult.error.message}`));
4691
+ }
4692
+ const manifests = registryResult.value.blocks;
4693
+ const blockManifest = manifests[name];
4378
4694
  if (!blockManifest) {
4379
4695
  return err(
4380
4696
  new Error(
4381
- `Block '${name}' not found in registry. Available: ${Object.keys(FIXTURE_MANIFESTS).join(", ")}`
4697
+ `Block '${name}' not found in registry. Available: ${Object.keys(manifests).join(", ")}`
4382
4698
  )
4383
4699
  );
4384
4700
  }
@@ -4386,9 +4702,9 @@ function addBlock2(input) {
4386
4702
  if (installedNames.has(name)) {
4387
4703
  return ok({ addedBlocks: [], filesCreated: 0 });
4388
4704
  }
4389
- const blocksToAdd = resolveDependencies3(name, installedNames);
4705
+ const blocksToAdd = resolveDependencies3(name, installedNames, manifests);
4390
4706
  for (const blockName of blocksToAdd) {
4391
- const dependencyManifest = FIXTURE_MANIFESTS[blockName];
4707
+ const dependencyManifest = manifests[blockName];
4392
4708
  if (dependencyManifest?.requiredMode && manifest2.renderMode !== dependencyManifest.requiredMode) {
4393
4709
  return err(
4394
4710
  new Error(
@@ -4398,14 +4714,15 @@ function addBlock2(input) {
4398
4714
  }
4399
4715
  }
4400
4716
  let filesCreated = 0;
4401
- for (const blockName of blocksToAdd) {
4402
- const blockDef = FIXTURE_MANIFESTS[blockName];
4403
- const sources = FIXTURE_BLOCK_SOURCES[blockName];
4404
- if (!blockDef || !sources) {
4405
- return err(
4406
- new Error(`Source files not found for block '${blockName}'.`)
4407
- );
4408
- }
4717
+ const blockResults = await fetchBlocks(blocksToAdd);
4718
+ for (let i = 0; i < blocksToAdd.length; i++) {
4719
+ const blockName = blocksToAdd[i];
4720
+ const result = blockResults[i];
4721
+ if (!result || !isOk(result)) {
4722
+ return err(new Error(`Failed to fetch files for block '${blockName}'.`));
4723
+ }
4724
+ const blockDef = result.value.manifest;
4725
+ const sources = result.value.files;
4409
4726
  for (const file of blockDef.files) {
4410
4727
  const content = sources[file.source];
4411
4728
  if (content === void 0) {
@@ -4415,15 +4732,15 @@ function addBlock2(input) {
4415
4732
  )
4416
4733
  );
4417
4734
  }
4418
- const filePath = join9(projectDirectory, file.destination);
4419
- mkdirSync4(dirname5(filePath), { recursive: true });
4420
- writeFileSync5(filePath, content);
4735
+ const filePath = join11(projectDirectory, file.destination);
4736
+ mkdirSync6(dirname5(filePath), { recursive: true });
4737
+ writeFileSync6(filePath, content);
4421
4738
  filesCreated++;
4422
4739
  }
4423
4740
  }
4424
4741
  const now = (/* @__PURE__ */ new Date()).toISOString();
4425
4742
  for (const blockName of blocksToAdd) {
4426
- const blockDef = FIXTURE_MANIFESTS[blockName];
4743
+ const blockDef = manifests[blockName];
4427
4744
  if (!blockDef) continue;
4428
4745
  manifest2.blocks.push({
4429
4746
  name: blockName,
@@ -4432,16 +4749,16 @@ function addBlock2(input) {
4432
4749
  installedAt: now
4433
4750
  });
4434
4751
  }
4435
- writeFileSync5(manifestPath, JSON.stringify(manifest2, null, 2) + "\n");
4752
+ writeFileSync6(manifestPath, JSON.stringify(manifest2, null, 2) + "\n");
4436
4753
  return ok({ addedBlocks: blocksToAdd, filesCreated });
4437
4754
  }
4438
- function resolveDependencies3(blockName, installedNames) {
4755
+ function resolveDependencies3(blockName, installedNames, manifests) {
4439
4756
  const result = [];
4440
4757
  const visited = /* @__PURE__ */ new Set();
4441
4758
  function walk(currentName) {
4442
4759
  if (visited.has(currentName) || installedNames.has(currentName)) return;
4443
4760
  visited.add(currentName);
4444
- const manifest2 = FIXTURE_MANIFESTS[currentName];
4761
+ const manifest2 = manifests[currentName];
4445
4762
  if (!manifest2) return;
4446
4763
  for (const dependency of manifest2.requires) {
4447
4764
  walk(dependency);
@@ -4454,34 +4771,39 @@ function resolveDependencies3(blockName, installedNames) {
4454
4771
 
4455
4772
  // src/mcp/tools/remove-block.ts
4456
4773
  import {
4457
- readFileSync as readFileSync8,
4458
- writeFileSync as writeFileSync6,
4459
- existsSync as existsSync7,
4774
+ readFileSync as readFileSync10,
4775
+ writeFileSync as writeFileSync7,
4776
+ existsSync as existsSync9,
4460
4777
  unlinkSync as unlinkSync2,
4461
- readdirSync as readdirSync3,
4778
+ readdirSync as readdirSync4,
4462
4779
  rmdirSync as rmdirSync2
4463
4780
  } from "fs";
4464
- import { join as join10, dirname as dirname6 } from "path";
4465
- function removeBlock(input) {
4781
+ import { join as join12, dirname as dirname6 } from "path";
4782
+ async function removeBlock(input) {
4466
4783
  const { name, force = false, projectDirectory } = input;
4467
- const manifestPath = join10(projectDirectory, "fornix.json");
4468
- if (!existsSync7(manifestPath)) {
4784
+ const manifestPath = join12(projectDirectory, "fornix.json");
4785
+ if (!existsSync9(manifestPath)) {
4469
4786
  return err(
4470
4787
  new Error("No fornix.json found. Not a Fornix project directory.")
4471
4788
  );
4472
4789
  }
4473
4790
  let manifest2;
4474
4791
  try {
4475
- const raw = readFileSync8(manifestPath, "utf-8");
4792
+ const raw = readFileSync10(manifestPath, "utf-8");
4476
4793
  manifest2 = JSON.parse(raw);
4477
4794
  } catch {
4478
4795
  return err(new Error("Failed to parse fornix.json."));
4479
4796
  }
4797
+ const registryResult = await fetchRegistryIndex();
4798
+ if (!isOk(registryResult)) {
4799
+ return err(new Error(`Failed to fetch block registry: ${registryResult.error.message}`));
4800
+ }
4801
+ const manifests = registryResult.value.blocks;
4480
4802
  const installedNames = new Set(manifest2.blocks.map((block) => block.name));
4481
4803
  if (!installedNames.has(name)) {
4482
4804
  return err(new Error(`Block '${name}' is not installed.`));
4483
4805
  }
4484
- const dependents = findDependents2(name, installedNames);
4806
+ const dependents = findDependents2(name, installedNames, manifests);
4485
4807
  if (dependents.length > 0 && !force) {
4486
4808
  return err(
4487
4809
  new Error(
@@ -4489,12 +4811,12 @@ function removeBlock(input) {
4489
4811
  )
4490
4812
  );
4491
4813
  }
4492
- const blockManifest = FIXTURE_MANIFESTS[name];
4814
+ const blockManifest = manifests[name];
4493
4815
  const filesToRemove = [];
4494
4816
  if (blockManifest) {
4495
4817
  for (const file of blockManifest.files) {
4496
- const filePath = join10(projectDirectory, file.destination);
4497
- if (existsSync7(filePath)) {
4818
+ const filePath = join12(projectDirectory, file.destination);
4819
+ if (existsSync9(filePath)) {
4498
4820
  filesToRemove.push(filePath);
4499
4821
  }
4500
4822
  }
@@ -4504,17 +4826,17 @@ function removeBlock(input) {
4504
4826
  tryRemoveEmptyDirectory(dirname6(filePath), projectDirectory);
4505
4827
  }
4506
4828
  manifest2.blocks = manifest2.blocks.filter((block) => block.name !== name);
4507
- writeFileSync6(manifestPath, JSON.stringify(manifest2, null, 2) + "\n");
4829
+ writeFileSync7(manifestPath, JSON.stringify(manifest2, null, 2) + "\n");
4508
4830
  return ok({
4509
4831
  removedBlock: name,
4510
4832
  filesRemoved: filesToRemove.length,
4511
4833
  dependentsWarning: dependents
4512
4834
  });
4513
4835
  }
4514
- function findDependents2(blockName, installedNames) {
4836
+ function findDependents2(blockName, installedNames, manifests) {
4515
4837
  const dependents = [];
4516
4838
  for (const installedName of installedNames) {
4517
- const manifest2 = FIXTURE_MANIFESTS[installedName];
4839
+ const manifest2 = manifests[installedName];
4518
4840
  if (manifest2 && manifest2.requires.includes(blockName)) {
4519
4841
  dependents.push(installedName);
4520
4842
  }
@@ -4524,7 +4846,7 @@ function findDependents2(blockName, installedNames) {
4524
4846
  function tryRemoveEmptyDirectory(directoryPath, rootPath) {
4525
4847
  if (directoryPath === rootPath || !directoryPath.startsWith(rootPath)) return;
4526
4848
  try {
4527
- const entries = readdirSync3(directoryPath);
4849
+ const entries = readdirSync4(directoryPath);
4528
4850
  if (entries.length === 0) {
4529
4851
  rmdirSync2(directoryPath);
4530
4852
  tryRemoveEmptyDirectory(dirname6(directoryPath), rootPath);
@@ -4534,33 +4856,51 @@ function tryRemoveEmptyDirectory(directoryPath, rootPath) {
4534
4856
  }
4535
4857
 
4536
4858
  // src/mcp/tools/get-content-schema.ts
4537
- function getContentSchema(input) {
4538
- const { collection } = input;
4539
- const manifest2 = FIXTURE_MANIFESTS[collection];
4859
+ async function getContentSchemaHandler(args2) {
4860
+ const typedArgs = args2;
4861
+ if (!typedArgs?.block) {
4862
+ throw new Error("Missing required argument: block");
4863
+ }
4864
+ const result = await fetchRegistryIndex();
4865
+ if (!isOk(result)) {
4866
+ throw new Error(`Failed to fetch block registry: ${result.error.message}`);
4867
+ }
4868
+ const manifests = result.value.blocks;
4869
+ const manifest2 = manifests[typedArgs.block];
4540
4870
  if (!manifest2) {
4541
- return err(
4542
- new Error(`Collection '${collection}' not found in registry.`)
4543
- );
4871
+ throw new Error(`Block '${typedArgs.block}' not found in registry`);
4544
4872
  }
4545
- const contentSlots = manifest2.ai?.contentSlots;
4546
- if (!contentSlots || Object.keys(contentSlots).length === 0) {
4547
- return err(
4548
- new Error(
4549
- `Block '${collection}' does not define content slots.`
4550
- )
4551
- );
4873
+ const slots = manifest2.ai?.contentSlots ?? {};
4874
+ if (Object.keys(slots).length === 0) {
4875
+ return {
4876
+ content: [
4877
+ {
4878
+ type: "text",
4879
+ text: `Block '${typedArgs.block}' does not have any AI-configurable content slots.`
4880
+ }
4881
+ ]
4882
+ };
4552
4883
  }
4553
- return ok({
4554
- collection,
4555
- slots: contentSlots
4556
- });
4884
+ return {
4885
+ content: [
4886
+ {
4887
+ type: "text",
4888
+ text: JSON.stringify(slots, null, 2)
4889
+ }
4890
+ ]
4891
+ };
4557
4892
  }
4558
4893
 
4559
4894
  // src/mcp/tools/validate-content.ts
4560
4895
  import { z as z5 } from "zod";
4561
- function validateContent(input) {
4896
+ async function validateContent(input) {
4562
4897
  const { collection, data } = input;
4563
- const manifest2 = FIXTURE_MANIFESTS[collection];
4898
+ const registryResult = await fetchRegistryIndex();
4899
+ if (!isOk(registryResult)) {
4900
+ return err(new Error(`Failed to fetch block registry: ${registryResult.error.message}`));
4901
+ }
4902
+ const manifests = registryResult.value.blocks;
4903
+ const manifest2 = manifests[collection];
4564
4904
  if (!manifest2) {
4565
4905
  return err(
4566
4906
  new Error(
@@ -4608,17 +4948,17 @@ function zodTypeForSlot2(slotType) {
4608
4948
  }
4609
4949
 
4610
4950
  // src/mcp/tools/get-project-status.ts
4611
- import { readFileSync as readFileSync9, existsSync as existsSync8 } from "fs";
4612
- import { join as join11 } from "path";
4951
+ import { readFileSync as readFileSync11, existsSync as existsSync10 } from "fs";
4952
+ import { join as join13 } from "path";
4613
4953
  function getProjectStatus(input) {
4614
- const manifestPath = join11(input.projectDirectory, "fornix.json");
4615
- if (!existsSync8(manifestPath)) {
4954
+ const manifestPath = join13(input.projectDirectory, "fornix.json");
4955
+ if (!existsSync10(manifestPath)) {
4616
4956
  return err(
4617
4957
  new Error("No fornix.json found. Not a Fornix project directory.")
4618
4958
  );
4619
4959
  }
4620
4960
  try {
4621
- const raw = readFileSync9(manifestPath, "utf-8");
4961
+ const raw = readFileSync11(manifestPath, "utf-8");
4622
4962
  const manifest2 = JSON.parse(raw);
4623
4963
  const blocks = manifest2.blocks;
4624
4964
  return ok({
@@ -4640,8 +4980,8 @@ function getProjectStatus(input) {
4640
4980
  }
4641
4981
 
4642
4982
  // src/mcp/tools/scaffold-project.ts
4643
- import { mkdirSync as mkdirSync5, writeFileSync as writeFileSync7 } from "fs";
4644
- import { join as join12, basename as basename3 } from "path";
4983
+ import { mkdirSync as mkdirSync7, writeFileSync as writeFileSync8 } from "fs";
4984
+ import { join as join14, basename as basename3 } from "path";
4645
4985
  var DEFAULT_COLORS2 = {
4646
4986
  primary: "#6366f1",
4647
4987
  secondary: "#818cf8",
@@ -4649,7 +4989,7 @@ var DEFAULT_COLORS2 = {
4649
4989
  background: "#0f172a",
4650
4990
  foreground: "#f8fafc"
4651
4991
  };
4652
- function scaffoldProject(input) {
4992
+ async function scaffoldProject(input) {
4653
4993
  const {
4654
4994
  projectDirectory,
4655
4995
  renderMode = "static",
@@ -4657,9 +4997,14 @@ function scaffoldProject(input) {
4657
4997
  blocks = [],
4658
4998
  locales = ["en"]
4659
4999
  } = input;
5000
+ const registryResult = await fetchRegistryIndex();
5001
+ if (!isOk(registryResult)) {
5002
+ return err(new Error(`Failed to fetch block registry: ${registryResult.error.message}`));
5003
+ }
5004
+ const manifests = registryResult.value.blocks;
5005
+ const allPalettes = registryResult.value.palettes.length > 0 ? registryResult.value.palettes : loadAllPalettes();
4660
5006
  const projectName = basename3(projectDirectory);
4661
5007
  const blockSelections = blocks.map((name) => ({ name, variant: "default" }));
4662
- const allPalettes = loadAllPalettes();
4663
5008
  const config = {
4664
5009
  projectName,
4665
5010
  projectDir: projectDirectory,
@@ -4677,11 +5022,27 @@ function scaffoldProject(input) {
4677
5022
  themeSwitcher: false,
4678
5023
  createdWith: "mcp"
4679
5024
  };
5025
+ const blockResults = await fetchBlocks([...blocks]);
5026
+ const blockSources = {};
5027
+ const blockDefaultContent = {};
5028
+ for (const result2 of blockResults) {
5029
+ if (!isOk(result2)) {
5030
+ return err(new Error(`Failed to fetch block '${result2.error.blockName}': ${result2.error.message}`));
5031
+ }
5032
+ const { manifest: manifest2, files: files2 } = result2.value;
5033
+ blockSources[manifest2.name] = files2;
5034
+ try {
5035
+ if (files2["default-content.json"]) {
5036
+ blockDefaultContent[manifest2.name] = JSON.parse(files2["default-content.json"]);
5037
+ }
5038
+ } catch {
5039
+ }
5040
+ }
4680
5041
  const scaffoldInput = {
4681
5042
  config,
4682
- manifests: FIXTURE_MANIFESTS,
4683
- blockSources: FIXTURE_BLOCK_SOURCES,
4684
- blockDefaultContent: FIXTURE_DEFAULT_CONTENT,
5043
+ manifests,
5044
+ blockSources,
5045
+ blockDefaultContent,
4685
5046
  allPalettes
4686
5047
  };
4687
5048
  const result = scaffold(scaffoldInput);
@@ -4691,10 +5052,10 @@ function scaffoldProject(input) {
4691
5052
  const files = result.value.files;
4692
5053
  let filesCreated = 0;
4693
5054
  for (const [relativePath, content] of Object.entries(files)) {
4694
- const fullPath = join12(projectDirectory, relativePath);
4695
- const parentDirectory = join12(fullPath, "..");
4696
- mkdirSync5(parentDirectory, { recursive: true });
4697
- writeFileSync7(fullPath, content, "utf-8");
5055
+ const fullPath = join14(projectDirectory, relativePath);
5056
+ const parentDirectory = join14(fullPath, "..");
5057
+ mkdirSync7(parentDirectory, { recursive: true });
5058
+ writeFileSync8(fullPath, content, "utf-8");
4698
5059
  filesCreated++;
4699
5060
  }
4700
5061
  return ok({
@@ -4891,7 +5252,11 @@ var FornixMCPServer = class {
4891
5252
  async (request) => {
4892
5253
  const uri = request.params.uri;
4893
5254
  if (uri === "fornix://registry") {
4894
- const blocks = Object.values(FIXTURE_MANIFESTS).map((manifest2) => ({
5255
+ const registryResult = await fetchRegistryIndex();
5256
+ if (!isOk(registryResult)) {
5257
+ throw new Error(`Failed to fetch block registry: ${registryResult.error.message}`);
5258
+ }
5259
+ const blocks = Object.values(registryResult.value.blocks).map((manifest2) => ({
4895
5260
  name: manifest2.name,
4896
5261
  type: manifest2.type,
4897
5262
  category: manifest2.category,
@@ -4934,16 +5299,19 @@ var FornixMCPServer = class {
4934
5299
  async executeTool(toolName, args2) {
4935
5300
  switch (toolName) {
4936
5301
  case "list_blocks": {
4937
- const result = listBlocks({
4938
- type: args2.type,
4939
- category: args2.category,
4940
- search: args2.search
4941
- });
4942
- if (!result.ok) return err(result.error);
4943
- return ok(JSON.stringify(result.value, null, 2));
5302
+ try {
5303
+ const response = await listBlocksHandler({
5304
+ type: args2.type,
5305
+ category: args2.category,
5306
+ search: args2.search
5307
+ });
5308
+ return ok(response.content[0].text);
5309
+ } catch (e) {
5310
+ return err(e instanceof Error ? e : new Error(String(e)));
5311
+ }
4944
5312
  }
4945
5313
  case "add_block": {
4946
- const result = addBlock2({
5314
+ const result = await addBlock2({
4947
5315
  name: args2.name,
4948
5316
  variant: args2.variant,
4949
5317
  projectDirectory: args2.projectDirectory
@@ -4952,7 +5320,7 @@ var FornixMCPServer = class {
4952
5320
  return ok(JSON.stringify(result.value, null, 2));
4953
5321
  }
4954
5322
  case "remove_block": {
4955
- const result = removeBlock({
5323
+ const result = await removeBlock({
4956
5324
  name: args2.name,
4957
5325
  force: args2.force,
4958
5326
  projectDirectory: args2.projectDirectory
@@ -4961,14 +5329,17 @@ var FornixMCPServer = class {
4961
5329
  return ok(JSON.stringify(result.value, null, 2));
4962
5330
  }
4963
5331
  case "get_content_schema": {
4964
- const result = getContentSchema({
4965
- collection: args2.collection
4966
- });
4967
- if (!result.ok) return err(result.error);
4968
- return ok(JSON.stringify(result.value, null, 2));
5332
+ try {
5333
+ const response = await getContentSchemaHandler({
5334
+ block: args2.collection
5335
+ });
5336
+ return ok(response.content[0].text);
5337
+ } catch (e) {
5338
+ return err(e instanceof Error ? e : new Error(String(e)));
5339
+ }
4969
5340
  }
4970
5341
  case "update_content": {
4971
- const validationResult = validateContent({
5342
+ const validationResult = await validateContent({
4972
5343
  collection: args2.collection,
4973
5344
  data: args2.data
4974
5345
  });
@@ -4990,7 +5361,7 @@ var FornixMCPServer = class {
4990
5361
  );
4991
5362
  }
4992
5363
  case "validate_content": {
4993
- const result = validateContent({
5364
+ const result = await validateContent({
4994
5365
  collection: args2.collection,
4995
5366
  data: args2.data
4996
5367
  });
@@ -5005,7 +5376,7 @@ var FornixMCPServer = class {
5005
5376
  return ok(JSON.stringify(result.value, null, 2));
5006
5377
  }
5007
5378
  case "scaffold_project": {
5008
- const result = scaffoldProject({
5379
+ const result = await scaffoldProject({
5009
5380
  description: args2.description,
5010
5381
  projectDirectory: args2.projectDirectory,
5011
5382
  renderMode: args2.renderMode,