@nuucognition/flint-cli 0.2.0-beta.1 → 0.3.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
- // ../../packages/flint/dist/chunk-OXC4WBGK.js
2
- import { readFile, writeFile, stat } from "fs/promises";
3
- import { join } from "path";
1
+ // ../../packages/flint/dist/chunk-HP5CLO2G.js
2
+ import { readFile, writeFile, stat, mkdir } from "fs/promises";
3
+ import { join as pathJoin } from "path";
4
4
 
5
5
  // ../../node_modules/.pnpm/smol-toml@1.6.0/node_modules/smol-toml/dist/error.js
6
6
  function getLineColFromPtr(string, ptr) {
@@ -828,12 +828,11 @@ function stringify(obj, { maxDepth = 1e3, numbersAsFloat = false } = {}) {
828
828
  return str;
829
829
  }
830
830
 
831
- // ../../packages/flint/dist/chunk-OXC4WBGK.js
831
+ // ../../packages/flint/dist/chunk-HP5CLO2G.js
832
832
  import { randomUUID } from "crypto";
833
+ var join = pathJoin;
833
834
  function resolveShardMode(decl) {
834
- if (decl.mode) return decl.mode;
835
- if (decl.dev) return "dev";
836
- return void 0;
835
+ return decl.mode;
837
836
  }
838
837
  function isLocalShard(decl) {
839
838
  const mode = resolveShardMode(decl);
@@ -841,7 +840,7 @@ function isLocalShard(decl) {
841
840
  }
842
841
  var FLINT_CONFIG_FILENAME = "flint.toml";
843
842
  var FLINT_JSON_FILENAME = "flint.json";
844
- var FLINT_VERSION = "0.2.0";
843
+ var FLINT_VERSION = "0.3.0";
845
844
  function toKebabCase(name) {
846
845
  return name.replace(/\([^)]*\)\s*/g, "").toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "").replace(/^-+|-+$/g, "");
847
846
  }
@@ -871,29 +870,17 @@ var DEFAULT_SHARD_SOURCES = {
871
870
  orbcode: "NUU-Cognition/shard-orbcode",
872
871
  projects: "NUU-Cognition/shard-projects"
873
872
  };
874
- var DEFAULT_MOD_SOURCES = {
875
- "claude-code": "NUU-Cognition/flint-mod-claude-code",
876
- agents: "NUU-Cognition/flint-mod-agents"
877
- };
878
- function createFlintToml(name, shards = [], mods = [], type = "flint") {
873
+ function createFlintToml(name, shards = []) {
879
874
  const shardDeclarations = {};
880
875
  for (const shard of shards) {
881
876
  shardDeclarations[shard] = { source: DEFAULT_SHARD_SOURCES[shard] || shard };
882
877
  }
883
878
  const config = {
884
879
  flint: {
885
- name,
886
- type
880
+ name
887
881
  },
888
882
  shards: shardDeclarations
889
883
  };
890
- if (mods.length > 0) {
891
- const modDeclarations = {};
892
- for (const mod of mods) {
893
- modDeclarations[mod] = { source: DEFAULT_MOD_SOURCES[mod] || mod };
894
- }
895
- config.mods = modDeclarations;
896
- }
897
884
  return config;
898
885
  }
899
886
  function createFlintJson() {
@@ -1020,18 +1007,6 @@ function formatFlintToml(config) {
1020
1007
  lines.push("");
1021
1008
  }
1022
1009
  }
1023
- if (config.mods) {
1024
- const modDeclarations = getModDeclarationsFromConfig(config);
1025
- if (Object.keys(modDeclarations).length > 0) {
1026
- lines.push("[mods]");
1027
- for (const [name, decl] of Object.entries(modDeclarations)) {
1028
- const fields = { source: decl.source };
1029
- if (decl.dev) fields.dev = true;
1030
- lines.push(`${name} = ${inlineTable(fields)}`);
1031
- }
1032
- lines.push("");
1033
- }
1034
- }
1035
1010
  if (config.exports?.required?.length) {
1036
1011
  lines.push("[exports]");
1037
1012
  const items = config.exports.required.map((e) => {
@@ -1075,15 +1050,18 @@ function formatFlintToml(config) {
1075
1050
  lines.push(`flints = ${inlineTableArray(items).join("\n")}`);
1076
1051
  lines.push("");
1077
1052
  }
1078
- if (config.lattices?.length) {
1079
- for (const lattice of config.lattices) {
1080
- lines.push("[[lattices]]");
1081
- lines.push(`name = ${tv(lattice.name)}`);
1082
- lines.push(`path = ${tv(lattice.path)}`);
1083
- lines.push("");
1084
- }
1053
+ if (config.git?.remote) {
1054
+ lines.push("[git]");
1055
+ lines.push(`remote = ${tv(config.git.remote)}`);
1056
+ lines.push("");
1085
1057
  }
1086
- const knownKeys = /* @__PURE__ */ new Set(["flint", "shards", "mods", "exports", "imports", "workspace", "connections", "lattices"]);
1058
+ if (config.lattices?.references?.length) {
1059
+ lines.push("[lattices]");
1060
+ const items = config.lattices.references.map((l) => ({ name: l.name }));
1061
+ lines.push(`references = ${inlineTableArray(items).join("\n")}`);
1062
+ lines.push("");
1063
+ }
1064
+ const knownKeys = /* @__PURE__ */ new Set(["flint", "shards", "exports", "imports", "workspace", "connections", "git", "lattices"]);
1087
1065
  const unknownKeys = Object.keys(config).filter((k) => !knownKeys.has(k));
1088
1066
  if (unknownKeys.length > 0) {
1089
1067
  const unknownConfig = {};
@@ -1118,8 +1096,7 @@ async function addShardToConfig(flintPath, shardName, source, options = {}) {
1118
1096
  const effectiveSource = source || kebabName;
1119
1097
  if (!existing || existing.source !== effectiveSource) {
1120
1098
  const decl = { source: effectiveSource };
1121
- const effectiveMode = options.mode || (options.dev ? "dev" : void 0);
1122
- if (effectiveMode) decl.mode = effectiveMode;
1099
+ if (options.mode) decl.mode = options.mode;
1123
1100
  config.shards[kebabName] = decl;
1124
1101
  await writeFlintToml(flintPath, config);
1125
1102
  }
@@ -1136,70 +1113,6 @@ async function removeShardFromConfig(flintPath, shardName) {
1136
1113
  }
1137
1114
  await writeFlintToml(flintPath, config);
1138
1115
  }
1139
- async function addModToConfig(flintPath, modName, source = "builtin", options = {}) {
1140
- let config = await readFlintToml(flintPath);
1141
- if (!config) {
1142
- throw new Error("flint.toml not found");
1143
- }
1144
- const kebabName = toKebabCase(modName);
1145
- if (!config.mods) {
1146
- config.mods = {};
1147
- }
1148
- const declaration = { source };
1149
- if (options.dev) declaration.dev = true;
1150
- config.mods[kebabName] = declaration;
1151
- await writeFlintToml(flintPath, config);
1152
- }
1153
- async function removeModFromConfig(flintPath, modName) {
1154
- let config = await readFlintToml(flintPath);
1155
- if (!config?.mods) return;
1156
- const kebabName = toKebabCase(modName);
1157
- delete config.mods[kebabName];
1158
- if (config.mods.required) {
1159
- config.mods.required = config.mods.required.filter((n) => n !== kebabName);
1160
- }
1161
- await writeFlintToml(flintPath, config);
1162
- }
1163
- function getModDeclarationsFromConfig(config) {
1164
- if (!config.mods) return {};
1165
- const declarations = {};
1166
- for (const [key, value] of Object.entries(config.mods)) {
1167
- if (key === "required") continue;
1168
- if (value && typeof value === "object" && !Array.isArray(value) && "source" in value) {
1169
- declarations[key] = value;
1170
- }
1171
- }
1172
- if (config.mods.required && Array.isArray(config.mods.required)) {
1173
- for (const name of config.mods.required) {
1174
- if (!declarations[name]) {
1175
- declarations[name] = { source: "builtin" };
1176
- }
1177
- }
1178
- }
1179
- return declarations;
1180
- }
1181
- async function getModDeclarations(flintPath) {
1182
- const config = await readFlintToml(flintPath);
1183
- if (!config) return {};
1184
- return getModDeclarationsFromConfig(config);
1185
- }
1186
- async function migrateModConfig(flintPath) {
1187
- const config = await readFlintToml(flintPath);
1188
- if (!config?.mods?.required || !Array.isArray(config.mods.required)) {
1189
- return false;
1190
- }
1191
- if (config.mods.required.length === 0) {
1192
- return false;
1193
- }
1194
- for (const name of config.mods.required) {
1195
- if (!config.mods[name]) {
1196
- config.mods[name] = { source: "builtin" };
1197
- }
1198
- }
1199
- delete config.mods.required;
1200
- await writeFlintToml(flintPath, config);
1201
- return true;
1202
- }
1203
1116
  async function getRequiredShardNames(flintPath) {
1204
1117
  const config = await readFlintToml(flintPath);
1205
1118
  if (!config?.shards) return [];
@@ -1374,40 +1287,101 @@ async function getWorkspaceSourceRepository(flintPath, name) {
1374
1287
  const normalizedName = name.toLowerCase();
1375
1288
  return config?.workspace?.sources?.repositories?.find((r) => r.name.toLowerCase() === normalizedName) || null;
1376
1289
  }
1377
- async function addLatticeReference(flintPath, name, path) {
1290
+ function getLatticesStatePath(flintPath) {
1291
+ return pathJoin(flintPath, ".flint", "lattices.json");
1292
+ }
1293
+ async function readLatticesState(flintPath) {
1294
+ const statePath = getLatticesStatePath(flintPath);
1295
+ try {
1296
+ const content = await readFile(statePath, "utf-8");
1297
+ return JSON.parse(content);
1298
+ } catch {
1299
+ return { version: 1, lattices: [] };
1300
+ }
1301
+ }
1302
+ async function writeLatticesState(flintPath, state) {
1303
+ const statePath = getLatticesStatePath(flintPath);
1304
+ const dir = pathJoin(flintPath, ".flint");
1305
+ await mkdir(dir, { recursive: true });
1306
+ await writeFile(statePath, JSON.stringify(state, null, 2) + "\n");
1307
+ }
1308
+ async function addLatticeDeclaration(flintPath, name) {
1378
1309
  let config = await readFlintToml(flintPath);
1379
1310
  if (!config) {
1380
1311
  throw new Error("flint.toml not found");
1381
1312
  }
1382
1313
  if (!config.lattices) {
1383
- config.lattices = [];
1314
+ config.lattices = { references: [] };
1384
1315
  }
1385
- const existing = config.lattices.find((entry) => entry.name.toLowerCase() === name.toLowerCase());
1316
+ if (!config.lattices.references) {
1317
+ config.lattices.references = [];
1318
+ }
1319
+ const existing = config.lattices.references.find(
1320
+ (entry) => entry.name.toLowerCase() === name.toLowerCase()
1321
+ );
1386
1322
  if (existing) {
1387
- throw new Error(`Lattice "${name}" already exists`);
1323
+ throw new Error(`Lattice "${name}" is already declared`);
1388
1324
  }
1389
- config.lattices.push({ name, path });
1325
+ config.lattices.references.push({ name });
1390
1326
  await writeFlintToml(flintPath, config);
1391
1327
  }
1392
- async function removeLatticeReference(flintPath, name) {
1328
+ async function removeLatticeDeclaration(flintPath, name) {
1393
1329
  let config = await readFlintToml(flintPath);
1394
- if (!config?.lattices) return false;
1330
+ if (!config?.lattices?.references) return false;
1395
1331
  const normalizedName = name.toLowerCase();
1396
- const index = config.lattices.findIndex((entry) => entry.name.toLowerCase() === normalizedName);
1332
+ const index = config.lattices.references.findIndex(
1333
+ (entry) => entry.name.toLowerCase() === normalizedName
1334
+ );
1397
1335
  if (index === -1) return false;
1398
- config.lattices.splice(index, 1);
1336
+ config.lattices.references.splice(index, 1);
1399
1337
  await writeFlintToml(flintPath, config);
1338
+ const state = await readLatticesState(flintPath);
1339
+ state.lattices = state.lattices.filter(
1340
+ (l) => l.name.toLowerCase() !== normalizedName
1341
+ );
1342
+ await writeLatticesState(flintPath, state);
1400
1343
  return true;
1401
1344
  }
1402
- async function getLatticeReferences(flintPath) {
1345
+ async function fulfillLattice(flintPath, name, latticePath, lang) {
1346
+ const fulfillment = {
1347
+ name,
1348
+ path: latticePath,
1349
+ lang,
1350
+ fulfilled: (/* @__PURE__ */ new Date()).toISOString()
1351
+ };
1352
+ const state = await readLatticesState(flintPath);
1353
+ const existingIndex = state.lattices.findIndex(
1354
+ (l) => l.name.toLowerCase() === name.toLowerCase()
1355
+ );
1356
+ if (existingIndex >= 0) {
1357
+ state.lattices[existingIndex] = fulfillment;
1358
+ } else {
1359
+ state.lattices.push(fulfillment);
1360
+ }
1361
+ await writeLatticesState(flintPath, state);
1362
+ return fulfillment;
1363
+ }
1364
+ async function getLatticeDeclarations(flintPath) {
1403
1365
  const config = await readFlintToml(flintPath);
1404
- return config?.lattices || [];
1366
+ return config?.lattices?.references || [];
1405
1367
  }
1406
- async function getLatticeReference(flintPath, name) {
1368
+ async function getLatticeDeclaration(flintPath, name) {
1407
1369
  const config = await readFlintToml(flintPath);
1408
1370
  const normalizedName = name.toLowerCase();
1409
- return config?.lattices?.find((entry) => entry.name.toLowerCase() === normalizedName) || null;
1410
- }
1371
+ return config?.lattices?.references?.find(
1372
+ (entry) => entry.name.toLowerCase() === normalizedName
1373
+ ) || null;
1374
+ }
1375
+ async function getLatticeFulfillment(flintPath, name) {
1376
+ const state = await readLatticesState(flintPath);
1377
+ return state.lattices.find(
1378
+ (l) => l.name.toLowerCase() === name.toLowerCase()
1379
+ ) || null;
1380
+ }
1381
+ var addLatticeReference = async (flintPath, name, _path) => addLatticeDeclaration(flintPath, name);
1382
+ var removeLatticeReference = async (flintPath, name) => removeLatticeDeclaration(flintPath, name);
1383
+ var getLatticeReferences = async (flintPath) => getLatticeDeclarations(flintPath);
1384
+ var getLatticeReference = async (flintPath, name) => getLatticeDeclaration(flintPath, name);
1411
1385
  async function addExportToConfig(flintPath, declaration) {
1412
1386
  let config = await readFlintToml(flintPath);
1413
1387
  if (!config) {
@@ -1496,19 +1470,6 @@ async function getFlintImports(flintPath) {
1496
1470
  if (!config) return [];
1497
1471
  return resolveFlintImports(config);
1498
1472
  }
1499
- var getRequiredImports = getFlintImports;
1500
- async function addWorkspaceEntry(flintPath, name, path) {
1501
- console.warn("addWorkspaceEntry is deprecated, use addWorkspaceReference instead");
1502
- }
1503
- async function removeWorkspaceEntry(flintPath, name) {
1504
- console.warn("removeWorkspaceEntry is deprecated, use removeWorkspaceReference instead");
1505
- }
1506
- async function getWorkspaceEntries(flintPath) {
1507
- return {};
1508
- }
1509
- async function getWorkspaceEntry(flintPath, name) {
1510
- return null;
1511
- }
1512
1473
 
1513
1474
  export {
1514
1475
  parse,
@@ -1535,11 +1496,6 @@ export {
1535
1496
  writeFlintToml,
1536
1497
  addShardToConfig,
1537
1498
  removeShardFromConfig,
1538
- addModToConfig,
1539
- removeModFromConfig,
1540
- getModDeclarationsFromConfig,
1541
- getModDeclarations,
1542
- migrateModConfig,
1543
1499
  getRequiredShardNames,
1544
1500
  getShardDeclarationsFromConfig,
1545
1501
  getShardDeclarations,
@@ -1558,6 +1514,13 @@ export {
1558
1514
  removeWorkspaceSourceRepository,
1559
1515
  getWorkspaceSourceRepositories,
1560
1516
  getWorkspaceSourceRepository,
1517
+ readLatticesState,
1518
+ addLatticeDeclaration,
1519
+ removeLatticeDeclaration,
1520
+ fulfillLattice,
1521
+ getLatticeDeclarations,
1522
+ getLatticeDeclaration,
1523
+ getLatticeFulfillment,
1561
1524
  addLatticeReference,
1562
1525
  removeLatticeReference,
1563
1526
  getLatticeReferences,
@@ -1567,12 +1530,7 @@ export {
1567
1530
  getExportDeclarations,
1568
1531
  addImportToConfig,
1569
1532
  removeImportFromConfig,
1570
- getFlintImports,
1571
- getRequiredImports,
1572
- addWorkspaceEntry,
1573
- removeWorkspaceEntry,
1574
- getWorkspaceEntries,
1575
- getWorkspaceEntry
1533
+ getFlintImports
1576
1534
  };
1577
1535
  /*! Bundled license information:
1578
1536
 
@@ -0,0 +1,297 @@
1
+ import {
2
+ readFlintToml,
3
+ toKebabCase
4
+ } from "./chunk-KLFK7CPM.js";
5
+
6
+ // ../../packages/flint/dist/chunk-7OFS4TXV.js
7
+ import { join, dirname, basename } from "path";
8
+ import { readFile, writeFile, mkdir, readdir, rm, stat as stat2 } from "fs/promises";
9
+ import { join as join2 } from "path";
10
+ import { randomUUID } from "crypto";
11
+ var FLINT_DIR = ".flint";
12
+ function getFlintConfigDir(flintPath) {
13
+ return join(flintPath, FLINT_DIR);
14
+ }
15
+ function getTypePrefix(_type) {
16
+ return "(Flint)";
17
+ }
18
+ function getMetadataDir(flintPath) {
19
+ return join2(flintPath, "Mesh", "Metadata");
20
+ }
21
+ function getReferencesMetadataDir(flintPath) {
22
+ return join2(getMetadataDir(flintPath), "Codebase References");
23
+ }
24
+ function getConnectionsMetadataDir(flintPath) {
25
+ return join2(getMetadataDir(flintPath), "Flint Connections");
26
+ }
27
+ function getSourcesMetadataDir(flintPath) {
28
+ return join2(getMetadataDir(flintPath), "Sources");
29
+ }
30
+ function getReferenceMetadataPath(flintPath, name) {
31
+ const slug = toKebabCase(name);
32
+ return join2(getReferencesMetadataDir(flintPath), `rf-${slug}.md`);
33
+ }
34
+ function getConnectionMetadataPath(flintPath, name) {
35
+ const slug = toKebabCase(name);
36
+ return join2(getConnectionsMetadataDir(flintPath), `con-${slug}.md`);
37
+ }
38
+ function getSourceMetadataPath(flintPath, importRef) {
39
+ const slug = toKebabCase(importRef.replace("/", "-"));
40
+ return join2(getSourcesMetadataDir(flintPath), `src-${slug}.md`);
41
+ }
42
+ async function fileExists(path) {
43
+ try {
44
+ await stat2(path);
45
+ return true;
46
+ } catch {
47
+ return false;
48
+ }
49
+ }
50
+ function extractId(content) {
51
+ const match = content.match(/^id:\s*(.+)$/m);
52
+ return match?.[1]?.trim() || null;
53
+ }
54
+ function extractNotesSection(content) {
55
+ const body = content.replace(/^---\n[\s\S]*?\n---\n*/, "").trim();
56
+ const idx = body.indexOf("## Notes");
57
+ if (idx === -1) return null;
58
+ return body.substring(idx).trim();
59
+ }
60
+ async function syncMetadataFile(filePath, buildContent) {
61
+ let existingId = null;
62
+ let existingNotes = null;
63
+ if (await fileExists(filePath)) {
64
+ const existing = await readFile(filePath, "utf-8");
65
+ existingId = extractId(existing);
66
+ existingNotes = extractNotesSection(existing);
67
+ }
68
+ const id = existingId || randomUUID();
69
+ const notes = existingNotes || "## Notes\n\n(Add notes here)";
70
+ const newContent = buildContent(id, notes);
71
+ if (existingId) {
72
+ const existing = await readFile(filePath, "utf-8");
73
+ if (existing === newContent) {
74
+ return "synced";
75
+ }
76
+ }
77
+ await writeFile(filePath, newContent);
78
+ return existingId ? "synced" : "created";
79
+ }
80
+ function buildReferenceContent(ref, id, notes) {
81
+ return `---
82
+ id: ${id}
83
+ tags:
84
+ - "#f/metadata"
85
+ - "#f/reference"
86
+ type: ${ref.type}
87
+ ---
88
+
89
+ Execute \`flint resolve codebase ${ref.name}\` to get the local path.
90
+
91
+ ${notes}
92
+ `;
93
+ }
94
+ function buildConnectionContent(declaration, id, notes) {
95
+ return `---
96
+ id: ${id}
97
+ tags:
98
+ - "#f/metadata"
99
+ - "#f/connection"
100
+ type: flint
101
+ ---
102
+
103
+ Execute \`flint resolve connection ${declaration.name}\` to get the local path.
104
+
105
+ ${notes}
106
+ `;
107
+ }
108
+ function buildSourceContent(importRef, id, notes) {
109
+ return `---
110
+ id: ${id}
111
+ tags:
112
+ - "#f/metadata"
113
+ - "#f/source"
114
+ type: flint-export
115
+ ---
116
+
117
+ Execute \`flint resolve source "${importRef}"\` to get the local path.
118
+
119
+ ${notes}
120
+ `;
121
+ }
122
+ async function generateReferenceMetadata(flintPath, ref) {
123
+ const filePath = getReferenceMetadataPath(flintPath, ref.name);
124
+ await mkdir(getReferencesMetadataDir(flintPath), { recursive: true });
125
+ const result = await syncMetadataFile(
126
+ filePath,
127
+ (id, notes) => buildReferenceContent(ref, id, notes)
128
+ );
129
+ return result === "created";
130
+ }
131
+ async function generateConnectionMetadata(flintPath, declaration) {
132
+ const filePath = getConnectionMetadataPath(flintPath, declaration.name);
133
+ await mkdir(getConnectionsMetadataDir(flintPath), { recursive: true });
134
+ const result = await syncMetadataFile(
135
+ filePath,
136
+ (id, notes) => buildConnectionContent(declaration, id, notes)
137
+ );
138
+ return result === "created";
139
+ }
140
+ async function generateSourceMetadata(flintPath, importRef) {
141
+ const filePath = getSourceMetadataPath(flintPath, importRef);
142
+ await mkdir(getSourcesMetadataDir(flintPath), { recursive: true });
143
+ const result = await syncMetadataFile(
144
+ filePath,
145
+ (id, notes) => buildSourceContent(importRef, id, notes)
146
+ );
147
+ return result === "created";
148
+ }
149
+ async function resolveCodebase(flintPath, name) {
150
+ const { readReferencesState } = await import("./workspace-local-LKB4MTN2-OY5UVN3K.js");
151
+ const state = await readReferencesState(flintPath);
152
+ const normalizedName = name.toLowerCase();
153
+ const fulfillment = state.references.find(
154
+ (r) => r.name.toLowerCase() === normalizedName
155
+ );
156
+ if (fulfillment?.path) {
157
+ return { status: "fulfilled", name, type: "codebase", path: fulfillment.path };
158
+ }
159
+ return { status: "unfulfilled", name, type: "codebase" };
160
+ }
161
+ async function resolveConnection(flintPath, name) {
162
+ const { readConnectionsState } = await import("./connections-AXGFYQOK-A6BXCAC7.js");
163
+ const state = await readConnectionsState(flintPath);
164
+ const normalizedName = name.toLowerCase();
165
+ const fulfillment = state.connections.find(
166
+ (c) => c.name.toLowerCase() === normalizedName
167
+ );
168
+ if (fulfillment?.path) {
169
+ return { status: "fulfilled", name, type: "connection", path: fulfillment.path };
170
+ }
171
+ return { status: "unfulfilled", name, type: "connection" };
172
+ }
173
+ async function resolveSource(flintPath, importRef) {
174
+ const parts = importRef.split("/");
175
+ const flintName = parts[0] || importRef;
176
+ const exportName = parts[1] || "";
177
+ const sourcePath = join2(flintPath, "Sources", "Flints", `(Flint) ${flintName}`, `(Mesh) ${exportName}`);
178
+ try {
179
+ await stat2(sourcePath);
180
+ return { status: "fulfilled", name: importRef, type: "source", path: sourcePath };
181
+ } catch {
182
+ return { status: "unfulfilled", name: importRef, type: "source", path: sourcePath };
183
+ }
184
+ }
185
+ async function listMetadataFiles(dirPath, prefix) {
186
+ try {
187
+ const entries = await readdir(dirPath);
188
+ return entries.filter((e) => e.startsWith(prefix) && e.endsWith(".md"));
189
+ } catch {
190
+ return [];
191
+ }
192
+ }
193
+ async function syncMetadata(flintPath) {
194
+ const result = { created: [], removed: [], unchanged: [] };
195
+ const config = await readFlintToml(flintPath);
196
+ if (!config) return result;
197
+ const references = config.workspace?.references || [];
198
+ const expectedRefFiles = new Set(
199
+ references.map((r) => `rf-${toKebabCase(r.name)}.md`)
200
+ );
201
+ for (const ref of references) {
202
+ const created = await generateReferenceMetadata(flintPath, ref);
203
+ const fileName = `rf-${toKebabCase(ref.name)}.md`;
204
+ if (created) {
205
+ result.created.push(fileName);
206
+ } else {
207
+ result.unchanged.push(fileName);
208
+ }
209
+ }
210
+ const existingRefFiles = await listMetadataFiles(
211
+ getReferencesMetadataDir(flintPath),
212
+ "rf-"
213
+ );
214
+ for (const file of existingRefFiles) {
215
+ if (!expectedRefFiles.has(file)) {
216
+ try {
217
+ await rm(join2(getReferencesMetadataDir(flintPath), file));
218
+ result.removed.push(file);
219
+ } catch {
220
+ }
221
+ }
222
+ }
223
+ const connections = config.connections?.flints || [];
224
+ const expectedConFiles = new Set(
225
+ connections.map((c) => `con-${toKebabCase(c.name)}.md`)
226
+ );
227
+ for (const con of connections) {
228
+ const created = await generateConnectionMetadata(flintPath, con);
229
+ const fileName = `con-${toKebabCase(con.name)}.md`;
230
+ if (created) {
231
+ result.created.push(fileName);
232
+ } else {
233
+ result.unchanged.push(fileName);
234
+ }
235
+ }
236
+ const existingConFiles = await listMetadataFiles(
237
+ getConnectionsMetadataDir(flintPath),
238
+ "con-"
239
+ );
240
+ for (const file of existingConFiles) {
241
+ if (!expectedConFiles.has(file)) {
242
+ try {
243
+ await rm(join2(getConnectionsMetadataDir(flintPath), file));
244
+ result.removed.push(file);
245
+ } catch {
246
+ }
247
+ }
248
+ }
249
+ const imports = config.imports?.flints || config.imports?.required || [];
250
+ const expectedSrcFiles = new Set(
251
+ imports.map((ref) => `src-${toKebabCase(ref.replace("/", "-"))}.md`)
252
+ );
253
+ for (const importRef of imports) {
254
+ const created = await generateSourceMetadata(flintPath, importRef);
255
+ const fileName = `src-${toKebabCase(importRef.replace("/", "-"))}.md`;
256
+ if (created) {
257
+ result.created.push(fileName);
258
+ } else {
259
+ result.unchanged.push(fileName);
260
+ }
261
+ }
262
+ const existingSrcFiles = await listMetadataFiles(
263
+ getSourcesMetadataDir(flintPath),
264
+ "src-"
265
+ );
266
+ for (const file of existingSrcFiles) {
267
+ if (!expectedSrcFiles.has(file)) {
268
+ try {
269
+ await rm(join2(getSourcesMetadataDir(flintPath), file));
270
+ result.removed.push(file);
271
+ } catch {
272
+ }
273
+ }
274
+ }
275
+ return result;
276
+ }
277
+ async function ensureMetadataDirs(flintPath) {
278
+ await mkdir(getReferencesMetadataDir(flintPath), { recursive: true });
279
+ await mkdir(getConnectionsMetadataDir(flintPath), { recursive: true });
280
+ await mkdir(getSourcesMetadataDir(flintPath), { recursive: true });
281
+ }
282
+
283
+ export {
284
+ getFlintConfigDir,
285
+ getTypePrefix,
286
+ getReferencesMetadataDir,
287
+ getConnectionsMetadataDir,
288
+ getReferenceMetadataPath,
289
+ getConnectionMetadataPath,
290
+ generateReferenceMetadata,
291
+ generateConnectionMetadata,
292
+ resolveCodebase,
293
+ resolveConnection,
294
+ resolveSource,
295
+ syncMetadata,
296
+ ensureMetadataDirs
297
+ };