@nuucognition/flint-cli 0.5.5 → 0.5.6-dev.1

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
@@ -1,5 +1,7 @@
1
1
  import {
2
2
  LiveSessionManager,
3
+ OBSIDIAN_REPO_URL,
4
+ OBSIDIAN_WINDOWS_REPO_URL,
3
5
  STANDARD_DIRECTORIES,
4
6
  TranscriptWatcher,
5
7
  addCodebaseReference,
@@ -121,7 +123,7 @@ import {
121
123
  updateSession,
122
124
  updateShards,
123
125
  updateSourceRepository
124
- } from "./chunk-XWUP7WHQ.js";
126
+ } from "./chunk-WMXC6KO6.js";
125
127
  import {
126
128
  cleanRegistryFile,
127
129
  findFlintByName,
@@ -132,7 +134,7 @@ import {
132
134
  registerFlintByPath,
133
135
  unregisterFlint,
134
136
  upsertFlintEntry
135
- } from "./chunk-C66KJDI7.js";
137
+ } from "./chunk-X6OG5PEE.js";
136
138
  import "./chunk-V7YA5RXL.js";
137
139
  import {
138
140
  generateSourceMeshExportMetadata,
@@ -148,7 +150,7 @@ import {
148
150
  resolveDocument,
149
151
  scanExportEligible,
150
152
  scanExports
151
- } from "./chunk-VAJMJ47E.js";
153
+ } from "./chunk-6MPRSFXI.js";
152
154
  import {
153
155
  addExportToConfig,
154
156
  addLatticeDeclaration,
@@ -170,6 +172,7 @@ import {
170
172
  hasFlintJson,
171
173
  hasFlintToml,
172
174
  isLocalShard,
175
+ parse,
173
176
  readFlintJson,
174
177
  readFlintToml,
175
178
  readLatticesState,
@@ -184,14 +187,227 @@ import {
184
187
  writeFlintJson,
185
188
  writeFlintToml
186
189
  } from "./chunk-CBGQBE6C.js";
190
+ import {
191
+ __commonJS,
192
+ __toESM
193
+ } from "./chunk-JSBRDJBE.js";
194
+
195
+ // ../../node_modules/.pnpm/balanced-match@1.0.2/node_modules/balanced-match/index.js
196
+ var require_balanced_match = __commonJS({
197
+ "../../node_modules/.pnpm/balanced-match@1.0.2/node_modules/balanced-match/index.js"(exports, module) {
198
+ "use strict";
199
+ module.exports = balanced;
200
+ function balanced(a, b, str) {
201
+ if (a instanceof RegExp) a = maybeMatch(a, str);
202
+ if (b instanceof RegExp) b = maybeMatch(b, str);
203
+ var r = range(a, b, str);
204
+ return r && {
205
+ start: r[0],
206
+ end: r[1],
207
+ pre: str.slice(0, r[0]),
208
+ body: str.slice(r[0] + a.length, r[1]),
209
+ post: str.slice(r[1] + b.length)
210
+ };
211
+ }
212
+ function maybeMatch(reg, str) {
213
+ var m = str.match(reg);
214
+ return m ? m[0] : null;
215
+ }
216
+ balanced.range = range;
217
+ function range(a, b, str) {
218
+ var begs, beg, left, right, result;
219
+ var ai = str.indexOf(a);
220
+ var bi = str.indexOf(b, ai + 1);
221
+ var i = ai;
222
+ if (ai >= 0 && bi > 0) {
223
+ if (a === b) {
224
+ return [ai, bi];
225
+ }
226
+ begs = [];
227
+ left = str.length;
228
+ while (i >= 0 && !result) {
229
+ if (i == ai) {
230
+ begs.push(i);
231
+ ai = str.indexOf(a, i + 1);
232
+ } else if (begs.length == 1) {
233
+ result = [begs.pop(), bi];
234
+ } else {
235
+ beg = begs.pop();
236
+ if (beg < left) {
237
+ left = beg;
238
+ right = bi;
239
+ }
240
+ bi = str.indexOf(b, i + 1);
241
+ }
242
+ i = ai < bi && ai >= 0 ? ai : bi;
243
+ }
244
+ if (begs.length) {
245
+ result = [left, right];
246
+ }
247
+ }
248
+ return result;
249
+ }
250
+ }
251
+ });
252
+
253
+ // ../../node_modules/.pnpm/brace-expansion@2.0.2/node_modules/brace-expansion/index.js
254
+ var require_brace_expansion = __commonJS({
255
+ "../../node_modules/.pnpm/brace-expansion@2.0.2/node_modules/brace-expansion/index.js"(exports, module) {
256
+ "use strict";
257
+ var balanced = require_balanced_match();
258
+ module.exports = expandTop;
259
+ var escSlash = "\0SLASH" + Math.random() + "\0";
260
+ var escOpen = "\0OPEN" + Math.random() + "\0";
261
+ var escClose = "\0CLOSE" + Math.random() + "\0";
262
+ var escComma = "\0COMMA" + Math.random() + "\0";
263
+ var escPeriod = "\0PERIOD" + Math.random() + "\0";
264
+ function numeric(str) {
265
+ return parseInt(str, 10) == str ? parseInt(str, 10) : str.charCodeAt(0);
266
+ }
267
+ function escapeBraces(str) {
268
+ return str.split("\\\\").join(escSlash).split("\\{").join(escOpen).split("\\}").join(escClose).split("\\,").join(escComma).split("\\.").join(escPeriod);
269
+ }
270
+ function unescapeBraces(str) {
271
+ return str.split(escSlash).join("\\").split(escOpen).join("{").split(escClose).join("}").split(escComma).join(",").split(escPeriod).join(".");
272
+ }
273
+ function parseCommaParts(str) {
274
+ if (!str)
275
+ return [""];
276
+ var parts = [];
277
+ var m = balanced("{", "}", str);
278
+ if (!m)
279
+ return str.split(",");
280
+ var pre = m.pre;
281
+ var body = m.body;
282
+ var post = m.post;
283
+ var p = pre.split(",");
284
+ p[p.length - 1] += "{" + body + "}";
285
+ var postParts = parseCommaParts(post);
286
+ if (post.length) {
287
+ p[p.length - 1] += postParts.shift();
288
+ p.push.apply(p, postParts);
289
+ }
290
+ parts.push.apply(parts, p);
291
+ return parts;
292
+ }
293
+ function expandTop(str) {
294
+ if (!str)
295
+ return [];
296
+ if (str.substr(0, 2) === "{}") {
297
+ str = "\\{\\}" + str.substr(2);
298
+ }
299
+ return expand2(escapeBraces(str), true).map(unescapeBraces);
300
+ }
301
+ function embrace(str) {
302
+ return "{" + str + "}";
303
+ }
304
+ function isPadded(el) {
305
+ return /^-?0\d/.test(el);
306
+ }
307
+ function lte(i, y) {
308
+ return i <= y;
309
+ }
310
+ function gte(i, y) {
311
+ return i >= y;
312
+ }
313
+ function expand2(str, isTop) {
314
+ var expansions = [];
315
+ var m = balanced("{", "}", str);
316
+ if (!m) return [str];
317
+ var pre = m.pre;
318
+ var post = m.post.length ? expand2(m.post, false) : [""];
319
+ if (/\$$/.test(m.pre)) {
320
+ for (var k = 0; k < post.length; k++) {
321
+ var expansion = pre + "{" + m.body + "}" + post[k];
322
+ expansions.push(expansion);
323
+ }
324
+ } else {
325
+ var isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body);
326
+ var isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body);
327
+ var isSequence = isNumericSequence || isAlphaSequence;
328
+ var isOptions = m.body.indexOf(",") >= 0;
329
+ if (!isSequence && !isOptions) {
330
+ if (m.post.match(/,(?!,).*\}/)) {
331
+ str = m.pre + "{" + m.body + escClose + m.post;
332
+ return expand2(str);
333
+ }
334
+ return [str];
335
+ }
336
+ var n;
337
+ if (isSequence) {
338
+ n = m.body.split(/\.\./);
339
+ } else {
340
+ n = parseCommaParts(m.body);
341
+ if (n.length === 1) {
342
+ n = expand2(n[0], false).map(embrace);
343
+ if (n.length === 1) {
344
+ return post.map(function(p) {
345
+ return m.pre + n[0] + p;
346
+ });
347
+ }
348
+ }
349
+ }
350
+ var N;
351
+ if (isSequence) {
352
+ var x = numeric(n[0]);
353
+ var y = numeric(n[1]);
354
+ var width = Math.max(n[0].length, n[1].length);
355
+ var incr = n.length == 3 ? Math.abs(numeric(n[2])) : 1;
356
+ var test = lte;
357
+ var reverse = y < x;
358
+ if (reverse) {
359
+ incr *= -1;
360
+ test = gte;
361
+ }
362
+ var pad3 = n.some(isPadded);
363
+ N = [];
364
+ for (var i = x; test(i, y); i += incr) {
365
+ var c;
366
+ if (isAlphaSequence) {
367
+ c = String.fromCharCode(i);
368
+ if (c === "\\")
369
+ c = "";
370
+ } else {
371
+ c = String(i);
372
+ if (pad3) {
373
+ var need = width - c.length;
374
+ if (need > 0) {
375
+ var z = new Array(need + 1).join("0");
376
+ if (i < 0)
377
+ c = "-" + z + c.slice(1);
378
+ else
379
+ c = z + c;
380
+ }
381
+ }
382
+ }
383
+ N.push(c);
384
+ }
385
+ } else {
386
+ N = [];
387
+ for (var j = 0; j < n.length; j++) {
388
+ N.push.apply(N, expand2(n[j], false));
389
+ }
390
+ }
391
+ for (var j = 0; j < N.length; j++) {
392
+ for (var k = 0; k < post.length; k++) {
393
+ var expansion = pre + N[j] + post[k];
394
+ if (!isTop || isSequence || expansion)
395
+ expansions.push(expansion);
396
+ }
397
+ }
398
+ }
399
+ return expansions;
400
+ }
401
+ }
402
+ });
187
403
 
188
404
  // src/index.ts
189
- import { Command as Command37 } from "commander";
405
+ import { Command as Command38 } from "commander";
190
406
  import { readFileSync as readFileSync11, existsSync as existsSync15, cpSync, mkdirSync as mkdirSync5, readdirSync as readdirSync8 } from "fs";
191
407
  import { fileURLToPath as fileURLToPath4 } from "url";
192
- import { dirname as dirname4, join as join19 } from "path";
408
+ import { dirname as dirname4, join as join20 } from "path";
193
409
  import { homedir as homedir11 } from "os";
194
- import pc42 from "picocolors";
410
+ import pc43 from "picocolors";
195
411
 
196
412
  // ../../../main/packages/cli-core/dist/index.js
197
413
  import { homedir } from "os";
@@ -275,7 +491,7 @@ function skipVoid(str, ptr, banNewLines, banComments) {
275
491
  ptr++;
276
492
  return banComments || c !== "#" ? ptr : skipVoid(str, skipComment(str, ptr), banNewLines);
277
493
  }
278
- function skipUntil(str, ptr, sep, end, banNewLines = false) {
494
+ function skipUntil(str, ptr, sep2, end, banNewLines = false) {
279
495
  if (!end) {
280
496
  ptr = indexOfNewline(str, ptr);
281
497
  return ptr < 0 ? str.length : ptr;
@@ -284,7 +500,7 @@ function skipUntil(str, ptr, sep, end, banNewLines = false) {
284
500
  let c = str[i];
285
501
  if (c === "#") {
286
502
  i = indexOfNewline(str, i);
287
- } else if (c === sep) {
503
+ } else if (c === sep2) {
288
504
  return i + 1;
289
505
  } else if (c === end || banNewLines && (c === "\n" || c === "\r" && str[i + 1] === "\n")) {
290
506
  return i;
@@ -325,18 +541,18 @@ var TomlDate = class _TomlDate extends Date {
325
541
  let hasTime = true;
326
542
  let offset = "Z";
327
543
  if (typeof date === "string") {
328
- let match = date.match(DATE_TIME_RE);
329
- if (match) {
330
- if (!match[1]) {
544
+ let match2 = date.match(DATE_TIME_RE);
545
+ if (match2) {
546
+ if (!match2[1]) {
331
547
  hasDate = false;
332
548
  date = `0000-01-01T${date}`;
333
549
  }
334
- hasTime = !!match[2];
550
+ hasTime = !!match2[2];
335
551
  hasTime && date[10] === " " && (date = date.replace(" ", "T"));
336
- if (match[2] && +match[2] > 23) {
552
+ if (match2[2] && +match2[2] > 23) {
337
553
  date = "";
338
554
  } else {
339
- offset = match[3] || null;
555
+ offset = match2[3] || null;
340
556
  date = date.toUpperCase();
341
557
  if (!offset && hasTime)
342
558
  date += "Z";
@@ -820,7 +1036,7 @@ function peekTable(key, table, meta, type) {
820
1036
  }
821
1037
  return [k, t, state.c];
822
1038
  }
823
- function parse(toml, { maxDepth = 1e3, integersAsBigInt } = {}) {
1039
+ function parse2(toml, { maxDepth = 1e3, integersAsBigInt } = {}) {
824
1040
  let res = {};
825
1041
  let meta = {};
826
1042
  let tbl = res;
@@ -1189,8 +1405,8 @@ async function defaultBrowserId() {
1189
1405
  throw new Error("macOS only");
1190
1406
  }
1191
1407
  const { stdout } = await execFileAsync("defaults", ["read", "com.apple.LaunchServices/com.apple.launchservices.secure", "LSHandlers"]);
1192
- const match = /LSHandlerRoleAll = "(?!-)(?<id>[^"]+?)";\s+?LSHandlerURLScheme = (?:http|https);/.exec(stdout);
1193
- const browserId = match?.groups.id ?? "com.apple.Safari";
1408
+ const match2 = /LSHandlerRoleAll = "(?!-)(?<id>[^"]+?)";\s+?LSHandlerURLScheme = (?:http|https);/.exec(stdout);
1409
+ const browserId = match2?.groups.id ?? "com.apple.Safari";
1194
1410
  if (browserId === "com.apple.safari") {
1195
1411
  return "com.apple.Safari";
1196
1412
  }
@@ -1254,11 +1470,11 @@ async function defaultBrowser(_execFileAsync = execFileAsync3) {
1254
1470
  "/v",
1255
1471
  "ProgId"
1256
1472
  ]);
1257
- const match = /ProgId\s*REG_SZ\s*(?<id>\S+)/.exec(stdout);
1258
- if (!match) {
1473
+ const match2 = /ProgId\s*REG_SZ\s*(?<id>\S+)/.exec(stdout);
1474
+ if (!match2) {
1259
1475
  throw new UnknownBrowserError(`Cannot find Windows browser in stdout: ${JSON.stringify(stdout)}`);
1260
1476
  }
1261
- const { id } = match.groups;
1477
+ const { id } = match2.groups;
1262
1478
  const browser = windowsBrowserProgIds[id];
1263
1479
  if (!browser) {
1264
1480
  throw new UnknownBrowserError(`Unknown browser ID: ${id}`);
@@ -1566,10 +1782,10 @@ function normalizeRuntimeMode(input) {
1566
1782
  function authEnvForMode(mode) {
1567
1783
  return mode === "dev" ? "dev" : "prod";
1568
1784
  }
1569
- async function readConfigFile(path8) {
1785
+ async function readConfigFile(path10) {
1570
1786
  try {
1571
- const content = await fsReadFile(path8, "utf-8");
1572
- return parse(content);
1787
+ const content = await fsReadFile(path10, "utf-8");
1788
+ return parse2(content);
1573
1789
  } catch (error22) {
1574
1790
  if (error22.code === "ENOENT") {
1575
1791
  return null;
@@ -1577,10 +1793,10 @@ async function readConfigFile(path8) {
1577
1793
  throw error22;
1578
1794
  }
1579
1795
  }
1580
- function readConfigFileSync(path8) {
1796
+ function readConfigFileSync(path10) {
1581
1797
  try {
1582
- const content = fsReadFileSync(path8, "utf-8");
1583
- return parse(content);
1798
+ const content = fsReadFileSync(path10, "utf-8");
1799
+ return parse2(content);
1584
1800
  } catch (error22) {
1585
1801
  if (error22.code === "ENOENT") {
1586
1802
  return null;
@@ -1588,25 +1804,25 @@ function readConfigFileSync(path8) {
1588
1804
  throw error22;
1589
1805
  }
1590
1806
  }
1591
- async function writeConfigFile(path8, data) {
1592
- await mkdir(dirname(path8), { recursive: true });
1593
- await fsWriteFile(path8, `${stringify(data)}
1807
+ async function writeConfigFile(path10, data) {
1808
+ await mkdir(dirname(path10), { recursive: true });
1809
+ await fsWriteFile(path10, `${stringify(data)}
1594
1810
  `, "utf-8");
1595
1811
  }
1596
- async function setConfigField(path8, key, value) {
1597
- const existing = await readConfigFile(path8) ?? {};
1812
+ async function setConfigField(path10, key, value) {
1813
+ const existing = await readConfigFile(path10) ?? {};
1598
1814
  existing[key] = value;
1599
- await writeConfigFile(path8, existing);
1815
+ await writeConfigFile(path10, existing);
1600
1816
  }
1601
- async function setFeatureOverride(path8, featureId, enabled) {
1602
- const existing = await readConfigFile(path8) ?? {};
1817
+ async function setFeatureOverride(path10, featureId, enabled) {
1818
+ const existing = await readConfigFile(path10) ?? {};
1603
1819
  const features = existing.features && typeof existing.features === "object" && !Array.isArray(existing.features) ? { ...existing.features } : {};
1604
1820
  features[featureId] = enabled;
1605
1821
  existing.features = features;
1606
- await writeConfigFile(path8, existing);
1822
+ await writeConfigFile(path10, existing);
1607
1823
  }
1608
- async function removeFeatureOverride(path8, featureId) {
1609
- const existing = await readConfigFile(path8);
1824
+ async function removeFeatureOverride(path10, featureId) {
1825
+ const existing = await readConfigFile(path10);
1610
1826
  if (!existing) return;
1611
1827
  const features = existing.features;
1612
1828
  if (!features || typeof features !== "object" || Array.isArray(features)) {
@@ -1619,7 +1835,7 @@ async function removeFeatureOverride(path8, featureId) {
1619
1835
  } else {
1620
1836
  existing.features = next;
1621
1837
  }
1622
- await writeConfigFile(path8, existing);
1838
+ await writeConfigFile(path10, existing);
1623
1839
  }
1624
1840
  var CONFIG_FILENAME = "config.toml";
1625
1841
  function getConfigDir(cliname) {
@@ -1628,10 +1844,10 @@ function getConfigDir(cliname) {
1628
1844
  function getConfigPath(cliname) {
1629
1845
  return join(getConfigDir(cliname), CONFIG_FILENAME);
1630
1846
  }
1631
- function mergeDefaults(config, defaults) {
1632
- if (!defaults) return config;
1847
+ function mergeDefaults(config, defaults2) {
1848
+ if (!defaults2) return config;
1633
1849
  return {
1634
- ...defaults,
1850
+ ...defaults2,
1635
1851
  ...config
1636
1852
  };
1637
1853
  }
@@ -1828,9 +2044,9 @@ async function loadAuth(env = "prod") {
1828
2044
  function loadAuthSync(env = "prod") {
1829
2045
  try {
1830
2046
  ensureNuuDirSync();
1831
- const path8 = authPath(env);
1832
- if (!existsSync(path8)) return null;
1833
- return normalizeCredentials(JSON.parse(readFileSync(path8, "utf-8")));
2047
+ const path10 = authPath(env);
2048
+ if (!existsSync(path10)) return null;
2049
+ return normalizeCredentials(JSON.parse(readFileSync(path10, "utf-8")));
1834
2050
  } catch {
1835
2051
  return null;
1836
2052
  }
@@ -2319,6 +2535,7 @@ var FEATURES = createFeatureRegistry([
2319
2535
  { id: "code", tier: "prod", type: "command", description: "Launch AI coding agents", requiresAuth: false },
2320
2536
  { id: "orb", tier: "prod", type: "command", description: "Orbh meta-harness agent management", requiresAuth: false },
2321
2537
  { id: "server", tier: "prod", type: "command", description: "Flint runtime server", requiresAuth: false },
2538
+ { id: "steel", tier: "prod", type: "command", description: "Manage Steel UI state", requiresAuth: false },
2322
2539
  { id: "runtime", tier: "dev", type: "command", description: "Flint runtime management", requiresAuth: false },
2323
2540
  { id: "obsidian.push", tier: "dev", type: "function", description: "Push obsidian config changes to remote", requiresAuth: false },
2324
2541
  { id: "agent.start", tier: "dev", type: "function", description: "Start AI agent session", requiresAuth: false }
@@ -2395,25 +2612,25 @@ function createProgressDisplay(label, total) {
2395
2612
  import { homedir as homedir3 } from "os";
2396
2613
  import { access } from "fs/promises";
2397
2614
  import { createInterface } from "readline";
2398
- function abbreviatePath(path8) {
2615
+ function abbreviatePath(path10) {
2399
2616
  const home = homedir3();
2400
- if (path8.startsWith(home)) {
2401
- return path8.replace(home, "~");
2617
+ if (path10.startsWith(home)) {
2618
+ return path10.replace(home, "~");
2402
2619
  }
2403
- return path8;
2620
+ return path10;
2404
2621
  }
2405
- function expandPath(path8) {
2406
- if (path8.startsWith("~/")) {
2407
- return path8.replace("~", homedir3());
2622
+ function expandPath(path10) {
2623
+ if (path10.startsWith("~/")) {
2624
+ return path10.replace("~", homedir3());
2408
2625
  }
2409
- return path8;
2626
+ return path10;
2410
2627
  }
2411
2628
  function padEnd(str, length) {
2412
2629
  return str.padEnd(length);
2413
2630
  }
2414
- async function checkPathExists(path8) {
2631
+ async function checkPathExists(path10) {
2415
2632
  try {
2416
- await access(path8);
2633
+ await access(path10);
2417
2634
  return true;
2418
2635
  } catch {
2419
2636
  return false;
@@ -2664,12 +2881,12 @@ function resolvePath(flint, fullPath) {
2664
2881
  }
2665
2882
  function printFlint(flint, opts) {
2666
2883
  const { nameColWidth, showStatus, fullPath, indent = " " } = opts;
2667
- const path8 = resolvePath(flint, fullPath);
2884
+ const path10 = resolvePath(flint, fullPath);
2668
2885
  const isBroken = showStatus && !flint.valid;
2669
2886
  const tags = formatTags(flint.tags);
2670
2887
  const nameCell = tags ? `${pc7.bold(flint.name)} ${tags}` : pc7.bold(flint.name);
2671
2888
  const status = showStatus ? statusBadge(flint) + " " : "";
2672
- const pathColor = isBroken ? pc7.red(path8) : pc7.dim(path8);
2889
+ const pathColor = isBroken ? pc7.red(path10) : pc7.dim(path10);
2673
2890
  console.log(`${indent}${pad(nameCell, nameColWidth)}${status}${pathColor}`);
2674
2891
  if (flint.description) {
2675
2892
  console.log(`${indent} ${pc7.dim(truncate(flint.description, 65))}`);
@@ -2677,10 +2894,10 @@ function printFlint(flint, opts) {
2677
2894
  }
2678
2895
  function printGroupRow(flint, opts) {
2679
2896
  const { nameColWidth, showStatus, fullPath } = opts;
2680
- const path8 = resolvePath(flint, fullPath);
2897
+ const path10 = resolvePath(flint, fullPath);
2681
2898
  const isBroken = showStatus && !flint.valid;
2682
2899
  const status = showStatus ? statusBadge(flint) + " " : "";
2683
- const pathColor = isBroken ? pc7.red(path8) : pc7.dim(path8);
2900
+ const pathColor = isBroken ? pc7.red(path10) : pc7.dim(path10);
2684
2901
  console.log(` ${pad(flint.name, nameColWidth)}${status}${pathColor}`);
2685
2902
  }
2686
2903
  function measureNameCol(flints) {
@@ -3208,9 +3425,9 @@ Uninstalled ${pc8.bold(result.name)}`));
3208
3425
  if (!existsSync3(gitDir)) continue;
3209
3426
  try {
3210
3427
  const url = execSync6("git remote get-url origin", { cwd: shardPath, encoding: "utf-8" }).trim();
3211
- const match = url.match(/(?:github\.com[/:])([\w.-]+\/[\w.-]+?)(?:\.git)?$/);
3212
- if (match) {
3213
- gitRemotes.set(shard.name, match[1]);
3428
+ const match2 = url.match(/(?:github\.com[/:])([\w.-]+\/[\w.-]+?)(?:\.git)?$/);
3429
+ if (match2) {
3430
+ gitRemotes.set(shard.name, match2[1]);
3214
3431
  }
3215
3432
  } catch {
3216
3433
  }
@@ -3421,8 +3638,8 @@ Cloned ${pc8.bold(result.name)} for development`));
3421
3638
  try {
3422
3639
  const flintPath = await resolveFlint(options.path);
3423
3640
  const installed = await getInstalledShardsWithVersions(flintPath);
3424
- const match = resolveInstalledShardInfo(installed, name);
3425
- if (!match) {
3641
+ const match2 = resolveInstalledShardInfo(installed, name);
3642
+ if (!match2) {
3426
3643
  console.error(pc8.red(`
3427
3644
  Shard "${name}" not found.`));
3428
3645
  console.log(pc8.dim(` Run ${pc8.cyan("flint shard list")} to see installed shards.`));
@@ -3430,11 +3647,11 @@ Shard "${name}" not found.`));
3430
3647
  return;
3431
3648
  }
3432
3649
  const declarations = await getShardDeclarations(flintPath);
3433
- const decl = declarations[match.name];
3650
+ const decl = declarations[match2.name];
3434
3651
  const source = decl?.source || "";
3435
3652
  console.log(pc8.dim(`
3436
- Transitioning ${match.folderName} to dev mode...`));
3437
- const result = await editShard(flintPath, match.folderName, source);
3653
+ Transitioning ${match2.folderName} to dev mode...`));
3654
+ const result = await editShard(flintPath, match2.folderName, source);
3438
3655
  await updateGitignore(flintPath);
3439
3656
  console.log(pc8.green(`
3440
3657
  ${pc8.bold(result.name)} is now in dev mode`));
@@ -3451,8 +3668,8 @@ ${pc8.bold(result.name)} is now in dev mode`));
3451
3668
  try {
3452
3669
  const flintPath = await resolveFlint(options.path);
3453
3670
  const installed = await getInstalledShardsWithVersions(flintPath);
3454
- const match = resolveInstalledShardInfo(installed, name);
3455
- if (!match) {
3671
+ const match2 = resolveInstalledShardInfo(installed, name);
3672
+ if (!match2) {
3456
3673
  console.error(pc8.red(`
3457
3674
  Shard "${name}" not found.`));
3458
3675
  console.log(pc8.dim(` Run ${pc8.cyan("flint shard list")} to see installed shards.`));
@@ -3460,8 +3677,8 @@ Shard "${name}" not found.`));
3460
3677
  return;
3461
3678
  }
3462
3679
  console.log(pc8.dim(`
3463
- Freezing ${match.folderName}...`));
3464
- const result = await freezeShard(flintPath, match.folderName);
3680
+ Freezing ${match2.folderName}...`));
3681
+ const result = await freezeShard(flintPath, match2.folderName);
3465
3682
  await updateGitignore(flintPath);
3466
3683
  console.log(pc8.green(`
3467
3684
  ${pc8.bold(result.name)} is now a normal shard`));
@@ -3478,17 +3695,17 @@ ${pc8.bold(result.name)} is now a normal shard`));
3478
3695
  try {
3479
3696
  const flintPath = await resolveFlint(options.path);
3480
3697
  const installed = await getInstalledShardsWithVersions(flintPath);
3481
- const match = resolveInstalledShardInfo(installed, name);
3482
- if (!match) {
3698
+ const match2 = resolveInstalledShardInfo(installed, name);
3699
+ if (!match2) {
3483
3700
  console.error(pc8.red(`
3484
3701
  Shard "${name}" not found.`));
3485
3702
  console.log(pc8.dim(` Run ${pc8.cyan("flint shard list")} to see installed shards.`));
3486
3703
  console.log();
3487
3704
  return;
3488
3705
  }
3489
- const result = await addShardGitRemote(flintPath, match.folderName, url);
3706
+ const result = await addShardGitRemote(flintPath, match2.folderName, url);
3490
3707
  console.log(pc8.green(`
3491
- Remote added to ${pc8.bold(match.folderName)}`));
3708
+ Remote added to ${pc8.bold(match2.folderName)}`));
3492
3709
  console.log(pc8.dim(` Remote: origin \u2192 ${url}`));
3493
3710
  console.log(pc8.dim(` Source: ${result.ownerRepo}`));
3494
3711
  console.log();
@@ -3614,15 +3831,15 @@ Shard not found: "${identifier}"`));
3614
3831
  const installed = await getInstalledShardsWithVersions(flintPath);
3615
3832
  const targets = [];
3616
3833
  if (name) {
3617
- const match = resolveInstalledShardInfo(installed, name);
3618
- if (!match) {
3834
+ const match2 = resolveInstalledShardInfo(installed, name);
3835
+ if (!match2) {
3619
3836
  console.error(pc8.red(`
3620
3837
  Shard "${name}" not found.`));
3621
3838
  console.log(pc8.dim(` Run ${pc8.cyan("flint shard list")} to see installed shards.`));
3622
3839
  console.log();
3623
3840
  return;
3624
3841
  }
3625
- targets.push(match);
3842
+ targets.push(match2);
3626
3843
  } else {
3627
3844
  for (const s of installed) {
3628
3845
  targets.push({ folderName: s.folderName });
@@ -3749,8 +3966,8 @@ Reinstalling ${shorthand}...
3749
3966
  const { execSync: execSync6 } = await import("child_process");
3750
3967
  const flintPath = await resolveFlint(options.path);
3751
3968
  const installed = await getInstalledShardsWithVersions(flintPath);
3752
- const match = resolveInstalledShardInfo(installed, name);
3753
- if (!match) {
3969
+ const match2 = resolveInstalledShardInfo(installed, name);
3970
+ if (!match2) {
3754
3971
  console.error(pc8.red(`
3755
3972
  Shard "${name}" not found.`));
3756
3973
  console.log(pc8.dim(` Run ${pc8.cyan("flint shard list")} to see installed shards.`));
@@ -3758,28 +3975,28 @@ Shard "${name}" not found.`));
3758
3975
  return;
3759
3976
  }
3760
3977
  const declarations = await getShardDeclarations(flintPath);
3761
- const declaration = declarations[match.name];
3978
+ const declaration = declarations[match2.name];
3762
3979
  const gitInitMode = declaration ? resolveShardMode(declaration) : void 0;
3763
3980
  if (gitInitMode === "custom") {
3764
3981
  console.error(pc8.red(`
3765
- "${match.folderName}" is a custom shard. Custom shards cannot have git remotes.`));
3982
+ "${match2.folderName}" is a custom shard. Custom shards cannot have git remotes.`));
3766
3983
  console.log();
3767
3984
  return;
3768
3985
  }
3769
3986
  if (gitInitMode !== "dev") {
3770
3987
  console.error(pc8.red(`
3771
- "${match.folderName}" is not a dev shard.`));
3988
+ "${match2.folderName}" is not a dev shard.`));
3772
3989
  console.log();
3773
3990
  return;
3774
3991
  }
3775
- const shardPath = join5(flintPath, "Shards", match.folderName);
3992
+ const shardPath = join5(flintPath, "Shards", match2.folderName);
3776
3993
  const gitDir = join5(shardPath, ".git");
3777
3994
  const hasGit = existsSync3(gitDir);
3778
3995
  if (hasGit) {
3779
3996
  try {
3780
3997
  const existing = execSync6("git remote get-url origin", { cwd: shardPath, stdio: "pipe" }).toString().trim();
3781
3998
  console.error(pc8.red(`
3782
- "${match.folderName}" already has a remote: ${existing}`));
3999
+ "${match2.folderName}" already has a remote: ${existing}`));
3783
4000
  console.log(pc8.dim(` Use ${pc8.cyan("flint shard push")} instead.`));
3784
4001
  console.log();
3785
4002
  return;
@@ -3787,7 +4004,7 @@ Shard "${name}" not found.`));
3787
4004
  }
3788
4005
  }
3789
4006
  console.log(pc8.bold(`
3790
- Initializing ${match.folderName}...
4007
+ Initializing ${match2.folderName}...
3791
4008
  `));
3792
4009
  if (!hasGit) {
3793
4010
  execSync6("git init", { cwd: shardPath, stdio: "pipe" });
@@ -3798,7 +4015,7 @@ Initializing ${match.folderName}...
3798
4015
  execSync6('git commit -m "initial commit"', { cwd: shardPath, stdio: "pipe" });
3799
4016
  execSync6("git push -u origin main", { cwd: shardPath, stdio: "inherit" });
3800
4017
  console.log(pc8.green(`
3801
- ${pc8.bold(match.folderName)} pushed to ${pc8.dim(url)}`));
4018
+ ${pc8.bold(match2.folderName)} pushed to ${pc8.dim(url)}`));
3802
4019
  console.log();
3803
4020
  } catch (err) {
3804
4021
  handleError(err);
@@ -3810,8 +4027,8 @@ Initializing ${match.folderName}...
3810
4027
  const { execSync: execSync6 } = await import("child_process");
3811
4028
  const flintPath = await resolveFlint(options.path);
3812
4029
  const installed = await getInstalledShardsWithVersions(flintPath);
3813
- const match = resolveInstalledShardInfo(installed, name);
3814
- if (!match) {
4030
+ const match2 = resolveInstalledShardInfo(installed, name);
4031
+ if (!match2) {
3815
4032
  console.error(pc8.red(`
3816
4033
  Shard "${name}" not found.`));
3817
4034
  console.log(pc8.dim(` Run ${pc8.cyan("flint shard list")} to see installed shards.`));
@@ -3819,26 +4036,26 @@ Shard "${name}" not found.`));
3819
4036
  return;
3820
4037
  }
3821
4038
  const declarations = await getShardDeclarations(flintPath);
3822
- const declaration = declarations[match.name];
4039
+ const declaration = declarations[match2.name];
3823
4040
  const shardMode = declaration ? resolveShardMode(declaration) : void 0;
3824
4041
  if (shardMode === "custom") {
3825
4042
  console.error(pc8.red(`
3826
- "${match.folderName}" is a custom shard. Custom shards are workspace-specific and cannot be pushed.`));
4043
+ "${match2.folderName}" is a custom shard. Custom shards are workspace-specific and cannot be pushed.`));
3827
4044
  console.log();
3828
4045
  return;
3829
4046
  }
3830
4047
  if (shardMode !== "dev") {
3831
4048
  console.error(pc8.red(`
3832
- "${match.folderName}" is not a dev shard. Only dev shards can be pushed.`));
4049
+ "${match2.folderName}" is not a dev shard. Only dev shards can be pushed.`));
3833
4050
  console.log();
3834
4051
  return;
3835
4052
  }
3836
- const shardPath = join5(flintPath, "Shards", match.folderName);
4053
+ const shardPath = join5(flintPath, "Shards", match2.folderName);
3837
4054
  const gitDir = join5(shardPath, ".git");
3838
4055
  if (!existsSync3(gitDir)) {
3839
4056
  console.error(pc8.red(`
3840
- "${match.folderName}" has no git repo. Initialize one first:`));
3841
- console.log(pc8.dim(` cd "Shards/${match.folderName}" && git init && git remote add origin <url>`));
4057
+ "${match2.folderName}" has no git repo. Initialize one first:`));
4058
+ console.log(pc8.dim(` cd "Shards/${match2.folderName}" && git init && git remote add origin <url>`));
3842
4059
  console.log();
3843
4060
  return;
3844
4061
  }
@@ -3848,7 +4065,7 @@ Shard "${name}" not found.`));
3848
4065
  const unpushed = execSync6("git log @{u}..HEAD --oneline", { cwd: shardPath, encoding: "utf-8" }).trim();
3849
4066
  if (unpushed) {
3850
4067
  console.log(pc8.bold(`
3851
- Pushing ${match.folderName}...
4068
+ Pushing ${match2.folderName}...
3852
4069
  `));
3853
4070
  execSync6("git push", { cwd: shardPath, stdio: "inherit" });
3854
4071
  console.log(pc8.green(`
@@ -3859,7 +4076,7 @@ Pushing ${match.folderName}...
3859
4076
  } catch {
3860
4077
  }
3861
4078
  console.log(pc8.dim(`
3862
- No changes to push in "${match.folderName}".`));
4079
+ No changes to push in "${match2.folderName}".`));
3863
4080
  console.log();
3864
4081
  return;
3865
4082
  }
@@ -3872,9 +4089,9 @@ Invalid bump level "${level}". Use: patch, minor, or major.`));
3872
4089
  console.log();
3873
4090
  return;
3874
4091
  }
3875
- const { readFile: readFile9, writeFile: writeFile7 } = await import("fs/promises");
4092
+ const { readFile: readFile10, writeFile: writeFile7 } = await import("fs/promises");
3876
4093
  const yamlPath = join5(shardPath, "shard.yaml");
3877
- const yamlContent = await readFile9(yamlPath, "utf-8");
4094
+ const yamlContent = await readFile10(yamlPath, "utf-8");
3878
4095
  const versionMatch = yamlContent.match(/^version:\s*"?(\d+)\.(\d+)\.(\d+)"?/m);
3879
4096
  if (!versionMatch) {
3880
4097
  console.error(pc8.red(`
@@ -3889,10 +4106,10 @@ Could not parse version from shard.yaml.`));
3889
4106
  const updatedYaml = yamlContent.replace(/^version:\s*.+$/m, `version: "${bumpedVersion}"`);
3890
4107
  await writeFile7(yamlPath, updatedYaml, "utf-8");
3891
4108
  }
3892
- const baseMessage = options.message || `update ${match.folderName.replace(/^\(Dev\)\s*/, "")} shard`;
4109
+ const baseMessage = options.message || `update ${match2.folderName.replace(/^\(Dev\)\s*/, "")} shard`;
3893
4110
  const message = bumpedVersion ? `v${bumpedVersion} ${baseMessage}` : baseMessage;
3894
4111
  console.log(pc8.bold(`
3895
- Pushing ${match.folderName}...
4112
+ Pushing ${match2.folderName}...
3896
4113
  `));
3897
4114
  execSync6("git add -A", { cwd: shardPath, stdio: "pipe" });
3898
4115
  execSync6(`git commit -m "${message.replace(/"/g, '\\"')}"`, { cwd: shardPath, stdio: "pipe" });
@@ -3903,7 +4120,7 @@ Pushing ${match.folderName}...
3903
4120
  execSync6(`git push -u origin ${branch}`, { cwd: shardPath, stdio: "inherit" });
3904
4121
  }
3905
4122
  console.log(pc8.green(`
3906
- ${pc8.bold(match.folderName)} pushed.`));
4123
+ ${pc8.bold(match2.folderName)} pushed.`));
3907
4124
  console.log(pc8.dim(` ${message}`));
3908
4125
  console.log();
3909
4126
  } catch (err) {
@@ -3924,15 +4141,15 @@ Pushing ${match.folderName}...
3924
4141
  try {
3925
4142
  const flintPath = await resolveFlint(options.path);
3926
4143
  const installed = await getInstalledShardsWithVersions(flintPath);
3927
- const match = resolveInstalledShardInfo(installed, name);
3928
- if (!match) {
4144
+ const match2 = resolveInstalledShardInfo(installed, name);
4145
+ if (!match2) {
3929
4146
  console.error(pc8.red(`
3930
4147
  Shard "${name}" not found.`));
3931
4148
  console.log(pc8.dim(` Run ${pc8.cyan("flint shard list")} to see installed shards.`));
3932
4149
  console.log();
3933
4150
  process.exit(1);
3934
4151
  }
3935
- const shardPath = join5(flintPath, "Shards", match.folderName);
4152
+ const shardPath = join5(flintPath, "Shards", match2.folderName);
3936
4153
  const detail2 = await getShardInfo(flintPath, name);
3937
4154
  if (!detail2) {
3938
4155
  console.error(pc8.red(`
@@ -3940,7 +4157,7 @@ Cannot read shard info for "${name}".`));
3940
4157
  process.exit(1);
3941
4158
  }
3942
4159
  const declarations = await getShardDeclarations(flintPath);
3943
- const declaration = declarations[match.name];
4160
+ const declaration = declarations[match2.name];
3944
4161
  let repo = "";
3945
4162
  if (declaration?.source) {
3946
4163
  const parsed = parseShardSource(declaration.source);
@@ -4969,11 +5186,12 @@ var REQUIRED_DIRS = [
4969
5186
  "Exports",
4970
5187
  "Workspace",
4971
5188
  "Workspace/Bench",
4972
- ".flint"
5189
+ ".flint",
5190
+ ".steel"
4973
5191
  ];
4974
- async function exists(path8) {
5192
+ async function exists(path10) {
4975
5193
  try {
4976
- await access2(path8);
5194
+ await access2(path10);
4977
5195
  return true;
4978
5196
  } catch {
4979
5197
  return false;
@@ -5198,9 +5416,9 @@ import pc12 from "picocolors";
5198
5416
  import { readFile as readFile4, stat } from "fs/promises";
5199
5417
  import { join as join7, basename as basename2 } from "path";
5200
5418
  import { createInterface as createInterface2 } from "readline";
5201
- async function exists2(path8) {
5419
+ async function exists2(path10) {
5202
5420
  try {
5203
- await stat(path8);
5421
+ await stat(path10);
5204
5422
  return true;
5205
5423
  } catch {
5206
5424
  return false;
@@ -5494,17 +5712,17 @@ import { resolve as resolve2 } from "path";
5494
5712
  import { platform as platform3 } from "os";
5495
5713
  import pc13 from "picocolors";
5496
5714
  var execAsync2 = promisify7(exec2);
5497
- async function openInObsidian(path8) {
5715
+ async function openInObsidian(path10) {
5498
5716
  const os2 = platform3();
5499
5717
  if (os2 === "darwin") {
5500
- await execAsync2(`open -a "Obsidian" "${path8}"`);
5718
+ await execAsync2(`open -a "Obsidian" "${path10}"`);
5501
5719
  } else if (os2 === "win32") {
5502
- await execAsync2(`start "" "Obsidian" "${path8}"`);
5720
+ await execAsync2(`start "" "Obsidian" "${path10}"`);
5503
5721
  } else {
5504
5722
  try {
5505
- await execAsync2(`obsidian "${path8}"`);
5723
+ await execAsync2(`obsidian "${path10}"`);
5506
5724
  } catch {
5507
- await execAsync2(`xdg-open "${path8}"`);
5725
+ await execAsync2(`xdg-open "${path10}"`);
5508
5726
  }
5509
5727
  }
5510
5728
  }
@@ -5636,6 +5854,7 @@ function sendNotification(title, message) {
5636
5854
  const child = spawn('claude', claudeArgs, {
5637
5855
  cwd: flintPath,
5638
5856
  stdio: ['ignore', 'ignore', 'pipe'],
5857
+ shell: process.platform === 'win32',
5639
5858
  });
5640
5859
 
5641
5860
  let stderr = '';
@@ -6445,7 +6664,10 @@ import pc18 from "picocolors";
6445
6664
  import { execSync as execSync2, spawnSync as spawnSync2 } from "child_process";
6446
6665
  import { join as join8 } from "path";
6447
6666
  import { stat as stat2, rm as rm2 } from "fs/promises";
6448
- var OBSIDIAN_REPO_URL = "https://github.com/NUU-Cognition/flint-dot-obsidian.git";
6667
+ import { platform as platform4 } from "os";
6668
+ function getExpectedRepoUrl() {
6669
+ return platform4() === "win32" ? OBSIDIAN_WINDOWS_REPO_URL : OBSIDIAN_REPO_URL;
6670
+ }
6449
6671
  var obsidianCommand = new Command15("obsidian").description("Manage .obsidian configuration").option("-p, --path <dir>", "Path to flint (default: auto-detect)");
6450
6672
  obsidianCommand.command("update").description("Force pull latest .obsidian from remote (discards local changes)").action(async () => {
6451
6673
  const options = obsidianCommand.opts();
@@ -6462,11 +6684,20 @@ obsidianCommand.command("update").description("Force pull latest .obsidian from
6462
6684
  console.log(pc18.dim("Run `flint init` to create a new flint with .obsidian."));
6463
6685
  process.exit(1);
6464
6686
  }
6465
- console.log(pc18.dim("Fetching latest from remote..."));
6466
6687
  try {
6467
- execSync2("git fetch origin", { cwd: obsidianDir, stdio: "pipe" });
6468
- execSync2("git reset --hard origin/main", { cwd: obsidianDir, stdio: "pipe" });
6469
- console.log(pc18.green("Updated .obsidian to latest from remote."));
6688
+ const expectedUrl = getExpectedRepoUrl();
6689
+ const currentUrl = execSync2("git remote get-url origin", { cwd: obsidianDir, encoding: "utf-8" }).trim();
6690
+ if (currentUrl !== expectedUrl) {
6691
+ console.log(pc18.dim("Detected wrong platform repo. Re-cloning with correct one..."));
6692
+ await rm2(obsidianDir, { recursive: true, force: true });
6693
+ await cloneObsidian(flintPath);
6694
+ console.log(pc18.green("Re-cloned .obsidian with correct platform repo."));
6695
+ } else {
6696
+ console.log(pc18.dim("Fetching latest from remote..."));
6697
+ execSync2("git fetch origin", { cwd: obsidianDir, stdio: "pipe" });
6698
+ execSync2("git reset --hard origin/main", { cwd: obsidianDir, stdio: "pipe" });
6699
+ console.log(pc18.green("Updated .obsidian to latest from remote."));
6700
+ }
6470
6701
  } catch (err) {
6471
6702
  const message = err instanceof Error ? err.message : String(err);
6472
6703
  console.error(pc18.red(`Error updating .obsidian: ${message}`));
@@ -6519,25 +6750,25 @@ obsidianCommand.command("reset").description("Delete and re-clone .obsidian from
6519
6750
  process.exit(1);
6520
6751
  }
6521
6752
  const obsidianDir = join8(flintPath, ".obsidian");
6522
- let exists5 = false;
6753
+ let exists6 = false;
6523
6754
  try {
6524
6755
  await stat2(obsidianDir);
6525
- exists5 = true;
6756
+ exists6 = true;
6526
6757
  } catch {
6527
6758
  }
6528
- if (exists5 && !cmdOptions.force) {
6759
+ if (exists6 && !cmdOptions.force) {
6529
6760
  console.log(pc18.yellow("Warning: This will delete your current .obsidian folder and re-clone from the template repo."));
6530
6761
  console.log(pc18.yellow("Any local changes will be lost."));
6531
6762
  console.log(pc18.dim("\nUse --force to skip this confirmation."));
6532
6763
  process.exit(1);
6533
6764
  }
6534
6765
  try {
6535
- if (exists5) {
6766
+ if (exists6) {
6536
6767
  console.log(pc18.dim("Removing existing .obsidian..."));
6537
6768
  await rm2(obsidianDir, { recursive: true, force: true });
6538
6769
  }
6539
6770
  console.log(pc18.dim("Cloning .obsidian from template repo..."));
6540
- execSync2(`git clone ${OBSIDIAN_REPO_URL} "${obsidianDir}"`, { stdio: "pipe" });
6771
+ await cloneObsidian(flintPath);
6541
6772
  console.log(pc18.green("Reset .obsidian to fresh state from template repo."));
6542
6773
  } catch (err) {
6543
6774
  const message = err instanceof Error ? err.message : String(err);
@@ -7009,7 +7240,7 @@ repoCommand.command("add").description("Add a plate from a git repo").argument("
7009
7240
  getPlateDeclaration,
7010
7241
  nameFormats,
7011
7242
  updateGitignore: updateGitignore2
7012
- } = await import("./dist-RGQKIZQW.js");
7243
+ } = await import("./dist-EAYA2DAP.js");
7013
7244
  const { proper, slug } = nameFormats(name);
7014
7245
  const existing = await getPlateDeclaration(flintPath, slug);
7015
7246
  if (existing) {
@@ -7021,7 +7252,7 @@ repoCommand.command("add").description("Add a plate from a git repo").argument("
7021
7252
  Cloning ${url}...`));
7022
7253
  await clonePlateFromRepo(flintPath, slug, url, platePath);
7023
7254
  await addPlateDeclaration(flintPath, slug, platePath, { title: proper });
7024
- const { setPlateRepo } = await import("./dist-RGQKIZQW.js");
7255
+ const { setPlateRepo } = await import("./dist-EAYA2DAP.js");
7025
7256
  await setPlateRepo(flintPath, slug, url);
7026
7257
  await updateGitignore2(flintPath);
7027
7258
  console.log(pc22.green(`
@@ -7039,9 +7270,9 @@ Added plate: ${pc22.bold(proper)}`));
7039
7270
  repoCommand.command("remove").description("Remove a repo-sourced plate").argument("<name>", "Plate declaration name or slug").option("-p, --path <dir>", "Path to flint (default: auto-detect)").action(async (name, options) => {
7040
7271
  try {
7041
7272
  const flintPath = await resolveFlintPath2(options.path);
7042
- const { removePlateDeclaration, updateGitignore: updateGitignore2 } = await import("./dist-RGQKIZQW.js");
7043
- const { rm: rm5, stat: stat11 } = await import("fs/promises");
7044
- const { join: join20 } = await import("path");
7273
+ const { removePlateDeclaration, updateGitignore: updateGitignore2 } = await import("./dist-EAYA2DAP.js");
7274
+ const { rm: rm6, stat: stat11 } = await import("fs/promises");
7275
+ const { join: join21 } = await import("path");
7045
7276
  const plate = await getPlate(flintPath, name);
7046
7277
  if (!plate) {
7047
7278
  console.error(pc22.red(`Error: Plate "${name}" not found.`));
@@ -7049,7 +7280,7 @@ repoCommand.command("remove").description("Remove a repo-sourced plate").argumen
7049
7280
  }
7050
7281
  try {
7051
7282
  await stat11(plate.path);
7052
- await rm5(plate.path, { recursive: true, force: true });
7283
+ await rm6(plate.path, { recursive: true, force: true });
7053
7284
  } catch {
7054
7285
  }
7055
7286
  await removePlateDeclaration(flintPath, plate.declarationName);
@@ -7073,11 +7304,11 @@ plateCommand.command("install").description("Install a Plate from a git repo URL
7073
7304
  readPlateManifest,
7074
7305
  setPlateRepo,
7075
7306
  updateGitignore: updateGitignore2
7076
- } = await import("./dist-RGQKIZQW.js");
7077
- const { join: join20 } = await import("path");
7078
- const { mkdtemp: mkdtemp2, rm: rm5, rename: rename2 } = await import("fs/promises");
7307
+ } = await import("./dist-EAYA2DAP.js");
7308
+ const { join: join21 } = await import("path");
7309
+ const { mkdtemp: mkdtemp2, rm: rm6, rename: rename3 } = await import("fs/promises");
7079
7310
  const { tmpdir: tmpdir2 } = await import("os");
7080
- const tmpDir = await mkdtemp2(join20(tmpdir2(), "flint-plate-"));
7311
+ const tmpDir = await mkdtemp2(join21(tmpdir2(), "flint-plate-"));
7081
7312
  console.log(pc22.dim(`
7082
7313
  Cloning ${url}...`));
7083
7314
  try {
@@ -7085,7 +7316,7 @@ Cloning ${url}...`));
7085
7316
  } catch {
7086
7317
  const { execSync: execSync6 } = await import("child_process");
7087
7318
  execSync6(`git clone --depth 1 "${url}" "${tmpDir}"`, { timeout: 6e4, stdio: "ignore" });
7088
- await rm5(join20(tmpDir, ".git"), { recursive: true, force: true }).catch(() => {
7319
+ await rm6(join21(tmpDir, ".git"), { recursive: true, force: true }).catch(() => {
7089
7320
  });
7090
7321
  }
7091
7322
  const manifest = await readPlateManifest(tmpDir);
@@ -7093,15 +7324,15 @@ Cloning ${url}...`));
7093
7324
  const title = manifest.title;
7094
7325
  const existing = await getPlate(flintPath, slug);
7095
7326
  if (existing) {
7096
- await rm5(tmpDir, { recursive: true, force: true });
7327
+ await rm6(tmpDir, { recursive: true, force: true });
7097
7328
  console.error(pc22.red(`Error: Plate "${slug}" already exists.`));
7098
7329
  process.exit(1);
7099
7330
  }
7100
7331
  const { mkdir: mkdir9 } = await import("fs/promises");
7101
7332
  const platePath = `Plates/${title}`;
7102
- const absolutePlatePath = join20(flintPath, platePath);
7103
- await mkdir9(join20(flintPath, "Plates"), { recursive: true });
7104
- await rename2(tmpDir, absolutePlatePath);
7333
+ const absolutePlatePath = join21(flintPath, platePath);
7334
+ await mkdir9(join21(flintPath, "Plates"), { recursive: true });
7335
+ await rename3(tmpDir, absolutePlatePath);
7105
7336
  await addPlateDeclaration(flintPath, slug, platePath, { title });
7106
7337
  await setPlateRepo(flintPath, slug, url);
7107
7338
  await updateGitignore2(flintPath);
@@ -7122,7 +7353,7 @@ Installed plate: ${pc22.bold(title)}`));
7122
7353
  plateCommand.command("push").description("Initialize a plate as a git repo, set remote, and push").argument("<name>", "Plate name").argument("<url>", "Git remote URL").option("-p, --path <dir>", "Path to flint (default: auto-detect)").action(async (name, url, options) => {
7123
7354
  try {
7124
7355
  const flintPath = await resolveFlintPath2(options.path);
7125
- const { setPlateRepo } = await import("./dist-RGQKIZQW.js");
7356
+ const { setPlateRepo } = await import("./dist-EAYA2DAP.js");
7126
7357
  console.log(pc22.dim(`
7127
7358
  Pushing plate "${name}"...`));
7128
7359
  const result = await initPlateRepo(flintPath, name, url);
@@ -7148,7 +7379,7 @@ Pushing plate "${name}"...`));
7148
7379
  plateCommand.command("sync").description("Sync plates that have a repo configured").option("-p, --path <dir>", "Path to flint (default: auto-detect)").action(async (options) => {
7149
7380
  try {
7150
7381
  const flintPath = await resolveFlintPath2(options.path);
7151
- const { getPlateDeclarations, syncPlateRepos } = await import("./dist-RGQKIZQW.js");
7382
+ const { getPlateDeclarations, syncPlateRepos } = await import("./dist-EAYA2DAP.js");
7152
7383
  const declarations = await getPlateDeclarations(flintPath);
7153
7384
  const hasRepos = Object.values(declarations).some((d) => d.repo);
7154
7385
  if (!hasRepos) {
@@ -7424,9 +7655,9 @@ repoCommand2.addCommand(
7424
7655
  }
7425
7656
  })
7426
7657
  );
7427
- async function fileExists(path8) {
7658
+ async function fileExists(path10) {
7428
7659
  try {
7429
- await stat3(path8);
7660
+ await stat3(path10);
7430
7661
  return true;
7431
7662
  } catch {
7432
7663
  return false;
@@ -7445,12 +7676,12 @@ function parseExportRef(ref) {
7445
7676
  }
7446
7677
  async function findFlintByName2(name) {
7447
7678
  const flints = await getFlintRegistry();
7448
- let match = flints.find((f) => f.name === name);
7449
- if (match) return match;
7450
- match = flints.find((f) => getSimplifiedName(f.name) === name);
7451
- if (match) return match;
7452
- match = flints.find((f) => getSimplifiedName(basename3(f.path)) === name);
7453
- if (match) return match;
7679
+ let match2 = flints.find((f) => f.name === name);
7680
+ if (match2) return match2;
7681
+ match2 = flints.find((f) => getSimplifiedName(f.name) === name);
7682
+ if (match2) return match2;
7683
+ match2 = flints.find((f) => getSimplifiedName(basename3(f.path)) === name);
7684
+ if (match2) return match2;
7454
7685
  return null;
7455
7686
  }
7456
7687
  async function getRegisteredFlintsWithExports() {
@@ -7712,9 +7943,9 @@ function readPinsToml(latticeRoot) {
7712
7943
  if (!recordsMatch) return [];
7713
7944
  const recordsStr = recordsMatch[1];
7714
7945
  const entryPattern = /\{\s*id\s*=\s*"([^"]+)"\s*,\s*title\s*=\s*"([^"]+)"\s*\}/g;
7715
- let match;
7716
- while ((match = entryPattern.exec(recordsStr)) !== null) {
7717
- records.push({ id: match[1], title: match[2] });
7946
+ let match2;
7947
+ while ((match2 = entryPattern.exec(recordsStr)) !== null) {
7948
+ records.push({ id: match2[1], title: match2[2] });
7718
7949
  }
7719
7950
  return records;
7720
7951
  }
@@ -8045,7 +8276,7 @@ var latticeCommand = new Command21("lattice").description("Manage lattice connec
8045
8276
  // src/commands/server.ts
8046
8277
  import { Command as Command22 } from "commander";
8047
8278
  import { createRequire } from "module";
8048
- import path6 from "path";
8279
+ import path8 from "path";
8049
8280
  import { spawn as spawn6 } from "child_process";
8050
8281
  import { stat as stat6 } from "fs/promises";
8051
8282
  import pc25 from "picocolors";
@@ -8054,8 +8285,8 @@ import pc25 from "picocolors";
8054
8285
  import Fastify from "fastify";
8055
8286
  import fastifyCors from "@fastify/cors";
8056
8287
  import fastifyStatic from "@fastify/static";
8057
- import { stat as stat4 } from "fs/promises";
8058
- import path5 from "path";
8288
+ import { stat as stat5 } from "fs/promises";
8289
+ import path7 from "path";
8059
8290
  import { fileURLToPath as fileURLToPath2 } from "url";
8060
8291
  import { join as join43 } from "path";
8061
8292
 
@@ -8076,16 +8307,14 @@ import { readdirSync as readdirSync2, readFileSync as readFileSync4 } from "fs";
8076
8307
  import { existsSync as existsSync6 } from "fs";
8077
8308
  import { join as join32 } from "path";
8078
8309
  import { homedir as homedir22 } from "os";
8079
- import { spawnSync as spawnSync22 } from "child_process";
8080
8310
  import { existsSync as existsSync7, readdirSync as readdirSync3, readFileSync as readFileSync5, statSync as statSync2 } from "fs";
8081
- import { spawnSync as spawnSync32 } from "child_process";
8082
8311
  import { basename as basename4, join as join42 } from "path";
8083
8312
  import { homedir as homedir32 } from "os";
8084
8313
  import { existsSync as existsSync8, readdirSync as readdirSync4, readFileSync as readFileSync6, statSync as statSync3 } from "fs";
8085
- import { spawnSync as spawnSync4 } from "child_process";
8314
+ import { spawnSync as spawnSync22 } from "child_process";
8086
8315
  import { homedir as homedir42 } from "os";
8087
8316
  import { basename as basename22, join as join52 } from "path";
8088
- import { spawn as spawn4, spawnSync as spawnSync5 } from "child_process";
8317
+ import { spawn as spawn4, spawnSync as spawnSync32 } from "child_process";
8089
8318
  import { existsSync as existsSync9, readdirSync as readdirSync5, readFileSync as readFileSync7 } from "fs";
8090
8319
  import { join as join62 } from "path";
8091
8320
  import { homedir as homedir52 } from "os";
@@ -9984,6 +10213,11 @@ var JsonSessionWatcher = class {
9984
10213
  function createJsonSessionWatcher(transcriptPath, mapper, options) {
9985
10214
  return new JsonSessionWatcher(transcriptPath, mapper, options);
9986
10215
  }
10216
+ function isCommandOnPath(name) {
10217
+ const cmd = process.platform === "win32" ? "where" : "which";
10218
+ return spawnSync3(cmd, [name], { stdio: "ignore" }).status === 0;
10219
+ }
10220
+ var SPAWN_SHELL = process.platform === "win32";
9987
10221
  function buildTranscriptPath(cwd, nativeSessionId) {
9988
10222
  const sanitized = cwd.replace(/[^a-zA-Z0-9\-_]/g, "-");
9989
10223
  return join22(homedir5(), ".claude", "projects", sanitized, `${nativeSessionId}.jsonl`);
@@ -10049,7 +10283,7 @@ function createClaudeHarness() {
10049
10283
  return parseClaudeTranscript(content);
10050
10284
  },
10051
10285
  async isAvailable() {
10052
- return spawnSync3("which", ["claude"], { stdio: "ignore" }).status === 0;
10286
+ return isCommandOnPath("claude");
10053
10287
  }
10054
10288
  };
10055
10289
  }
@@ -10158,7 +10392,7 @@ function createCodexHarness() {
10158
10392
  return parseCodexTranscript(content);
10159
10393
  },
10160
10394
  async isAvailable() {
10161
- return spawnSync22("which", ["codex"], { stdio: "ignore" }).status === 0;
10395
+ return isCommandOnPath("codex");
10162
10396
  }
10163
10397
  };
10164
10398
  }
@@ -10321,7 +10555,7 @@ function createDroidHarness() {
10321
10555
  return parseDroidTranscript(content, { transcriptPath: options?.transcriptPath });
10322
10556
  },
10323
10557
  async isAvailable() {
10324
- return spawnSync32("which", ["droid"], { stdio: "ignore" }).status === 0;
10558
+ return isCommandOnPath("droid");
10325
10559
  }
10326
10560
  };
10327
10561
  }
@@ -10358,12 +10592,12 @@ function readGeminiSessionId(transcriptPath) {
10358
10592
  function parseGeminiSessionList(output) {
10359
10593
  const mapping = /* @__PURE__ */ new Map();
10360
10594
  for (const line of output.split("\n")) {
10361
- const match = line.match(/^\s*(\d+)\.\s+.*\[(.+?)\]\s*$/);
10362
- if (!match) {
10595
+ const match2 = line.match(/^\s*(\d+)\.\s+.*\[(.+?)\]\s*$/);
10596
+ if (!match2) {
10363
10597
  continue;
10364
10598
  }
10365
- const index = match[1];
10366
- const sessionId = match[2];
10599
+ const index = match2[1];
10600
+ const sessionId = match2[2];
10367
10601
  if (index && sessionId) {
10368
10602
  mapping.set(sessionId, index);
10369
10603
  }
@@ -10395,7 +10629,7 @@ function resolveGeminiResumeTarget(nativeSessionId, cwd) {
10395
10629
  if (nativeSessionId === "latest" || /^\d+$/.test(nativeSessionId)) {
10396
10630
  return nativeSessionId;
10397
10631
  }
10398
- const result = spawnSync4("gemini", ["--list-sessions"], {
10632
+ const result = spawnSync22("gemini", ["--list-sessions"], {
10399
10633
  cwd,
10400
10634
  encoding: "utf-8",
10401
10635
  stdio: ["ignore", "pipe", "pipe"]
@@ -10508,7 +10742,7 @@ function createGeminiHarness() {
10508
10742
  return parseGeminiTranscript(content);
10509
10743
  },
10510
10744
  async isAvailable() {
10511
- return spawnSync4("which", ["gemini"], { stdio: "ignore" }).status === 0;
10745
+ return isCommandOnPath("gemini");
10512
10746
  }
10513
10747
  };
10514
10748
  }
@@ -10568,9 +10802,9 @@ function sendNotification2(session, exitCode) {
10568
10802
  const body = `${session.runtime}:${session.id}`;
10569
10803
  try {
10570
10804
  if (process.platform === "darwin") {
10571
- spawnSync5("osascript", ["-e", `display notification "${body}" with title "${title}"`], { stdio: "ignore" });
10805
+ spawnSync32("osascript", ["-e", `display notification "${body}" with title "${title}"`], { stdio: "ignore" });
10572
10806
  } else if (process.platform === "linux") {
10573
- spawnSync5("notify-send", [title, body], { stdio: "ignore" });
10807
+ spawnSync32("notify-send", [title, body], { stdio: "ignore" });
10574
10808
  }
10575
10809
  } catch {
10576
10810
  }
@@ -10668,7 +10902,8 @@ async function spawnHarnessProcess(options) {
10668
10902
  cwd: options.cwd,
10669
10903
  detached: true,
10670
10904
  stdio: ["ignore", "ignore", "pipe"],
10671
- env: buildHarnessSpawnEnv(options.cwd, options.sessionId)
10905
+ env: buildHarnessSpawnEnv(options.cwd, options.sessionId),
10906
+ shell: process.platform === "win32"
10672
10907
  });
10673
10908
  let stderr = "";
10674
10909
  child.stderr?.on("data", (chunk) => {
@@ -10766,203 +11001,2235 @@ function killHarnessProcess(options) {
10766
11001
  }
10767
11002
 
10768
11003
  // ../../packages/flint-server/dist/index.js
10769
- import {
10770
- createRuntime,
10771
- computeRuntimeId
10772
- } from "@nuucognition/flint-runtime";
10773
- import { existsSync as existsSync10, watch as watch3 } from "fs";
10774
- import { stat as stat5 } from "fs/promises";
10775
- import path3 from "path";
10776
- import { mkdir as mkdir5, readFile as readFile6, writeFile as writeFile3 } from "fs/promises";
10777
- import { homedir as homedir6 } from "os";
10778
- import { join as join11, resolve as resolve7 } from "path";
10779
- import { existsSync as existsSync23 } from "fs";
10780
- import { stat as stat22, readFile as readFile22 } from "fs/promises";
10781
- import path22 from "path";
10782
- import { existsSync as existsSync33 } from "fs";
11004
+ import { randomUUID as randomUUID3, createHash as createHash2 } from "crypto";
11005
+ import { EventEmitter } from "events";
11006
+ import { readFile as readFile6, stat as stat4 } from "fs/promises";
10783
11007
  import { spawn as spawn5 } from "child_process";
10784
- import { readFile as readFile32 } from "fs/promises";
10785
- import path32 from "path";
10786
- import { readdir as readdir2 } from "fs/promises";
10787
11008
  import path4 from "path";
10788
- import { readdir as readdir22 } from "fs/promises";
10789
- import { join as join23 } from "path";
10790
- import { randomUUID as randomUUID3 } from "crypto";
10791
- import { writeFile as writeFile22, mkdir as mkdir22, readdir as readdir3, readFile as readFile42, stat as stat32 } from "fs/promises";
10792
- import { join as join33 } from "path";
10793
- function sendApiError(reply, status, error3, message, extra = {}) {
10794
- return reply.code(status).send({ error: error3, message, ...extra });
10795
- }
10796
- var CONTENT_TYPES = {
10797
- ".css": "text/css; charset=utf-8",
10798
- ".html": "text/html; charset=utf-8",
10799
- ".js": "application/javascript; charset=utf-8",
10800
- ".json": "application/json; charset=utf-8",
10801
- ".map": "application/json; charset=utf-8",
10802
- ".mjs": "application/javascript; charset=utf-8",
10803
- ".png": "image/png",
10804
- ".svg": "image/svg+xml",
10805
- ".tsx": "text/plain; charset=utf-8",
10806
- ".txt": "text/plain; charset=utf-8",
10807
- ".woff": "font/woff",
10808
- ".woff2": "font/woff2"
10809
- };
10810
- function contentTypeFor(filePath) {
10811
- return CONTENT_TYPES[path3.extname(filePath).toLowerCase()] ?? "application/octet-stream";
10812
- }
10813
- function isImmutableAsset(filePath) {
10814
- return /\.[a-f0-9]{8,}\./i.test(path3.basename(filePath));
10815
- }
10816
- async function resolveFlintPath4(inputPath) {
10817
- const resolved = path3.resolve(inputPath);
10818
- const flintToml = path3.join(resolved, "flint.toml");
10819
- const flintState = path3.join(resolved, ".flint");
10820
- const hasConfig = await exists3(flintToml);
10821
- const hasState = await exists3(flintState);
10822
- if (!hasConfig && !hasState) {
10823
- throw new Error(`Not a Flint workspace: ${resolved}`);
10824
- }
10825
- return resolved;
10826
- }
10827
- async function exists3(targetPath) {
10828
- try {
10829
- await stat5(targetPath);
10830
- return true;
10831
- } catch {
10832
- return false;
11009
+ import chokidar from "chokidar";
11010
+ import { glob } from "glob";
11011
+
11012
+ // ../../node_modules/.pnpm/minimatch@9.0.9/node_modules/minimatch/dist/esm/index.js
11013
+ var import_brace_expansion = __toESM(require_brace_expansion(), 1);
11014
+
11015
+ // ../../node_modules/.pnpm/minimatch@9.0.9/node_modules/minimatch/dist/esm/assert-valid-pattern.js
11016
+ var MAX_PATTERN_LENGTH = 1024 * 64;
11017
+ var assertValidPattern = (pattern) => {
11018
+ if (typeof pattern !== "string") {
11019
+ throw new TypeError("invalid pattern");
10833
11020
  }
10834
- }
10835
- function toError(error3, fallbackMessage) {
10836
- if (error3 instanceof Error) {
10837
- return error3;
11021
+ if (pattern.length > MAX_PATTERN_LENGTH) {
11022
+ throw new TypeError("pattern is too long");
10838
11023
  }
10839
- return new Error(typeof error3 === "string" ? error3 : fallbackMessage);
10840
- }
10841
- function isUnsupportedRecursiveWatchError(error3) {
10842
- const code = typeof error3 === "object" && error3 !== null && "code" in error3 ? String(error3.code ?? "") : "";
10843
- return code === "ERR_FEATURE_UNAVAILABLE_ON_PLATFORM" || code === "ENOSYS" || code === "ENOTSUP";
10844
- }
10845
- function createResilientWatcher({
10846
- label,
10847
- targetPath,
10848
- recursive = false,
10849
- retryMs = 1e3,
10850
- onChange
10851
- }) {
10852
- let watcher = null;
10853
- let retryTimer = null;
10854
- let closed = false;
10855
- const scheduleRestart = () => {
10856
- if (closed || retryTimer) {
10857
- return;
10858
- }
10859
- retryTimer = setTimeout(() => {
10860
- retryTimer = null;
10861
- start();
10862
- }, retryMs);
10863
- retryTimer.unref?.();
10864
- };
10865
- const handleWatchError = (error3) => {
10866
- const resolved = toError(error3, `${label} watcher failed`);
10867
- const unsupported = recursive && isUnsupportedRecursiveWatchError(error3);
10868
- watcher?.close();
10869
- watcher = null;
10870
- if (unsupported) {
10871
- console.warn(`[flint-server] ${label} watcher disabled: recursive fs.watch is not supported on this platform.`);
10872
- return;
11024
+ };
11025
+
11026
+ // ../../node_modules/.pnpm/minimatch@9.0.9/node_modules/minimatch/dist/esm/brace-expressions.js
11027
+ var posixClasses = {
11028
+ "[:alnum:]": ["\\p{L}\\p{Nl}\\p{Nd}", true],
11029
+ "[:alpha:]": ["\\p{L}\\p{Nl}", true],
11030
+ "[:ascii:]": ["\\x00-\\x7f", false],
11031
+ "[:blank:]": ["\\p{Zs}\\t", true],
11032
+ "[:cntrl:]": ["\\p{Cc}", true],
11033
+ "[:digit:]": ["\\p{Nd}", true],
11034
+ "[:graph:]": ["\\p{Z}\\p{C}", true, true],
11035
+ "[:lower:]": ["\\p{Ll}", true],
11036
+ "[:print:]": ["\\p{C}", true],
11037
+ "[:punct:]": ["\\p{P}", true],
11038
+ "[:space:]": ["\\p{Z}\\t\\r\\n\\v\\f", true],
11039
+ "[:upper:]": ["\\p{Lu}", true],
11040
+ "[:word:]": ["\\p{L}\\p{Nl}\\p{Nd}\\p{Pc}", true],
11041
+ "[:xdigit:]": ["A-Fa-f0-9", false]
11042
+ };
11043
+ var braceEscape = (s) => s.replace(/[[\]\\-]/g, "\\$&");
11044
+ var regexpEscape = (s) => s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
11045
+ var rangesToString = (ranges) => ranges.join("");
11046
+ var parseClass = (glob2, position) => {
11047
+ const pos = position;
11048
+ if (glob2.charAt(pos) !== "[") {
11049
+ throw new Error("not in a brace expression");
11050
+ }
11051
+ const ranges = [];
11052
+ const negs = [];
11053
+ let i = pos + 1;
11054
+ let sawStart = false;
11055
+ let uflag = false;
11056
+ let escaping = false;
11057
+ let negate = false;
11058
+ let endPos = pos;
11059
+ let rangeStart = "";
11060
+ WHILE: while (i < glob2.length) {
11061
+ const c = glob2.charAt(i);
11062
+ if ((c === "!" || c === "^") && i === pos + 1) {
11063
+ negate = true;
11064
+ i++;
11065
+ continue;
10873
11066
  }
10874
- console.warn(`[flint-server] ${label} watcher error: ${resolved.message}. Retrying.`);
10875
- scheduleRestart();
10876
- };
10877
- const start = () => {
10878
- if (closed) {
10879
- return;
11067
+ if (c === "]" && sawStart && !escaping) {
11068
+ endPos = i + 1;
11069
+ break;
10880
11070
  }
10881
- if (!existsSync10(targetPath)) {
10882
- scheduleRestart();
10883
- return;
11071
+ sawStart = true;
11072
+ if (c === "\\") {
11073
+ if (!escaping) {
11074
+ escaping = true;
11075
+ i++;
11076
+ continue;
11077
+ }
10884
11078
  }
10885
- try {
10886
- watcher = watch3(targetPath, { recursive }, (_eventType, filename) => {
10887
- onChange(filename);
10888
- });
10889
- watcher.on("error", handleWatchError);
10890
- } catch (error3) {
10891
- handleWatchError(error3);
11079
+ if (c === "[" && !escaping) {
11080
+ for (const [cls, [unip, u, neg]] of Object.entries(posixClasses)) {
11081
+ if (glob2.startsWith(cls, i)) {
11082
+ if (rangeStart) {
11083
+ return ["$.", false, glob2.length - pos, true];
11084
+ }
11085
+ i += cls.length;
11086
+ if (neg)
11087
+ negs.push(unip);
11088
+ else
11089
+ ranges.push(unip);
11090
+ uflag = uflag || u;
11091
+ continue WHILE;
11092
+ }
11093
+ }
10892
11094
  }
10893
- };
10894
- start();
10895
- return {
10896
- close() {
10897
- closed = true;
10898
- if (retryTimer) {
10899
- clearTimeout(retryTimer);
10900
- retryTimer = null;
11095
+ escaping = false;
11096
+ if (rangeStart) {
11097
+ if (c > rangeStart) {
11098
+ ranges.push(braceEscape(rangeStart) + "-" + braceEscape(c));
11099
+ } else if (c === rangeStart) {
11100
+ ranges.push(braceEscape(c));
10901
11101
  }
10902
- watcher?.close();
10903
- watcher = null;
11102
+ rangeStart = "";
11103
+ i++;
11104
+ continue;
10904
11105
  }
10905
- };
10906
- }
10907
- var RuntimeManager = class {
10908
- runtimes = /* @__PURE__ */ new Map();
10909
- async startRuntime(flintPath) {
10910
- const resolved = await resolveFlintPath4(flintPath);
10911
- const runtimeId = computeRuntimeId(resolved);
10912
- const existing = this.runtimes.get(runtimeId);
10913
- if (existing) {
10914
- return existing.getStatus();
11106
+ if (glob2.startsWith("-]", i + 1)) {
11107
+ ranges.push(braceEscape(c + "-"));
11108
+ i += 2;
11109
+ continue;
10915
11110
  }
10916
- const runtime2 = createRuntime({ flintPath: resolved });
10917
- await runtime2.start();
10918
- this.runtimes.set(runtimeId, runtime2);
10919
- return runtime2.getStatus();
11111
+ if (glob2.startsWith("-", i + 1)) {
11112
+ rangeStart = c;
11113
+ i += 2;
11114
+ continue;
11115
+ }
11116
+ ranges.push(braceEscape(c));
11117
+ i++;
10920
11118
  }
10921
- listRuntimes() {
10922
- return Array.from(this.runtimes.values()).map((runtime2) => runtime2.getStatus());
11119
+ if (endPos < i) {
11120
+ return ["", false, 0, false];
10923
11121
  }
10924
- getRuntime(id) {
10925
- return this.runtimes.get(id);
11122
+ if (!ranges.length && !negs.length) {
11123
+ return ["$.", false, glob2.length - pos, true];
10926
11124
  }
10927
- async stopRuntime(id) {
10928
- const runtime2 = this.runtimes.get(id);
10929
- if (!runtime2) {
10930
- return false;
11125
+ if (negs.length === 0 && ranges.length === 1 && /^\\?.$/.test(ranges[0]) && !negate) {
11126
+ const r = ranges[0].length === 2 ? ranges[0].slice(-1) : ranges[0];
11127
+ return [regexpEscape(r), false, endPos - pos, false];
11128
+ }
11129
+ const sranges = "[" + (negate ? "^" : "") + rangesToString(ranges) + "]";
11130
+ const snegs = "[" + (negate ? "" : "^") + rangesToString(negs) + "]";
11131
+ const comb = ranges.length && negs.length ? "(" + sranges + "|" + snegs + ")" : ranges.length ? sranges : snegs;
11132
+ return [comb, uflag, endPos - pos, true];
11133
+ };
11134
+
11135
+ // ../../node_modules/.pnpm/minimatch@9.0.9/node_modules/minimatch/dist/esm/unescape.js
11136
+ var unescape = (s, { windowsPathsNoEscape = false } = {}) => {
11137
+ return windowsPathsNoEscape ? s.replace(/\[([^\/\\])\]/g, "$1") : s.replace(/((?!\\).|^)\[([^\/\\])\]/g, "$1$2").replace(/\\([^\/])/g, "$1");
11138
+ };
11139
+
11140
+ // ../../node_modules/.pnpm/minimatch@9.0.9/node_modules/minimatch/dist/esm/ast.js
11141
+ var _a;
11142
+ var types = /* @__PURE__ */ new Set(["!", "?", "+", "*", "@"]);
11143
+ var isExtglobType = (c) => types.has(c);
11144
+ var isExtglobAST = (c) => isExtglobType(c.type);
11145
+ var adoptionMap = /* @__PURE__ */ new Map([
11146
+ ["!", ["@"]],
11147
+ ["?", ["?", "@"]],
11148
+ ["@", ["@"]],
11149
+ ["*", ["*", "+", "?", "@"]],
11150
+ ["+", ["+", "@"]]
11151
+ ]);
11152
+ var adoptionWithSpaceMap = /* @__PURE__ */ new Map([
11153
+ ["!", ["?"]],
11154
+ ["@", ["?"]],
11155
+ ["+", ["?", "*"]]
11156
+ ]);
11157
+ var adoptionAnyMap = /* @__PURE__ */ new Map([
11158
+ ["!", ["?", "@"]],
11159
+ ["?", ["?", "@"]],
11160
+ ["@", ["?", "@"]],
11161
+ ["*", ["*", "+", "?", "@"]],
11162
+ ["+", ["+", "@", "?", "*"]]
11163
+ ]);
11164
+ var usurpMap = /* @__PURE__ */ new Map([
11165
+ ["!", /* @__PURE__ */ new Map([["!", "@"]])],
11166
+ ["?", /* @__PURE__ */ new Map([["*", "*"], ["+", "*"]])],
11167
+ ["@", /* @__PURE__ */ new Map([["!", "!"], ["?", "?"], ["@", "@"], ["*", "*"], ["+", "+"]])],
11168
+ ["+", /* @__PURE__ */ new Map([["?", "*"], ["*", "*"]])]
11169
+ ]);
11170
+ var startNoTraversal = "(?!(?:^|/)\\.\\.?(?:$|/))";
11171
+ var startNoDot = "(?!\\.)";
11172
+ var addPatternStart = /* @__PURE__ */ new Set(["[", "."]);
11173
+ var justDots = /* @__PURE__ */ new Set(["..", "."]);
11174
+ var reSpecials = new Set("().*{}+?[]^$\\!");
11175
+ var regExpEscape = (s) => s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
11176
+ var qmark = "[^/]";
11177
+ var star = qmark + "*?";
11178
+ var starNoEmpty = qmark + "+?";
11179
+ var AST = class {
11180
+ type;
11181
+ #root;
11182
+ #hasMagic;
11183
+ #uflag = false;
11184
+ #parts = [];
11185
+ #parent;
11186
+ #parentIndex;
11187
+ #negs;
11188
+ #filledNegs = false;
11189
+ #options;
11190
+ #toString;
11191
+ // set to true if it's an extglob with no children
11192
+ // (which really means one child of '')
11193
+ #emptyExt = false;
11194
+ constructor(type, parent, options = {}) {
11195
+ this.type = type;
11196
+ if (type)
11197
+ this.#hasMagic = true;
11198
+ this.#parent = parent;
11199
+ this.#root = this.#parent ? this.#parent.#root : this;
11200
+ this.#options = this.#root === this ? options : this.#root.#options;
11201
+ this.#negs = this.#root === this ? [] : this.#root.#negs;
11202
+ if (type === "!" && !this.#root.#filledNegs)
11203
+ this.#negs.push(this);
11204
+ this.#parentIndex = this.#parent ? this.#parent.#parts.length : 0;
11205
+ }
11206
+ get hasMagic() {
11207
+ if (this.#hasMagic !== void 0)
11208
+ return this.#hasMagic;
11209
+ for (const p of this.#parts) {
11210
+ if (typeof p === "string")
11211
+ continue;
11212
+ if (p.type || p.hasMagic)
11213
+ return this.#hasMagic = true;
10931
11214
  }
10932
- await runtime2.stop();
10933
- this.runtimes.delete(id);
10934
- return true;
11215
+ return this.#hasMagic;
10935
11216
  }
10936
- async stopAll() {
10937
- const entries = Array.from(this.runtimes.entries());
10938
- await Promise.all(entries.map(async ([id, runtime2]) => {
10939
- await runtime2.stop();
10940
- this.runtimes.delete(id);
10941
- }));
11217
+ // reconstructs the pattern
11218
+ toString() {
11219
+ if (this.#toString !== void 0)
11220
+ return this.#toString;
11221
+ if (!this.type) {
11222
+ return this.#toString = this.#parts.map((p) => String(p)).join("");
11223
+ } else {
11224
+ return this.#toString = this.type + "(" + this.#parts.map((p) => String(p)).join("|") + ")";
11225
+ }
11226
+ }
11227
+ #fillNegs() {
11228
+ if (this !== this.#root)
11229
+ throw new Error("should only call on root");
11230
+ if (this.#filledNegs)
11231
+ return this;
11232
+ this.toString();
11233
+ this.#filledNegs = true;
11234
+ let n;
11235
+ while (n = this.#negs.pop()) {
11236
+ if (n.type !== "!")
11237
+ continue;
11238
+ let p = n;
11239
+ let pp = p.#parent;
11240
+ while (pp) {
11241
+ for (let i = p.#parentIndex + 1; !pp.type && i < pp.#parts.length; i++) {
11242
+ for (const part of n.#parts) {
11243
+ if (typeof part === "string") {
11244
+ throw new Error("string part in extglob AST??");
11245
+ }
11246
+ part.copyIn(pp.#parts[i]);
11247
+ }
11248
+ }
11249
+ p = pp;
11250
+ pp = p.#parent;
11251
+ }
11252
+ }
11253
+ return this;
10942
11254
  }
10943
- };
10944
- var REGISTRY_PATH = join11(homedir6(), ".nuucognition", "servers.json");
10945
- function getRegistryDir() {
10946
- return join11(homedir6(), ".nuucognition");
10947
- }
10948
- async function readServerRegistry() {
10949
- try {
10950
- const content = await readFile6(REGISTRY_PATH, "utf-8");
10951
- const data = JSON.parse(content);
10952
- return data.servers ?? [];
10953
- } catch (error3) {
10954
- if (error3.code === "ENOENT") {
10955
- return [];
11255
+ push(...parts) {
11256
+ for (const p of parts) {
11257
+ if (p === "")
11258
+ continue;
11259
+ if (typeof p !== "string" && !(p instanceof _a && p.#parent === this)) {
11260
+ throw new Error("invalid part: " + p);
11261
+ }
11262
+ this.#parts.push(p);
10956
11263
  }
10957
- return [];
10958
11264
  }
10959
- }
10960
- async function writeServerRegistry(servers) {
10961
- await mkdir5(getRegistryDir(), { recursive: true });
10962
- const data = { version: 1, servers };
10963
- const content = JSON.stringify(data, null, 2);
11265
+ toJSON() {
11266
+ const ret = this.type === null ? this.#parts.slice().map((p) => typeof p === "string" ? p : p.toJSON()) : [this.type, ...this.#parts.map((p) => p.toJSON())];
11267
+ if (this.isStart() && !this.type)
11268
+ ret.unshift([]);
11269
+ if (this.isEnd() && (this === this.#root || this.#root.#filledNegs && this.#parent?.type === "!")) {
11270
+ ret.push({});
11271
+ }
11272
+ return ret;
11273
+ }
11274
+ isStart() {
11275
+ if (this.#root === this)
11276
+ return true;
11277
+ if (!this.#parent?.isStart())
11278
+ return false;
11279
+ if (this.#parentIndex === 0)
11280
+ return true;
11281
+ const p = this.#parent;
11282
+ for (let i = 0; i < this.#parentIndex; i++) {
11283
+ const pp = p.#parts[i];
11284
+ if (!(pp instanceof _a && pp.type === "!")) {
11285
+ return false;
11286
+ }
11287
+ }
11288
+ return true;
11289
+ }
11290
+ isEnd() {
11291
+ if (this.#root === this)
11292
+ return true;
11293
+ if (this.#parent?.type === "!")
11294
+ return true;
11295
+ if (!this.#parent?.isEnd())
11296
+ return false;
11297
+ if (!this.type)
11298
+ return this.#parent?.isEnd();
11299
+ const pl = this.#parent ? this.#parent.#parts.length : 0;
11300
+ return this.#parentIndex === pl - 1;
11301
+ }
11302
+ copyIn(part) {
11303
+ if (typeof part === "string")
11304
+ this.push(part);
11305
+ else
11306
+ this.push(part.clone(this));
11307
+ }
11308
+ clone(parent) {
11309
+ const c = new _a(this.type, parent);
11310
+ for (const p of this.#parts) {
11311
+ c.copyIn(p);
11312
+ }
11313
+ return c;
11314
+ }
11315
+ static #parseAST(str, ast, pos, opt, extDepth) {
11316
+ const maxDepth = opt.maxExtglobRecursion ?? 2;
11317
+ let escaping = false;
11318
+ let inBrace = false;
11319
+ let braceStart = -1;
11320
+ let braceNeg = false;
11321
+ if (ast.type === null) {
11322
+ let i2 = pos;
11323
+ let acc2 = "";
11324
+ while (i2 < str.length) {
11325
+ const c = str.charAt(i2++);
11326
+ if (escaping || c === "\\") {
11327
+ escaping = !escaping;
11328
+ acc2 += c;
11329
+ continue;
11330
+ }
11331
+ if (inBrace) {
11332
+ if (i2 === braceStart + 1) {
11333
+ if (c === "^" || c === "!") {
11334
+ braceNeg = true;
11335
+ }
11336
+ } else if (c === "]" && !(i2 === braceStart + 2 && braceNeg)) {
11337
+ inBrace = false;
11338
+ }
11339
+ acc2 += c;
11340
+ continue;
11341
+ } else if (c === "[") {
11342
+ inBrace = true;
11343
+ braceStart = i2;
11344
+ braceNeg = false;
11345
+ acc2 += c;
11346
+ continue;
11347
+ }
11348
+ const doRecurse = !opt.noext && isExtglobType(c) && str.charAt(i2) === "(" && extDepth <= maxDepth;
11349
+ if (doRecurse) {
11350
+ ast.push(acc2);
11351
+ acc2 = "";
11352
+ const ext2 = new _a(c, ast);
11353
+ i2 = _a.#parseAST(str, ext2, i2, opt, extDepth + 1);
11354
+ ast.push(ext2);
11355
+ continue;
11356
+ }
11357
+ acc2 += c;
11358
+ }
11359
+ ast.push(acc2);
11360
+ return i2;
11361
+ }
11362
+ let i = pos + 1;
11363
+ let part = new _a(null, ast);
11364
+ const parts = [];
11365
+ let acc = "";
11366
+ while (i < str.length) {
11367
+ const c = str.charAt(i++);
11368
+ if (escaping || c === "\\") {
11369
+ escaping = !escaping;
11370
+ acc += c;
11371
+ continue;
11372
+ }
11373
+ if (inBrace) {
11374
+ if (i === braceStart + 1) {
11375
+ if (c === "^" || c === "!") {
11376
+ braceNeg = true;
11377
+ }
11378
+ } else if (c === "]" && !(i === braceStart + 2 && braceNeg)) {
11379
+ inBrace = false;
11380
+ }
11381
+ acc += c;
11382
+ continue;
11383
+ } else if (c === "[") {
11384
+ inBrace = true;
11385
+ braceStart = i;
11386
+ braceNeg = false;
11387
+ acc += c;
11388
+ continue;
11389
+ }
11390
+ const doRecurse = isExtglobType(c) && str.charAt(i) === "(" && /* c8 ignore start - the maxDepth is sufficient here */
11391
+ (extDepth <= maxDepth || ast && ast.#canAdoptType(c));
11392
+ if (doRecurse) {
11393
+ const depthAdd = ast && ast.#canAdoptType(c) ? 0 : 1;
11394
+ part.push(acc);
11395
+ acc = "";
11396
+ const ext2 = new _a(c, part);
11397
+ part.push(ext2);
11398
+ i = _a.#parseAST(str, ext2, i, opt, extDepth + depthAdd);
11399
+ continue;
11400
+ }
11401
+ if (c === "|") {
11402
+ part.push(acc);
11403
+ acc = "";
11404
+ parts.push(part);
11405
+ part = new _a(null, ast);
11406
+ continue;
11407
+ }
11408
+ if (c === ")") {
11409
+ if (acc === "" && ast.#parts.length === 0) {
11410
+ ast.#emptyExt = true;
11411
+ }
11412
+ part.push(acc);
11413
+ acc = "";
11414
+ ast.push(...parts, part);
11415
+ return i;
11416
+ }
11417
+ acc += c;
11418
+ }
11419
+ ast.type = null;
11420
+ ast.#hasMagic = void 0;
11421
+ ast.#parts = [str.substring(pos - 1)];
11422
+ return i;
11423
+ }
11424
+ #canAdoptWithSpace(child) {
11425
+ return this.#canAdopt(child, adoptionWithSpaceMap);
11426
+ }
11427
+ #canAdopt(child, map = adoptionMap) {
11428
+ if (!child || typeof child !== "object" || child.type !== null || child.#parts.length !== 1 || this.type === null) {
11429
+ return false;
11430
+ }
11431
+ const gc = child.#parts[0];
11432
+ if (!gc || typeof gc !== "object" || gc.type === null) {
11433
+ return false;
11434
+ }
11435
+ return this.#canAdoptType(gc.type, map);
11436
+ }
11437
+ #canAdoptType(c, map = adoptionAnyMap) {
11438
+ return !!map.get(this.type)?.includes(c);
11439
+ }
11440
+ #adoptWithSpace(child, index) {
11441
+ const gc = child.#parts[0];
11442
+ const blank = new _a(null, gc, this.options);
11443
+ blank.#parts.push("");
11444
+ gc.push(blank);
11445
+ this.#adopt(child, index);
11446
+ }
11447
+ #adopt(child, index) {
11448
+ const gc = child.#parts[0];
11449
+ this.#parts.splice(index, 1, ...gc.#parts);
11450
+ for (const p of gc.#parts) {
11451
+ if (typeof p === "object")
11452
+ p.#parent = this;
11453
+ }
11454
+ this.#toString = void 0;
11455
+ }
11456
+ #canUsurpType(c) {
11457
+ const m = usurpMap.get(this.type);
11458
+ return !!m?.has(c);
11459
+ }
11460
+ #canUsurp(child) {
11461
+ if (!child || typeof child !== "object" || child.type !== null || child.#parts.length !== 1 || this.type === null || this.#parts.length !== 1) {
11462
+ return false;
11463
+ }
11464
+ const gc = child.#parts[0];
11465
+ if (!gc || typeof gc !== "object" || gc.type === null) {
11466
+ return false;
11467
+ }
11468
+ return this.#canUsurpType(gc.type);
11469
+ }
11470
+ #usurp(child) {
11471
+ const m = usurpMap.get(this.type);
11472
+ const gc = child.#parts[0];
11473
+ const nt = m?.get(gc.type);
11474
+ if (!nt)
11475
+ return false;
11476
+ this.#parts = gc.#parts;
11477
+ for (const p of this.#parts) {
11478
+ if (typeof p === "object")
11479
+ p.#parent = this;
11480
+ }
11481
+ this.type = nt;
11482
+ this.#toString = void 0;
11483
+ this.#emptyExt = false;
11484
+ }
11485
+ #flatten() {
11486
+ if (!isExtglobAST(this)) {
11487
+ for (const p of this.#parts) {
11488
+ if (typeof p === "object")
11489
+ p.#flatten();
11490
+ }
11491
+ } else {
11492
+ let iterations = 0;
11493
+ let done = false;
11494
+ do {
11495
+ done = true;
11496
+ for (let i = 0; i < this.#parts.length; i++) {
11497
+ const c = this.#parts[i];
11498
+ if (typeof c === "object") {
11499
+ c.#flatten();
11500
+ if (this.#canAdopt(c)) {
11501
+ done = false;
11502
+ this.#adopt(c, i);
11503
+ } else if (this.#canAdoptWithSpace(c)) {
11504
+ done = false;
11505
+ this.#adoptWithSpace(c, i);
11506
+ } else if (this.#canUsurp(c)) {
11507
+ done = false;
11508
+ this.#usurp(c);
11509
+ }
11510
+ }
11511
+ }
11512
+ } while (!done && ++iterations < 10);
11513
+ }
11514
+ this.#toString = void 0;
11515
+ }
11516
+ static fromGlob(pattern, options = {}) {
11517
+ const ast = new _a(null, void 0, options);
11518
+ _a.#parseAST(pattern, ast, 0, options, 0);
11519
+ return ast;
11520
+ }
11521
+ // returns the regular expression if there's magic, or the unescaped
11522
+ // string if not.
11523
+ toMMPattern() {
11524
+ if (this !== this.#root)
11525
+ return this.#root.toMMPattern();
11526
+ const glob2 = this.toString();
11527
+ const [re, body, hasMagic, uflag] = this.toRegExpSource();
11528
+ const anyMagic = hasMagic || this.#hasMagic || this.#options.nocase && !this.#options.nocaseMagicOnly && glob2.toUpperCase() !== glob2.toLowerCase();
11529
+ if (!anyMagic) {
11530
+ return body;
11531
+ }
11532
+ const flags = (this.#options.nocase ? "i" : "") + (uflag ? "u" : "");
11533
+ return Object.assign(new RegExp(`^${re}$`, flags), {
11534
+ _src: re,
11535
+ _glob: glob2
11536
+ });
11537
+ }
11538
+ get options() {
11539
+ return this.#options;
11540
+ }
11541
+ // returns the string match, the regexp source, whether there's magic
11542
+ // in the regexp (so a regular expression is required) and whether or
11543
+ // not the uflag is needed for the regular expression (for posix classes)
11544
+ // TODO: instead of injecting the start/end at this point, just return
11545
+ // the BODY of the regexp, along with the start/end portions suitable
11546
+ // for binding the start/end in either a joined full-path makeRe context
11547
+ // (where we bind to (^|/), or a standalone matchPart context (where
11548
+ // we bind to ^, and not /). Otherwise slashes get duped!
11549
+ //
11550
+ // In part-matching mode, the start is:
11551
+ // - if not isStart: nothing
11552
+ // - if traversal possible, but not allowed: ^(?!\.\.?$)
11553
+ // - if dots allowed or not possible: ^
11554
+ // - if dots possible and not allowed: ^(?!\.)
11555
+ // end is:
11556
+ // - if not isEnd(): nothing
11557
+ // - else: $
11558
+ //
11559
+ // In full-path matching mode, we put the slash at the START of the
11560
+ // pattern, so start is:
11561
+ // - if first pattern: same as part-matching mode
11562
+ // - if not isStart(): nothing
11563
+ // - if traversal possible, but not allowed: /(?!\.\.?(?:$|/))
11564
+ // - if dots allowed or not possible: /
11565
+ // - if dots possible and not allowed: /(?!\.)
11566
+ // end is:
11567
+ // - if last pattern, same as part-matching mode
11568
+ // - else nothing
11569
+ //
11570
+ // Always put the (?:$|/) on negated tails, though, because that has to be
11571
+ // there to bind the end of the negated pattern portion, and it's easier to
11572
+ // just stick it in now rather than try to inject it later in the middle of
11573
+ // the pattern.
11574
+ //
11575
+ // We can just always return the same end, and leave it up to the caller
11576
+ // to know whether it's going to be used joined or in parts.
11577
+ // And, if the start is adjusted slightly, can do the same there:
11578
+ // - if not isStart: nothing
11579
+ // - if traversal possible, but not allowed: (?:/|^)(?!\.\.?$)
11580
+ // - if dots allowed or not possible: (?:/|^)
11581
+ // - if dots possible and not allowed: (?:/|^)(?!\.)
11582
+ //
11583
+ // But it's better to have a simpler binding without a conditional, for
11584
+ // performance, so probably better to return both start options.
11585
+ //
11586
+ // Then the caller just ignores the end if it's not the first pattern,
11587
+ // and the start always gets applied.
11588
+ //
11589
+ // But that's always going to be $ if it's the ending pattern, or nothing,
11590
+ // so the caller can just attach $ at the end of the pattern when building.
11591
+ //
11592
+ // So the todo is:
11593
+ // - better detect what kind of start is needed
11594
+ // - return both flavors of starting pattern
11595
+ // - attach $ at the end of the pattern when creating the actual RegExp
11596
+ //
11597
+ // Ah, but wait, no, that all only applies to the root when the first pattern
11598
+ // is not an extglob. If the first pattern IS an extglob, then we need all
11599
+ // that dot prevention biz to live in the extglob portions, because eg
11600
+ // +(*|.x*) can match .xy but not .yx.
11601
+ //
11602
+ // So, return the two flavors if it's #root and the first child is not an
11603
+ // AST, otherwise leave it to the child AST to handle it, and there,
11604
+ // use the (?:^|/) style of start binding.
11605
+ //
11606
+ // Even simplified further:
11607
+ // - Since the start for a join is eg /(?!\.) and the start for a part
11608
+ // is ^(?!\.), we can just prepend (?!\.) to the pattern (either root
11609
+ // or start or whatever) and prepend ^ or / at the Regexp construction.
11610
+ toRegExpSource(allowDot) {
11611
+ const dot = allowDot ?? !!this.#options.dot;
11612
+ if (this.#root === this) {
11613
+ this.#flatten();
11614
+ this.#fillNegs();
11615
+ }
11616
+ if (!isExtglobAST(this)) {
11617
+ const noEmpty = this.isStart() && this.isEnd();
11618
+ const src = this.#parts.map((p) => {
11619
+ const [re, _, hasMagic, uflag] = typeof p === "string" ? _a.#parseGlob(p, this.#hasMagic, noEmpty) : p.toRegExpSource(allowDot);
11620
+ this.#hasMagic = this.#hasMagic || hasMagic;
11621
+ this.#uflag = this.#uflag || uflag;
11622
+ return re;
11623
+ }).join("");
11624
+ let start2 = "";
11625
+ if (this.isStart()) {
11626
+ if (typeof this.#parts[0] === "string") {
11627
+ const dotTravAllowed = this.#parts.length === 1 && justDots.has(this.#parts[0]);
11628
+ if (!dotTravAllowed) {
11629
+ const aps = addPatternStart;
11630
+ const needNoTrav = (
11631
+ // dots are allowed, and the pattern starts with [ or .
11632
+ dot && aps.has(src.charAt(0)) || // the pattern starts with \., and then [ or .
11633
+ src.startsWith("\\.") && aps.has(src.charAt(2)) || // the pattern starts with \.\., and then [ or .
11634
+ src.startsWith("\\.\\.") && aps.has(src.charAt(4))
11635
+ );
11636
+ const needNoDot = !dot && !allowDot && aps.has(src.charAt(0));
11637
+ start2 = needNoTrav ? startNoTraversal : needNoDot ? startNoDot : "";
11638
+ }
11639
+ }
11640
+ }
11641
+ let end = "";
11642
+ if (this.isEnd() && this.#root.#filledNegs && this.#parent?.type === "!") {
11643
+ end = "(?:$|\\/)";
11644
+ }
11645
+ const final2 = start2 + src + end;
11646
+ return [
11647
+ final2,
11648
+ unescape(src),
11649
+ this.#hasMagic = !!this.#hasMagic,
11650
+ this.#uflag
11651
+ ];
11652
+ }
11653
+ const repeated = this.type === "*" || this.type === "+";
11654
+ const start = this.type === "!" ? "(?:(?!(?:" : "(?:";
11655
+ let body = this.#partsToRegExp(dot);
11656
+ if (this.isStart() && this.isEnd() && !body && this.type !== "!") {
11657
+ const s = this.toString();
11658
+ const me = this;
11659
+ me.#parts = [s];
11660
+ me.type = null;
11661
+ me.#hasMagic = void 0;
11662
+ return [s, unescape(this.toString()), false, false];
11663
+ }
11664
+ let bodyDotAllowed = !repeated || allowDot || dot || !startNoDot ? "" : this.#partsToRegExp(true);
11665
+ if (bodyDotAllowed === body) {
11666
+ bodyDotAllowed = "";
11667
+ }
11668
+ if (bodyDotAllowed) {
11669
+ body = `(?:${body})(?:${bodyDotAllowed})*?`;
11670
+ }
11671
+ let final = "";
11672
+ if (this.type === "!" && this.#emptyExt) {
11673
+ final = (this.isStart() && !dot ? startNoDot : "") + starNoEmpty;
11674
+ } else {
11675
+ const close = this.type === "!" ? (
11676
+ // !() must match something,but !(x) can match ''
11677
+ "))" + (this.isStart() && !dot && !allowDot ? startNoDot : "") + star + ")"
11678
+ ) : this.type === "@" ? ")" : this.type === "?" ? ")?" : this.type === "+" && bodyDotAllowed ? ")" : this.type === "*" && bodyDotAllowed ? `)?` : `)${this.type}`;
11679
+ final = start + body + close;
11680
+ }
11681
+ return [
11682
+ final,
11683
+ unescape(body),
11684
+ this.#hasMagic = !!this.#hasMagic,
11685
+ this.#uflag
11686
+ ];
11687
+ }
11688
+ #partsToRegExp(dot) {
11689
+ return this.#parts.map((p) => {
11690
+ if (typeof p === "string") {
11691
+ throw new Error("string type in extglob ast??");
11692
+ }
11693
+ const [re, _, _hasMagic, uflag] = p.toRegExpSource(dot);
11694
+ this.#uflag = this.#uflag || uflag;
11695
+ return re;
11696
+ }).filter((p) => !(this.isStart() && this.isEnd()) || !!p).join("|");
11697
+ }
11698
+ static #parseGlob(glob2, hasMagic, noEmpty = false) {
11699
+ let escaping = false;
11700
+ let re = "";
11701
+ let uflag = false;
11702
+ let inStar = false;
11703
+ for (let i = 0; i < glob2.length; i++) {
11704
+ const c = glob2.charAt(i);
11705
+ if (escaping) {
11706
+ escaping = false;
11707
+ re += (reSpecials.has(c) ? "\\" : "") + c;
11708
+ inStar = false;
11709
+ continue;
11710
+ }
11711
+ if (c === "\\") {
11712
+ if (i === glob2.length - 1) {
11713
+ re += "\\\\";
11714
+ } else {
11715
+ escaping = true;
11716
+ }
11717
+ continue;
11718
+ }
11719
+ if (c === "[") {
11720
+ const [src, needUflag, consumed, magic] = parseClass(glob2, i);
11721
+ if (consumed) {
11722
+ re += src;
11723
+ uflag = uflag || needUflag;
11724
+ i += consumed - 1;
11725
+ hasMagic = hasMagic || magic;
11726
+ inStar = false;
11727
+ continue;
11728
+ }
11729
+ }
11730
+ if (c === "*") {
11731
+ if (inStar)
11732
+ continue;
11733
+ inStar = true;
11734
+ re += noEmpty && /^[*]+$/.test(glob2) ? starNoEmpty : star;
11735
+ hasMagic = true;
11736
+ continue;
11737
+ } else {
11738
+ inStar = false;
11739
+ }
11740
+ if (c === "?") {
11741
+ re += qmark;
11742
+ hasMagic = true;
11743
+ continue;
11744
+ }
11745
+ re += regExpEscape(c);
11746
+ }
11747
+ return [re, unescape(glob2), !!hasMagic, uflag];
11748
+ }
11749
+ };
11750
+ _a = AST;
11751
+
11752
+ // ../../node_modules/.pnpm/minimatch@9.0.9/node_modules/minimatch/dist/esm/escape.js
11753
+ var escape = (s, { windowsPathsNoEscape = false } = {}) => {
11754
+ return windowsPathsNoEscape ? s.replace(/[?*()[\]]/g, "[$&]") : s.replace(/[?*()[\]\\]/g, "\\$&");
11755
+ };
11756
+
11757
+ // ../../node_modules/.pnpm/minimatch@9.0.9/node_modules/minimatch/dist/esm/index.js
11758
+ var minimatch = (p, pattern, options = {}) => {
11759
+ assertValidPattern(pattern);
11760
+ if (!options.nocomment && pattern.charAt(0) === "#") {
11761
+ return false;
11762
+ }
11763
+ return new Minimatch(pattern, options).match(p);
11764
+ };
11765
+ var starDotExtRE = /^\*+([^+@!?\*\[\(]*)$/;
11766
+ var starDotExtTest = (ext2) => (f) => !f.startsWith(".") && f.endsWith(ext2);
11767
+ var starDotExtTestDot = (ext2) => (f) => f.endsWith(ext2);
11768
+ var starDotExtTestNocase = (ext2) => {
11769
+ ext2 = ext2.toLowerCase();
11770
+ return (f) => !f.startsWith(".") && f.toLowerCase().endsWith(ext2);
11771
+ };
11772
+ var starDotExtTestNocaseDot = (ext2) => {
11773
+ ext2 = ext2.toLowerCase();
11774
+ return (f) => f.toLowerCase().endsWith(ext2);
11775
+ };
11776
+ var starDotStarRE = /^\*+\.\*+$/;
11777
+ var starDotStarTest = (f) => !f.startsWith(".") && f.includes(".");
11778
+ var starDotStarTestDot = (f) => f !== "." && f !== ".." && f.includes(".");
11779
+ var dotStarRE = /^\.\*+$/;
11780
+ var dotStarTest = (f) => f !== "." && f !== ".." && f.startsWith(".");
11781
+ var starRE = /^\*+$/;
11782
+ var starTest = (f) => f.length !== 0 && !f.startsWith(".");
11783
+ var starTestDot = (f) => f.length !== 0 && f !== "." && f !== "..";
11784
+ var qmarksRE = /^\?+([^+@!?\*\[\(]*)?$/;
11785
+ var qmarksTestNocase = ([$0, ext2 = ""]) => {
11786
+ const noext = qmarksTestNoExt([$0]);
11787
+ if (!ext2)
11788
+ return noext;
11789
+ ext2 = ext2.toLowerCase();
11790
+ return (f) => noext(f) && f.toLowerCase().endsWith(ext2);
11791
+ };
11792
+ var qmarksTestNocaseDot = ([$0, ext2 = ""]) => {
11793
+ const noext = qmarksTestNoExtDot([$0]);
11794
+ if (!ext2)
11795
+ return noext;
11796
+ ext2 = ext2.toLowerCase();
11797
+ return (f) => noext(f) && f.toLowerCase().endsWith(ext2);
11798
+ };
11799
+ var qmarksTestDot = ([$0, ext2 = ""]) => {
11800
+ const noext = qmarksTestNoExtDot([$0]);
11801
+ return !ext2 ? noext : (f) => noext(f) && f.endsWith(ext2);
11802
+ };
11803
+ var qmarksTest = ([$0, ext2 = ""]) => {
11804
+ const noext = qmarksTestNoExt([$0]);
11805
+ return !ext2 ? noext : (f) => noext(f) && f.endsWith(ext2);
11806
+ };
11807
+ var qmarksTestNoExt = ([$0]) => {
11808
+ const len = $0.length;
11809
+ return (f) => f.length === len && !f.startsWith(".");
11810
+ };
11811
+ var qmarksTestNoExtDot = ([$0]) => {
11812
+ const len = $0.length;
11813
+ return (f) => f.length === len && f !== "." && f !== "..";
11814
+ };
11815
+ var defaultPlatform = typeof process === "object" && process ? typeof process.env === "object" && process.env && process.env.__MINIMATCH_TESTING_PLATFORM__ || process.platform : "posix";
11816
+ var path3 = {
11817
+ win32: { sep: "\\" },
11818
+ posix: { sep: "/" }
11819
+ };
11820
+ var sep = defaultPlatform === "win32" ? path3.win32.sep : path3.posix.sep;
11821
+ minimatch.sep = sep;
11822
+ var GLOBSTAR = /* @__PURE__ */ Symbol("globstar **");
11823
+ minimatch.GLOBSTAR = GLOBSTAR;
11824
+ var qmark2 = "[^/]";
11825
+ var star2 = qmark2 + "*?";
11826
+ var twoStarDot = "(?:(?!(?:\\/|^)(?:\\.{1,2})($|\\/)).)*?";
11827
+ var twoStarNoDot = "(?:(?!(?:\\/|^)\\.).)*?";
11828
+ var filter = (pattern, options = {}) => (p) => minimatch(p, pattern, options);
11829
+ minimatch.filter = filter;
11830
+ var ext = (a, b = {}) => Object.assign({}, a, b);
11831
+ var defaults = (def) => {
11832
+ if (!def || typeof def !== "object" || !Object.keys(def).length) {
11833
+ return minimatch;
11834
+ }
11835
+ const orig = minimatch;
11836
+ const m = (p, pattern, options = {}) => orig(p, pattern, ext(def, options));
11837
+ return Object.assign(m, {
11838
+ Minimatch: class Minimatch extends orig.Minimatch {
11839
+ constructor(pattern, options = {}) {
11840
+ super(pattern, ext(def, options));
11841
+ }
11842
+ static defaults(options) {
11843
+ return orig.defaults(ext(def, options)).Minimatch;
11844
+ }
11845
+ },
11846
+ AST: class AST extends orig.AST {
11847
+ /* c8 ignore start */
11848
+ constructor(type, parent, options = {}) {
11849
+ super(type, parent, ext(def, options));
11850
+ }
11851
+ /* c8 ignore stop */
11852
+ static fromGlob(pattern, options = {}) {
11853
+ return orig.AST.fromGlob(pattern, ext(def, options));
11854
+ }
11855
+ },
11856
+ unescape: (s, options = {}) => orig.unescape(s, ext(def, options)),
11857
+ escape: (s, options = {}) => orig.escape(s, ext(def, options)),
11858
+ filter: (pattern, options = {}) => orig.filter(pattern, ext(def, options)),
11859
+ defaults: (options) => orig.defaults(ext(def, options)),
11860
+ makeRe: (pattern, options = {}) => orig.makeRe(pattern, ext(def, options)),
11861
+ braceExpand: (pattern, options = {}) => orig.braceExpand(pattern, ext(def, options)),
11862
+ match: (list, pattern, options = {}) => orig.match(list, pattern, ext(def, options)),
11863
+ sep: orig.sep,
11864
+ GLOBSTAR
11865
+ });
11866
+ };
11867
+ minimatch.defaults = defaults;
11868
+ var braceExpand = (pattern, options = {}) => {
11869
+ assertValidPattern(pattern);
11870
+ if (options.nobrace || !/\{(?:(?!\{).)*\}/.test(pattern)) {
11871
+ return [pattern];
11872
+ }
11873
+ return (0, import_brace_expansion.default)(pattern);
11874
+ };
11875
+ minimatch.braceExpand = braceExpand;
11876
+ var makeRe = (pattern, options = {}) => new Minimatch(pattern, options).makeRe();
11877
+ minimatch.makeRe = makeRe;
11878
+ var match = (list, pattern, options = {}) => {
11879
+ const mm = new Minimatch(pattern, options);
11880
+ list = list.filter((f) => mm.match(f));
11881
+ if (mm.options.nonull && !list.length) {
11882
+ list.push(pattern);
11883
+ }
11884
+ return list;
11885
+ };
11886
+ minimatch.match = match;
11887
+ var globMagic = /[?*]|[+@!]\(.*?\)|\[|\]/;
11888
+ var regExpEscape2 = (s) => s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
11889
+ var Minimatch = class {
11890
+ options;
11891
+ set;
11892
+ pattern;
11893
+ windowsPathsNoEscape;
11894
+ nonegate;
11895
+ negate;
11896
+ comment;
11897
+ empty;
11898
+ preserveMultipleSlashes;
11899
+ partial;
11900
+ globSet;
11901
+ globParts;
11902
+ nocase;
11903
+ isWindows;
11904
+ platform;
11905
+ windowsNoMagicRoot;
11906
+ maxGlobstarRecursion;
11907
+ regexp;
11908
+ constructor(pattern, options = {}) {
11909
+ assertValidPattern(pattern);
11910
+ options = options || {};
11911
+ this.options = options;
11912
+ this.maxGlobstarRecursion = options.maxGlobstarRecursion ?? 200;
11913
+ this.pattern = pattern;
11914
+ this.platform = options.platform || defaultPlatform;
11915
+ this.isWindows = this.platform === "win32";
11916
+ this.windowsPathsNoEscape = !!options.windowsPathsNoEscape || options.allowWindowsEscape === false;
11917
+ if (this.windowsPathsNoEscape) {
11918
+ this.pattern = this.pattern.replace(/\\/g, "/");
11919
+ }
11920
+ this.preserveMultipleSlashes = !!options.preserveMultipleSlashes;
11921
+ this.regexp = null;
11922
+ this.negate = false;
11923
+ this.nonegate = !!options.nonegate;
11924
+ this.comment = false;
11925
+ this.empty = false;
11926
+ this.partial = !!options.partial;
11927
+ this.nocase = !!this.options.nocase;
11928
+ this.windowsNoMagicRoot = options.windowsNoMagicRoot !== void 0 ? options.windowsNoMagicRoot : !!(this.isWindows && this.nocase);
11929
+ this.globSet = [];
11930
+ this.globParts = [];
11931
+ this.set = [];
11932
+ this.make();
11933
+ }
11934
+ hasMagic() {
11935
+ if (this.options.magicalBraces && this.set.length > 1) {
11936
+ return true;
11937
+ }
11938
+ for (const pattern of this.set) {
11939
+ for (const part of pattern) {
11940
+ if (typeof part !== "string")
11941
+ return true;
11942
+ }
11943
+ }
11944
+ return false;
11945
+ }
11946
+ debug(..._) {
11947
+ }
11948
+ make() {
11949
+ const pattern = this.pattern;
11950
+ const options = this.options;
11951
+ if (!options.nocomment && pattern.charAt(0) === "#") {
11952
+ this.comment = true;
11953
+ return;
11954
+ }
11955
+ if (!pattern) {
11956
+ this.empty = true;
11957
+ return;
11958
+ }
11959
+ this.parseNegate();
11960
+ this.globSet = [...new Set(this.braceExpand())];
11961
+ if (options.debug) {
11962
+ this.debug = (...args) => console.error(...args);
11963
+ }
11964
+ this.debug(this.pattern, this.globSet);
11965
+ const rawGlobParts = this.globSet.map((s) => this.slashSplit(s));
11966
+ this.globParts = this.preprocess(rawGlobParts);
11967
+ this.debug(this.pattern, this.globParts);
11968
+ let set = this.globParts.map((s, _, __) => {
11969
+ if (this.isWindows && this.windowsNoMagicRoot) {
11970
+ const isUNC = s[0] === "" && s[1] === "" && (s[2] === "?" || !globMagic.test(s[2])) && !globMagic.test(s[3]);
11971
+ const isDrive = /^[a-z]:/i.test(s[0]);
11972
+ if (isUNC) {
11973
+ return [...s.slice(0, 4), ...s.slice(4).map((ss) => this.parse(ss))];
11974
+ } else if (isDrive) {
11975
+ return [s[0], ...s.slice(1).map((ss) => this.parse(ss))];
11976
+ }
11977
+ }
11978
+ return s.map((ss) => this.parse(ss));
11979
+ });
11980
+ this.debug(this.pattern, set);
11981
+ this.set = set.filter((s) => s.indexOf(false) === -1);
11982
+ if (this.isWindows) {
11983
+ for (let i = 0; i < this.set.length; i++) {
11984
+ const p = this.set[i];
11985
+ if (p[0] === "" && p[1] === "" && this.globParts[i][2] === "?" && typeof p[3] === "string" && /^[a-z]:$/i.test(p[3])) {
11986
+ p[2] = "?";
11987
+ }
11988
+ }
11989
+ }
11990
+ this.debug(this.pattern, this.set);
11991
+ }
11992
+ // various transforms to equivalent pattern sets that are
11993
+ // faster to process in a filesystem walk. The goal is to
11994
+ // eliminate what we can, and push all ** patterns as far
11995
+ // to the right as possible, even if it increases the number
11996
+ // of patterns that we have to process.
11997
+ preprocess(globParts) {
11998
+ if (this.options.noglobstar) {
11999
+ for (let i = 0; i < globParts.length; i++) {
12000
+ for (let j = 0; j < globParts[i].length; j++) {
12001
+ if (globParts[i][j] === "**") {
12002
+ globParts[i][j] = "*";
12003
+ }
12004
+ }
12005
+ }
12006
+ }
12007
+ const { optimizationLevel = 1 } = this.options;
12008
+ if (optimizationLevel >= 2) {
12009
+ globParts = this.firstPhasePreProcess(globParts);
12010
+ globParts = this.secondPhasePreProcess(globParts);
12011
+ } else if (optimizationLevel >= 1) {
12012
+ globParts = this.levelOneOptimize(globParts);
12013
+ } else {
12014
+ globParts = this.adjascentGlobstarOptimize(globParts);
12015
+ }
12016
+ return globParts;
12017
+ }
12018
+ // just get rid of adjascent ** portions
12019
+ adjascentGlobstarOptimize(globParts) {
12020
+ return globParts.map((parts) => {
12021
+ let gs = -1;
12022
+ while (-1 !== (gs = parts.indexOf("**", gs + 1))) {
12023
+ let i = gs;
12024
+ while (parts[i + 1] === "**") {
12025
+ i++;
12026
+ }
12027
+ if (i !== gs) {
12028
+ parts.splice(gs, i - gs);
12029
+ }
12030
+ }
12031
+ return parts;
12032
+ });
12033
+ }
12034
+ // get rid of adjascent ** and resolve .. portions
12035
+ levelOneOptimize(globParts) {
12036
+ return globParts.map((parts) => {
12037
+ parts = parts.reduce((set, part) => {
12038
+ const prev = set[set.length - 1];
12039
+ if (part === "**" && prev === "**") {
12040
+ return set;
12041
+ }
12042
+ if (part === "..") {
12043
+ if (prev && prev !== ".." && prev !== "." && prev !== "**") {
12044
+ set.pop();
12045
+ return set;
12046
+ }
12047
+ }
12048
+ set.push(part);
12049
+ return set;
12050
+ }, []);
12051
+ return parts.length === 0 ? [""] : parts;
12052
+ });
12053
+ }
12054
+ levelTwoFileOptimize(parts) {
12055
+ if (!Array.isArray(parts)) {
12056
+ parts = this.slashSplit(parts);
12057
+ }
12058
+ let didSomething = false;
12059
+ do {
12060
+ didSomething = false;
12061
+ if (!this.preserveMultipleSlashes) {
12062
+ for (let i = 1; i < parts.length - 1; i++) {
12063
+ const p = parts[i];
12064
+ if (i === 1 && p === "" && parts[0] === "")
12065
+ continue;
12066
+ if (p === "." || p === "") {
12067
+ didSomething = true;
12068
+ parts.splice(i, 1);
12069
+ i--;
12070
+ }
12071
+ }
12072
+ if (parts[0] === "." && parts.length === 2 && (parts[1] === "." || parts[1] === "")) {
12073
+ didSomething = true;
12074
+ parts.pop();
12075
+ }
12076
+ }
12077
+ let dd = 0;
12078
+ while (-1 !== (dd = parts.indexOf("..", dd + 1))) {
12079
+ const p = parts[dd - 1];
12080
+ if (p && p !== "." && p !== ".." && p !== "**") {
12081
+ didSomething = true;
12082
+ parts.splice(dd - 1, 2);
12083
+ dd -= 2;
12084
+ }
12085
+ }
12086
+ } while (didSomething);
12087
+ return parts.length === 0 ? [""] : parts;
12088
+ }
12089
+ // First phase: single-pattern processing
12090
+ // <pre> is 1 or more portions
12091
+ // <rest> is 1 or more portions
12092
+ // <p> is any portion other than ., .., '', or **
12093
+ // <e> is . or ''
12094
+ //
12095
+ // **/.. is *brutal* for filesystem walking performance, because
12096
+ // it effectively resets the recursive walk each time it occurs,
12097
+ // and ** cannot be reduced out by a .. pattern part like a regexp
12098
+ // or most strings (other than .., ., and '') can be.
12099
+ //
12100
+ // <pre>/**/../<p>/<p>/<rest> -> {<pre>/../<p>/<p>/<rest>,<pre>/**/<p>/<p>/<rest>}
12101
+ // <pre>/<e>/<rest> -> <pre>/<rest>
12102
+ // <pre>/<p>/../<rest> -> <pre>/<rest>
12103
+ // **/**/<rest> -> **/<rest>
12104
+ //
12105
+ // **/*/<rest> -> */**/<rest> <== not valid because ** doesn't follow
12106
+ // this WOULD be allowed if ** did follow symlinks, or * didn't
12107
+ firstPhasePreProcess(globParts) {
12108
+ let didSomething = false;
12109
+ do {
12110
+ didSomething = false;
12111
+ for (let parts of globParts) {
12112
+ let gs = -1;
12113
+ while (-1 !== (gs = parts.indexOf("**", gs + 1))) {
12114
+ let gss = gs;
12115
+ while (parts[gss + 1] === "**") {
12116
+ gss++;
12117
+ }
12118
+ if (gss > gs) {
12119
+ parts.splice(gs + 1, gss - gs);
12120
+ }
12121
+ let next = parts[gs + 1];
12122
+ const p = parts[gs + 2];
12123
+ const p2 = parts[gs + 3];
12124
+ if (next !== "..")
12125
+ continue;
12126
+ if (!p || p === "." || p === ".." || !p2 || p2 === "." || p2 === "..") {
12127
+ continue;
12128
+ }
12129
+ didSomething = true;
12130
+ parts.splice(gs, 1);
12131
+ const other = parts.slice(0);
12132
+ other[gs] = "**";
12133
+ globParts.push(other);
12134
+ gs--;
12135
+ }
12136
+ if (!this.preserveMultipleSlashes) {
12137
+ for (let i = 1; i < parts.length - 1; i++) {
12138
+ const p = parts[i];
12139
+ if (i === 1 && p === "" && parts[0] === "")
12140
+ continue;
12141
+ if (p === "." || p === "") {
12142
+ didSomething = true;
12143
+ parts.splice(i, 1);
12144
+ i--;
12145
+ }
12146
+ }
12147
+ if (parts[0] === "." && parts.length === 2 && (parts[1] === "." || parts[1] === "")) {
12148
+ didSomething = true;
12149
+ parts.pop();
12150
+ }
12151
+ }
12152
+ let dd = 0;
12153
+ while (-1 !== (dd = parts.indexOf("..", dd + 1))) {
12154
+ const p = parts[dd - 1];
12155
+ if (p && p !== "." && p !== ".." && p !== "**") {
12156
+ didSomething = true;
12157
+ const needDot = dd === 1 && parts[dd + 1] === "**";
12158
+ const splin = needDot ? ["."] : [];
12159
+ parts.splice(dd - 1, 2, ...splin);
12160
+ if (parts.length === 0)
12161
+ parts.push("");
12162
+ dd -= 2;
12163
+ }
12164
+ }
12165
+ }
12166
+ } while (didSomething);
12167
+ return globParts;
12168
+ }
12169
+ // second phase: multi-pattern dedupes
12170
+ // {<pre>/*/<rest>,<pre>/<p>/<rest>} -> <pre>/*/<rest>
12171
+ // {<pre>/<rest>,<pre>/<rest>} -> <pre>/<rest>
12172
+ // {<pre>/**/<rest>,<pre>/<rest>} -> <pre>/**/<rest>
12173
+ //
12174
+ // {<pre>/**/<rest>,<pre>/**/<p>/<rest>} -> <pre>/**/<rest>
12175
+ // ^-- not valid because ** doens't follow symlinks
12176
+ secondPhasePreProcess(globParts) {
12177
+ for (let i = 0; i < globParts.length - 1; i++) {
12178
+ for (let j = i + 1; j < globParts.length; j++) {
12179
+ const matched = this.partsMatch(globParts[i], globParts[j], !this.preserveMultipleSlashes);
12180
+ if (matched) {
12181
+ globParts[i] = [];
12182
+ globParts[j] = matched;
12183
+ break;
12184
+ }
12185
+ }
12186
+ }
12187
+ return globParts.filter((gs) => gs.length);
12188
+ }
12189
+ partsMatch(a, b, emptyGSMatch = false) {
12190
+ let ai = 0;
12191
+ let bi = 0;
12192
+ let result = [];
12193
+ let which = "";
12194
+ while (ai < a.length && bi < b.length) {
12195
+ if (a[ai] === b[bi]) {
12196
+ result.push(which === "b" ? b[bi] : a[ai]);
12197
+ ai++;
12198
+ bi++;
12199
+ } else if (emptyGSMatch && a[ai] === "**" && b[bi] === a[ai + 1]) {
12200
+ result.push(a[ai]);
12201
+ ai++;
12202
+ } else if (emptyGSMatch && b[bi] === "**" && a[ai] === b[bi + 1]) {
12203
+ result.push(b[bi]);
12204
+ bi++;
12205
+ } else if (a[ai] === "*" && b[bi] && (this.options.dot || !b[bi].startsWith(".")) && b[bi] !== "**") {
12206
+ if (which === "b")
12207
+ return false;
12208
+ which = "a";
12209
+ result.push(a[ai]);
12210
+ ai++;
12211
+ bi++;
12212
+ } else if (b[bi] === "*" && a[ai] && (this.options.dot || !a[ai].startsWith(".")) && a[ai] !== "**") {
12213
+ if (which === "a")
12214
+ return false;
12215
+ which = "b";
12216
+ result.push(b[bi]);
12217
+ ai++;
12218
+ bi++;
12219
+ } else {
12220
+ return false;
12221
+ }
12222
+ }
12223
+ return a.length === b.length && result;
12224
+ }
12225
+ parseNegate() {
12226
+ if (this.nonegate)
12227
+ return;
12228
+ const pattern = this.pattern;
12229
+ let negate = false;
12230
+ let negateOffset = 0;
12231
+ for (let i = 0; i < pattern.length && pattern.charAt(i) === "!"; i++) {
12232
+ negate = !negate;
12233
+ negateOffset++;
12234
+ }
12235
+ if (negateOffset)
12236
+ this.pattern = pattern.slice(negateOffset);
12237
+ this.negate = negate;
12238
+ }
12239
+ // set partial to true to test if, for example,
12240
+ // "/a/b" matches the start of "/*/b/*/d"
12241
+ // Partial means, if you run out of file before you run
12242
+ // out of pattern, then that's fine, as long as all
12243
+ // the parts match.
12244
+ matchOne(file, pattern, partial = false) {
12245
+ let fileStartIndex = 0;
12246
+ let patternStartIndex = 0;
12247
+ if (this.isWindows) {
12248
+ const fileDrive = typeof file[0] === "string" && /^[a-z]:$/i.test(file[0]);
12249
+ const fileUNC = !fileDrive && file[0] === "" && file[1] === "" && file[2] === "?" && /^[a-z]:$/i.test(file[3]);
12250
+ const patternDrive = typeof pattern[0] === "string" && /^[a-z]:$/i.test(pattern[0]);
12251
+ const patternUNC = !patternDrive && pattern[0] === "" && pattern[1] === "" && pattern[2] === "?" && typeof pattern[3] === "string" && /^[a-z]:$/i.test(pattern[3]);
12252
+ const fdi = fileUNC ? 3 : fileDrive ? 0 : void 0;
12253
+ const pdi = patternUNC ? 3 : patternDrive ? 0 : void 0;
12254
+ if (typeof fdi === "number" && typeof pdi === "number") {
12255
+ const [fd, pd] = [
12256
+ file[fdi],
12257
+ pattern[pdi]
12258
+ ];
12259
+ if (fd.toLowerCase() === pd.toLowerCase()) {
12260
+ pattern[pdi] = fd;
12261
+ patternStartIndex = pdi;
12262
+ fileStartIndex = fdi;
12263
+ }
12264
+ }
12265
+ }
12266
+ const { optimizationLevel = 1 } = this.options;
12267
+ if (optimizationLevel >= 2) {
12268
+ file = this.levelTwoFileOptimize(file);
12269
+ }
12270
+ if (pattern.includes(GLOBSTAR)) {
12271
+ return this.#matchGlobstar(file, pattern, partial, fileStartIndex, patternStartIndex);
12272
+ }
12273
+ return this.#matchOne(file, pattern, partial, fileStartIndex, patternStartIndex);
12274
+ }
12275
+ #matchGlobstar(file, pattern, partial, fileIndex, patternIndex) {
12276
+ const firstgs = pattern.indexOf(GLOBSTAR, patternIndex);
12277
+ const lastgs = pattern.lastIndexOf(GLOBSTAR);
12278
+ const [head, body, tail] = partial ? [
12279
+ pattern.slice(patternIndex, firstgs),
12280
+ pattern.slice(firstgs + 1),
12281
+ []
12282
+ ] : [
12283
+ pattern.slice(patternIndex, firstgs),
12284
+ pattern.slice(firstgs + 1, lastgs),
12285
+ pattern.slice(lastgs + 1)
12286
+ ];
12287
+ if (head.length) {
12288
+ const fileHead = file.slice(fileIndex, fileIndex + head.length);
12289
+ if (!this.#matchOne(fileHead, head, partial, 0, 0))
12290
+ return false;
12291
+ fileIndex += head.length;
12292
+ }
12293
+ let fileTailMatch = 0;
12294
+ if (tail.length) {
12295
+ if (tail.length + fileIndex > file.length)
12296
+ return false;
12297
+ let tailStart = file.length - tail.length;
12298
+ if (this.#matchOne(file, tail, partial, tailStart, 0)) {
12299
+ fileTailMatch = tail.length;
12300
+ } else {
12301
+ if (file[file.length - 1] !== "" || fileIndex + tail.length === file.length) {
12302
+ return false;
12303
+ }
12304
+ tailStart--;
12305
+ if (!this.#matchOne(file, tail, partial, tailStart, 0))
12306
+ return false;
12307
+ fileTailMatch = tail.length + 1;
12308
+ }
12309
+ }
12310
+ if (!body.length) {
12311
+ let sawSome = !!fileTailMatch;
12312
+ for (let i2 = fileIndex; i2 < file.length - fileTailMatch; i2++) {
12313
+ const f = String(file[i2]);
12314
+ sawSome = true;
12315
+ if (f === "." || f === ".." || !this.options.dot && f.startsWith(".")) {
12316
+ return false;
12317
+ }
12318
+ }
12319
+ return partial || sawSome;
12320
+ }
12321
+ const bodySegments = [[[], 0]];
12322
+ let currentBody = bodySegments[0];
12323
+ let nonGsParts = 0;
12324
+ const nonGsPartsSums = [0];
12325
+ for (const b of body) {
12326
+ if (b === GLOBSTAR) {
12327
+ nonGsPartsSums.push(nonGsParts);
12328
+ currentBody = [[], 0];
12329
+ bodySegments.push(currentBody);
12330
+ } else {
12331
+ currentBody[0].push(b);
12332
+ nonGsParts++;
12333
+ }
12334
+ }
12335
+ let i = bodySegments.length - 1;
12336
+ const fileLength = file.length - fileTailMatch;
12337
+ for (const b of bodySegments) {
12338
+ b[1] = fileLength - (nonGsPartsSums[i--] + b[0].length);
12339
+ }
12340
+ return !!this.#matchGlobStarBodySections(file, bodySegments, fileIndex, 0, partial, 0, !!fileTailMatch);
12341
+ }
12342
+ #matchGlobStarBodySections(file, bodySegments, fileIndex, bodyIndex, partial, globStarDepth, sawTail) {
12343
+ const bs = bodySegments[bodyIndex];
12344
+ if (!bs) {
12345
+ for (let i = fileIndex; i < file.length; i++) {
12346
+ sawTail = true;
12347
+ const f = file[i];
12348
+ if (f === "." || f === ".." || !this.options.dot && f.startsWith(".")) {
12349
+ return false;
12350
+ }
12351
+ }
12352
+ return sawTail;
12353
+ }
12354
+ const [body, after] = bs;
12355
+ while (fileIndex <= after) {
12356
+ const m = this.#matchOne(file.slice(0, fileIndex + body.length), body, partial, fileIndex, 0);
12357
+ if (m && globStarDepth < this.maxGlobstarRecursion) {
12358
+ const sub = this.#matchGlobStarBodySections(file, bodySegments, fileIndex + body.length, bodyIndex + 1, partial, globStarDepth + 1, sawTail);
12359
+ if (sub !== false)
12360
+ return sub;
12361
+ }
12362
+ const f = file[fileIndex];
12363
+ if (f === "." || f === ".." || !this.options.dot && f.startsWith(".")) {
12364
+ return false;
12365
+ }
12366
+ fileIndex++;
12367
+ }
12368
+ return partial || null;
12369
+ }
12370
+ #matchOne(file, pattern, partial, fileIndex, patternIndex) {
12371
+ let fi;
12372
+ let pi;
12373
+ let pl;
12374
+ let fl;
12375
+ for (fi = fileIndex, pi = patternIndex, fl = file.length, pl = pattern.length; fi < fl && pi < pl; fi++, pi++) {
12376
+ this.debug("matchOne loop");
12377
+ let p = pattern[pi];
12378
+ let f = file[fi];
12379
+ this.debug(pattern, p, f);
12380
+ if (p === false || p === GLOBSTAR)
12381
+ return false;
12382
+ let hit;
12383
+ if (typeof p === "string") {
12384
+ hit = f === p;
12385
+ this.debug("string match", p, f, hit);
12386
+ } else {
12387
+ hit = p.test(f);
12388
+ this.debug("pattern match", p, f, hit);
12389
+ }
12390
+ if (!hit)
12391
+ return false;
12392
+ }
12393
+ if (fi === fl && pi === pl) {
12394
+ return true;
12395
+ } else if (fi === fl) {
12396
+ return partial;
12397
+ } else if (pi === pl) {
12398
+ return fi === fl - 1 && file[fi] === "";
12399
+ } else {
12400
+ throw new Error("wtf?");
12401
+ }
12402
+ }
12403
+ braceExpand() {
12404
+ return braceExpand(this.pattern, this.options);
12405
+ }
12406
+ parse(pattern) {
12407
+ assertValidPattern(pattern);
12408
+ const options = this.options;
12409
+ if (pattern === "**")
12410
+ return GLOBSTAR;
12411
+ if (pattern === "")
12412
+ return "";
12413
+ let m;
12414
+ let fastTest = null;
12415
+ if (m = pattern.match(starRE)) {
12416
+ fastTest = options.dot ? starTestDot : starTest;
12417
+ } else if (m = pattern.match(starDotExtRE)) {
12418
+ fastTest = (options.nocase ? options.dot ? starDotExtTestNocaseDot : starDotExtTestNocase : options.dot ? starDotExtTestDot : starDotExtTest)(m[1]);
12419
+ } else if (m = pattern.match(qmarksRE)) {
12420
+ fastTest = (options.nocase ? options.dot ? qmarksTestNocaseDot : qmarksTestNocase : options.dot ? qmarksTestDot : qmarksTest)(m);
12421
+ } else if (m = pattern.match(starDotStarRE)) {
12422
+ fastTest = options.dot ? starDotStarTestDot : starDotStarTest;
12423
+ } else if (m = pattern.match(dotStarRE)) {
12424
+ fastTest = dotStarTest;
12425
+ }
12426
+ const re = AST.fromGlob(pattern, this.options).toMMPattern();
12427
+ if (fastTest && typeof re === "object") {
12428
+ Reflect.defineProperty(re, "test", { value: fastTest });
12429
+ }
12430
+ return re;
12431
+ }
12432
+ makeRe() {
12433
+ if (this.regexp || this.regexp === false)
12434
+ return this.regexp;
12435
+ const set = this.set;
12436
+ if (!set.length) {
12437
+ this.regexp = false;
12438
+ return this.regexp;
12439
+ }
12440
+ const options = this.options;
12441
+ const twoStar = options.noglobstar ? star2 : options.dot ? twoStarDot : twoStarNoDot;
12442
+ const flags = new Set(options.nocase ? ["i"] : []);
12443
+ let re = set.map((pattern) => {
12444
+ const pp = pattern.map((p) => {
12445
+ if (p instanceof RegExp) {
12446
+ for (const f of p.flags.split(""))
12447
+ flags.add(f);
12448
+ }
12449
+ return typeof p === "string" ? regExpEscape2(p) : p === GLOBSTAR ? GLOBSTAR : p._src;
12450
+ });
12451
+ pp.forEach((p, i) => {
12452
+ const next = pp[i + 1];
12453
+ const prev = pp[i - 1];
12454
+ if (p !== GLOBSTAR || prev === GLOBSTAR) {
12455
+ return;
12456
+ }
12457
+ if (prev === void 0) {
12458
+ if (next !== void 0 && next !== GLOBSTAR) {
12459
+ pp[i + 1] = "(?:\\/|" + twoStar + "\\/)?" + next;
12460
+ } else {
12461
+ pp[i] = twoStar;
12462
+ }
12463
+ } else if (next === void 0) {
12464
+ pp[i - 1] = prev + "(?:\\/|" + twoStar + ")?";
12465
+ } else if (next !== GLOBSTAR) {
12466
+ pp[i - 1] = prev + "(?:\\/|\\/" + twoStar + "\\/)" + next;
12467
+ pp[i + 1] = GLOBSTAR;
12468
+ }
12469
+ });
12470
+ return pp.filter((p) => p !== GLOBSTAR).join("/");
12471
+ }).join("|");
12472
+ const [open2, close] = set.length > 1 ? ["(?:", ")"] : ["", ""];
12473
+ re = "^" + open2 + re + close + "$";
12474
+ if (this.negate)
12475
+ re = "^(?!" + re + ").+$";
12476
+ try {
12477
+ this.regexp = new RegExp(re, [...flags].join(""));
12478
+ } catch (ex) {
12479
+ this.regexp = false;
12480
+ }
12481
+ return this.regexp;
12482
+ }
12483
+ slashSplit(p) {
12484
+ if (this.preserveMultipleSlashes) {
12485
+ return p.split("/");
12486
+ } else if (this.isWindows && /^\/\/[^\/]+/.test(p)) {
12487
+ return ["", ...p.split(/\/+/)];
12488
+ } else {
12489
+ return p.split(/\/+/);
12490
+ }
12491
+ }
12492
+ match(f, partial = this.partial) {
12493
+ this.debug("match", f, this.pattern);
12494
+ if (this.comment) {
12495
+ return false;
12496
+ }
12497
+ if (this.empty) {
12498
+ return f === "";
12499
+ }
12500
+ if (f === "/" && partial) {
12501
+ return true;
12502
+ }
12503
+ const options = this.options;
12504
+ if (this.isWindows) {
12505
+ f = f.split("\\").join("/");
12506
+ }
12507
+ const ff = this.slashSplit(f);
12508
+ this.debug(this.pattern, "split", ff);
12509
+ const set = this.set;
12510
+ this.debug(this.pattern, "set", set);
12511
+ let filename = ff[ff.length - 1];
12512
+ if (!filename) {
12513
+ for (let i = ff.length - 2; !filename && i >= 0; i--) {
12514
+ filename = ff[i];
12515
+ }
12516
+ }
12517
+ for (let i = 0; i < set.length; i++) {
12518
+ const pattern = set[i];
12519
+ let file = ff;
12520
+ if (options.matchBase && pattern.length === 1) {
12521
+ file = [filename];
12522
+ }
12523
+ const hit = this.matchOne(file, pattern, partial);
12524
+ if (hit) {
12525
+ if (options.flipNegate) {
12526
+ return true;
12527
+ }
12528
+ return !this.negate;
12529
+ }
12530
+ }
12531
+ if (options.flipNegate) {
12532
+ return false;
12533
+ }
12534
+ return this.negate;
12535
+ }
12536
+ static defaults(def) {
12537
+ return minimatch.defaults(def).Minimatch;
12538
+ }
12539
+ };
12540
+ minimatch.AST = AST;
12541
+ minimatch.Minimatch = Minimatch;
12542
+ minimatch.escape = escape;
12543
+ minimatch.unescape = unescape;
12544
+
12545
+ // ../../packages/flint-server/dist/index.js
12546
+ import { parse as parseYaml } from "yaml";
12547
+ import { existsSync as existsSync10, watch as watch3 } from "fs";
12548
+ import { stat as stat22 } from "fs/promises";
12549
+ import path22 from "path";
12550
+ import { mkdir as mkdir5, readFile as readFile22, writeFile as writeFile3 } from "fs/promises";
12551
+ import { homedir as homedir6 } from "os";
12552
+ import { join as join11, resolve as resolve7 } from "path";
12553
+ import { existsSync as existsSync23 } from "fs";
12554
+ import { stat as stat32, readFile as readFile32 } from "fs/promises";
12555
+ import path32 from "path";
12556
+ import { existsSync as existsSync33 } from "fs";
12557
+ import { spawn as spawn22 } from "child_process";
12558
+ import { readFile as readFile42 } from "fs/promises";
12559
+ import path42 from "path";
12560
+ import { readdir as readdir2 } from "fs/promises";
12561
+ import path5 from "path";
12562
+ import { readdir as readdir22 } from "fs/promises";
12563
+ import { join as join23 } from "path";
12564
+ import { mkdir as mkdir22, readFile as readFile52, rename as rename2, writeFile as writeFile22, readdir as readdir3 } from "fs/promises";
12565
+ import path6 from "path";
12566
+ import { randomUUID as randomUUID22 } from "crypto";
12567
+ import { writeFile as writeFile32, mkdir as mkdir32, readdir as readdir4, readFile as readFile62, stat as stat42 } from "fs/promises";
12568
+ import { join as join33 } from "path";
12569
+ var DEFAULT_EVENT_LOG_SIZE = 200;
12570
+ function computeRuntimeId(flintPath) {
12571
+ const resolved = path4.resolve(flintPath);
12572
+ return createHash2("sha1").update(resolved).digest("hex").slice(0, 10);
12573
+ }
12574
+ function createRuntime(options) {
12575
+ return new FlintRuntimeImpl(options);
12576
+ }
12577
+ var FlintRuntimeImpl = class {
12578
+ id;
12579
+ flintPath;
12580
+ hooksPath;
12581
+ logger;
12582
+ eventLogSize;
12583
+ emitter = new EventEmitter();
12584
+ watcher = null;
12585
+ hooksConfig = { hooks: {} };
12586
+ eventLog = [];
12587
+ frontmatterCache = /* @__PURE__ */ new Map();
12588
+ sessionCache = /* @__PURE__ */ new Map();
12589
+ startedAt = null;
12590
+ constructor(options) {
12591
+ this.flintPath = path4.resolve(options.flintPath);
12592
+ this.hooksPath = options.hooksPath ? path4.resolve(options.hooksPath) : path4.join(this.flintPath, "flint-hooks.toml");
12593
+ this.id = computeRuntimeId(this.flintPath);
12594
+ this.eventLogSize = options.eventLogSize ?? DEFAULT_EVENT_LOG_SIZE;
12595
+ this.logger = options.logger ?? {
12596
+ debug: (...args) => console.debug("[flint-runtime]", ...args),
12597
+ info: (...args) => console.info("[flint-runtime]", ...args),
12598
+ warn: (...args) => console.warn("[flint-runtime]", ...args),
12599
+ error: (...args) => console.error("[flint-runtime]", ...args)
12600
+ };
12601
+ }
12602
+ on(event, handler) {
12603
+ this.emitter.on(event, handler);
12604
+ }
12605
+ off(event, handler) {
12606
+ this.emitter.off(event, handler);
12607
+ }
12608
+ async start() {
12609
+ if (this.watcher) {
12610
+ return;
12611
+ }
12612
+ await this.reloadHooks();
12613
+ await this.seedCaches();
12614
+ const relativeHooksPath = path4.relative(this.flintPath, this.hooksPath);
12615
+ const watchPatterns = [
12616
+ "Mesh/**/*.md",
12617
+ ".flint/sessions/*.json",
12618
+ relativeHooksPath || "flint-hooks.toml"
12619
+ ];
12620
+ this.watcher = chokidar.watch(watchPatterns, {
12621
+ cwd: this.flintPath,
12622
+ ignoreInitial: true,
12623
+ awaitWriteFinish: {
12624
+ stabilityThreshold: 200,
12625
+ pollInterval: 50
12626
+ }
12627
+ });
12628
+ this.watcher.on("add", (filePath) => this.handleWatchEvent("add", filePath));
12629
+ this.watcher.on("change", (filePath) => this.handleWatchEvent("change", filePath));
12630
+ this.watcher.on("unlink", (filePath) => this.handleWatchEvent("unlink", filePath));
12631
+ this.startedAt = (/* @__PURE__ */ new Date()).toISOString();
12632
+ await this.emitEvent("RuntimeStart", {
12633
+ startedAt: this.startedAt
12634
+ });
12635
+ }
12636
+ async stop() {
12637
+ if (!this.watcher) {
12638
+ return;
12639
+ }
12640
+ await this.emitEvent("RuntimeStop", {
12641
+ stoppedAt: (/* @__PURE__ */ new Date()).toISOString()
12642
+ });
12643
+ await this.watcher.close();
12644
+ this.watcher = null;
12645
+ }
12646
+ async reloadHooks() {
12647
+ this.hooksConfig = await loadHooksConfig(this.hooksPath, this.logger);
12648
+ }
12649
+ getStatus() {
12650
+ return {
12651
+ id: this.id,
12652
+ flintPath: this.flintPath,
12653
+ hooksPath: this.hooksPath,
12654
+ startedAt: this.startedAt,
12655
+ watching: this.watcher !== null,
12656
+ hookCount: countHooks(this.hooksConfig)
12657
+ };
12658
+ }
12659
+ getEventLog() {
12660
+ return [...this.eventLog];
12661
+ }
12662
+ async seedCaches() {
12663
+ const meshFiles = await glob("Mesh/**/*.md", {
12664
+ cwd: this.flintPath,
12665
+ nodir: true
12666
+ });
12667
+ await Promise.all(
12668
+ meshFiles.map(async (filePath) => {
12669
+ const snapshot = await this.readFrontmatterSnapshot(filePath);
12670
+ if (snapshot) {
12671
+ this.frontmatterCache.set(filePath, snapshot);
12672
+ }
12673
+ })
12674
+ );
12675
+ const sessionFiles = await glob(".flint/sessions/*.json", {
12676
+ cwd: this.flintPath,
12677
+ nodir: true
12678
+ });
12679
+ await Promise.all(
12680
+ sessionFiles.map(async (filePath) => {
12681
+ const snapshot = await this.readSessionSnapshot(filePath);
12682
+ if (snapshot) {
12683
+ const sessionId = path4.basename(filePath, ".json");
12684
+ this.sessionCache.set(sessionId, snapshot);
12685
+ }
12686
+ })
12687
+ );
12688
+ }
12689
+ async handleWatchEvent(event, filePath) {
12690
+ const normalized = normalizePath(filePath);
12691
+ if (normalized === normalizePath(path4.relative(this.flintPath, this.hooksPath))) {
12692
+ if (event === "change") {
12693
+ this.logger.info?.("Reloading hooks config");
12694
+ await this.reloadHooks();
12695
+ }
12696
+ return;
12697
+ }
12698
+ if (normalized.startsWith("Mesh/")) {
12699
+ if (event === "unlink") {
12700
+ this.frontmatterCache.delete(normalized);
12701
+ return;
12702
+ }
12703
+ await this.handleMeshFileChange(normalized);
12704
+ return;
12705
+ }
12706
+ if (normalized.startsWith(".flint/sessions/")) {
12707
+ if (event === "unlink") {
12708
+ const sessionId = path4.basename(normalized, ".json");
12709
+ this.sessionCache.delete(sessionId);
12710
+ return;
12711
+ }
12712
+ await this.handleSessionFileChange(normalized);
12713
+ return;
12714
+ }
12715
+ }
12716
+ async handleMeshFileChange(relativePath) {
12717
+ const snapshot = await this.readFrontmatterSnapshot(relativePath);
12718
+ if (!snapshot) {
12719
+ return;
12720
+ }
12721
+ const previous = this.frontmatterCache.get(relativePath);
12722
+ this.frontmatterCache.set(relativePath, snapshot);
12723
+ await this.emitEvent("FileChanged", {
12724
+ path: relativePath,
12725
+ absolutePath: path4.join(this.flintPath, relativePath),
12726
+ frontmatter: snapshot,
12727
+ previousFrontmatter: previous ?? null
12728
+ });
12729
+ if (!previous) {
12730
+ return;
12731
+ }
12732
+ if (previous.status !== snapshot.status) {
12733
+ await this.emitEvent("StatusChanged", {
12734
+ path: relativePath,
12735
+ absolutePath: path4.join(this.flintPath, relativePath),
12736
+ field: "status",
12737
+ from: previous.status ?? null,
12738
+ to: snapshot.status ?? null,
12739
+ tags: snapshot.tags
12740
+ });
12741
+ }
12742
+ const addedTags = snapshot.tags.filter((tag) => !previous.tags.includes(tag));
12743
+ const removedTags = previous.tags.filter((tag) => !snapshot.tags.includes(tag));
12744
+ for (const tag of addedTags) {
12745
+ await this.emitEvent("TagAdded", {
12746
+ path: relativePath,
12747
+ absolutePath: path4.join(this.flintPath, relativePath),
12748
+ tag,
12749
+ tags: snapshot.tags
12750
+ });
12751
+ }
12752
+ for (const tag of removedTags) {
12753
+ await this.emitEvent("TagRemoved", {
12754
+ path: relativePath,
12755
+ absolutePath: path4.join(this.flintPath, relativePath),
12756
+ tag,
12757
+ tags: snapshot.tags
12758
+ });
12759
+ }
12760
+ }
12761
+ async handleSessionFileChange(relativePath) {
12762
+ const snapshot = await this.readSessionSnapshot(relativePath);
12763
+ if (!snapshot) {
12764
+ return;
12765
+ }
12766
+ const sessionId = path4.basename(relativePath, ".json");
12767
+ const previous = this.sessionCache.get(sessionId);
12768
+ this.sessionCache.set(sessionId, snapshot);
12769
+ if (!previous && snapshot.status === "active") {
12770
+ await this.emitEvent("AgentStart", {
12771
+ sessionId,
12772
+ status: snapshot.status,
12773
+ model: snapshot.model,
12774
+ goal: snapshot.goal
12775
+ });
12776
+ return;
12777
+ }
12778
+ if (previous?.status !== snapshot.status) {
12779
+ if (snapshot.status === "active") {
12780
+ await this.emitEvent("AgentStart", {
12781
+ sessionId,
12782
+ status: snapshot.status,
12783
+ model: snapshot.model,
12784
+ goal: snapshot.goal
12785
+ });
12786
+ } else if (snapshot.status) {
12787
+ await this.emitEvent("AgentComplete", {
12788
+ sessionId,
12789
+ status: snapshot.status,
12790
+ model: snapshot.model,
12791
+ goal: snapshot.goal
12792
+ });
12793
+ }
12794
+ }
12795
+ }
12796
+ async emitEvent(type, payload) {
12797
+ const event = {
12798
+ id: randomUUID3(),
12799
+ type,
12800
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
12801
+ payload
12802
+ };
12803
+ this.eventLog.push(event);
12804
+ if (this.eventLog.length > this.eventLogSize) {
12805
+ this.eventLog.shift();
12806
+ }
12807
+ this.emitter.emit(type, event);
12808
+ await this.runHooks(type, event);
12809
+ }
12810
+ async runHooks(type, event) {
12811
+ const hooks = (this.hooksConfig.hooks ?? {})[type] ?? [];
12812
+ if (!hooks.length) {
12813
+ return;
12814
+ }
12815
+ for (const hook of hooks) {
12816
+ if (!hookMatches(type, hook, event.payload)) {
12817
+ continue;
12818
+ }
12819
+ try {
12820
+ await executeHook({
12821
+ hook,
12822
+ event,
12823
+ flintPath: this.flintPath,
12824
+ logger: this.logger
12825
+ });
12826
+ } catch (error3) {
12827
+ this.logger.error?.("Hook execution failed", error3);
12828
+ }
12829
+ }
12830
+ }
12831
+ async readFrontmatterSnapshot(relativePath) {
12832
+ const absolutePath = path4.join(this.flintPath, relativePath);
12833
+ const content = await safeReadFile(absolutePath);
12834
+ if (!content) {
12835
+ return null;
12836
+ }
12837
+ const { frontmatter } = parseFrontmatter(content);
12838
+ const tags = extractTags(frontmatter);
12839
+ const status = frontmatter?.status ? String(frontmatter.status) : void 0;
12840
+ return { status, tags };
12841
+ }
12842
+ async readSessionSnapshot(relativePath) {
12843
+ const absolutePath = path4.join(this.flintPath, relativePath);
12844
+ const content = await safeReadFile(absolutePath);
12845
+ if (!content) {
12846
+ return null;
12847
+ }
12848
+ try {
12849
+ const parsed = JSON.parse(content);
12850
+ return {
12851
+ status: typeof parsed.status === "string" ? parsed.status : void 0,
12852
+ model: typeof parsed.model === "string" ? parsed.model : void 0,
12853
+ goal: typeof parsed.goal === "string" ? parsed.goal : void 0
12854
+ };
12855
+ } catch {
12856
+ return null;
12857
+ }
12858
+ }
12859
+ };
12860
+ function normalizePath(filePath) {
12861
+ return filePath.replace(/\\/g, "/");
12862
+ }
12863
+ async function safeReadFile(filePath) {
12864
+ try {
12865
+ const fileStats = await stat4(filePath);
12866
+ if (!fileStats.isFile()) {
12867
+ return null;
12868
+ }
12869
+ return await readFile6(filePath, "utf-8");
12870
+ } catch {
12871
+ return null;
12872
+ }
12873
+ }
12874
+ function parseFrontmatter(content) {
12875
+ const match2 = content.match(/^---\n([\s\S]*?)\n---\n?/);
12876
+ if (!match2) {
12877
+ return { frontmatter: null, body: content };
12878
+ }
12879
+ const raw = match2[1] ?? "";
12880
+ let frontmatter = {};
12881
+ try {
12882
+ const parsed = parseYaml(raw);
12883
+ if (parsed && typeof parsed === "object") {
12884
+ frontmatter = parsed;
12885
+ }
12886
+ } catch {
12887
+ frontmatter = {};
12888
+ }
12889
+ const body = content.slice(match2[0].length);
12890
+ return { frontmatter, body };
12891
+ }
12892
+ function extractTags(frontmatter) {
12893
+ if (!frontmatter || frontmatter.tags === void 0) {
12894
+ return [];
12895
+ }
12896
+ const tags = frontmatter.tags;
12897
+ if (Array.isArray(tags)) {
12898
+ return tags.map((tag) => String(tag));
12899
+ }
12900
+ if (typeof tags === "string") {
12901
+ return [tags];
12902
+ }
12903
+ return [];
12904
+ }
12905
+ async function loadHooksConfig(hooksPath, logger) {
12906
+ try {
12907
+ const content = await readFile6(hooksPath, "utf-8");
12908
+ const parsed = parse(content);
12909
+ if (parsed && typeof parsed === "object") {
12910
+ return parsed;
12911
+ }
12912
+ } catch (error3) {
12913
+ if (error3.code !== "ENOENT") {
12914
+ logger.warn?.("Failed to read hooks config", error3);
12915
+ }
12916
+ }
12917
+ return { hooks: {} };
12918
+ }
12919
+ function countHooks(config) {
12920
+ const hooks = config.hooks ?? {};
12921
+ return Object.values(hooks).reduce((count, entries) => count + entries.length, 0);
12922
+ }
12923
+ function hookMatches(type, hook, payload) {
12924
+ const matcher = hook.matcher;
12925
+ if (!matcher) {
12926
+ return true;
12927
+ }
12928
+ if (typeof matcher === "string") {
12929
+ if (type === "FileChanged") {
12930
+ const targetPath = typeof payload.path === "string" ? payload.path : "";
12931
+ return minimatch(targetPath, matcher, { dot: true });
12932
+ }
12933
+ return true;
12934
+ }
12935
+ if (matcher.tag) {
12936
+ const tags = Array.isArray(payload.tags) ? payload.tags.map(String) : [];
12937
+ if (!tags.includes(matcher.tag)) {
12938
+ return false;
12939
+ }
12940
+ }
12941
+ const fieldValue = typeof payload.field === "string" ? payload.field : void 0;
12942
+ if (matcher.field && matcher.field !== fieldValue) {
12943
+ return false;
12944
+ }
12945
+ const fromValue = typeof payload.from === "string" ? payload.from : void 0;
12946
+ if (matcher.from && matcher.from !== fromValue) {
12947
+ return false;
12948
+ }
12949
+ const toValue = typeof payload.to === "string" ? payload.to : void 0;
12950
+ if (matcher.to && matcher.to !== toValue) {
12951
+ return false;
12952
+ }
12953
+ return true;
12954
+ }
12955
+ async function executeHook(options) {
12956
+ const { hook, event, flintPath, logger } = options;
12957
+ const command = resolveHookCommand(hook.command, flintPath);
12958
+ logger.debug?.("Running hook", hook.command);
12959
+ await new Promise((resolve22, reject) => {
12960
+ const envPathEntries = [
12961
+ path4.join(flintPath, "node_modules", ".bin"),
12962
+ path4.join(process.cwd(), "node_modules", ".bin"),
12963
+ process.env.PATH
12964
+ ].filter(Boolean);
12965
+ const child = spawn5(command, {
12966
+ cwd: flintPath,
12967
+ env: {
12968
+ ...process.env,
12969
+ PATH: envPathEntries.join(path4.delimiter)
12970
+ },
12971
+ shell: true,
12972
+ stdio: ["pipe", "pipe", "pipe"]
12973
+ });
12974
+ let stdout = "";
12975
+ let stderr = "";
12976
+ child.stdout?.on("data", (data) => {
12977
+ stdout += String(data);
12978
+ });
12979
+ child.stderr?.on("data", (data) => {
12980
+ stderr += String(data);
12981
+ });
12982
+ const timeoutMs = hook.timeout ? hook.timeout * 1e3 : void 0;
12983
+ let timeoutId = null;
12984
+ if (timeoutMs) {
12985
+ timeoutId = setTimeout(() => {
12986
+ child.kill("SIGKILL");
12987
+ reject(new Error(`Hook timed out after ${hook.timeout}s: ${hook.command}`));
12988
+ }, timeoutMs);
12989
+ }
12990
+ child.on("error", (error3) => {
12991
+ if (timeoutId) {
12992
+ clearTimeout(timeoutId);
12993
+ }
12994
+ reject(error3);
12995
+ });
12996
+ child.on("close", (code) => {
12997
+ if (timeoutId) {
12998
+ clearTimeout(timeoutId);
12999
+ }
13000
+ if (code === 0) {
13001
+ if (stdout.trim()) {
13002
+ logger.info?.(`Hook output: ${stdout.trim()}`);
13003
+ }
13004
+ resolve22();
13005
+ return;
13006
+ }
13007
+ if (code === 2) {
13008
+ logger.warn?.(`Hook blocked: ${hook.command}`);
13009
+ if (stderr.trim()) {
13010
+ logger.warn?.(stderr.trim());
13011
+ }
13012
+ resolve22();
13013
+ return;
13014
+ }
13015
+ const error3 = new Error(`Hook failed (${code ?? "unknown"}): ${hook.command}`);
13016
+ if (stderr.trim()) {
13017
+ logger.error?.(stderr.trim());
13018
+ }
13019
+ reject(error3);
13020
+ });
13021
+ child.stdin?.write(JSON.stringify({
13022
+ event,
13023
+ flint: { path: flintPath }
13024
+ }));
13025
+ child.stdin?.end();
13026
+ });
13027
+ }
13028
+ function resolveHookCommand(command, flintPath) {
13029
+ const trimmed = command.trim();
13030
+ if (!trimmed) {
13031
+ return trimmed;
13032
+ }
13033
+ const parts = trimmed.split(/\s+/);
13034
+ const target = parts[0] ?? "";
13035
+ const rest = parts.slice(1).join(" ");
13036
+ const extension = path4.extname(target);
13037
+ if (!extension) {
13038
+ return trimmed;
13039
+ }
13040
+ const resolvedTarget = path4.isAbsolute(target) ? target : path4.join(flintPath, target);
13041
+ const quotedTarget = quoteIfNeeded(resolvedTarget);
13042
+ const suffix = rest ? ` ${rest}` : "";
13043
+ if (extension === ".ts") {
13044
+ return `tsx ${quotedTarget}${suffix}`;
13045
+ }
13046
+ if (extension === ".py") {
13047
+ return `python3 ${quotedTarget}${suffix}`;
13048
+ }
13049
+ if (extension === ".sh") {
13050
+ return `bash ${quotedTarget}${suffix}`;
13051
+ }
13052
+ return trimmed;
13053
+ }
13054
+ function quoteIfNeeded(value) {
13055
+ if (value.includes(" ")) {
13056
+ return `"${value.replace(/"/g, '\\"')}"`;
13057
+ }
13058
+ return value;
13059
+ }
13060
+ function sendApiError(reply, status, error3, message, extra = {}) {
13061
+ return reply.code(status).send({ error: error3, message, ...extra });
13062
+ }
13063
+ var CONTENT_TYPES = {
13064
+ ".css": "text/css; charset=utf-8",
13065
+ ".html": "text/html; charset=utf-8",
13066
+ ".js": "application/javascript; charset=utf-8",
13067
+ ".json": "application/json; charset=utf-8",
13068
+ ".map": "application/json; charset=utf-8",
13069
+ ".mjs": "application/javascript; charset=utf-8",
13070
+ ".png": "image/png",
13071
+ ".svg": "image/svg+xml",
13072
+ ".tsx": "text/plain; charset=utf-8",
13073
+ ".txt": "text/plain; charset=utf-8",
13074
+ ".woff": "font/woff",
13075
+ ".woff2": "font/woff2"
13076
+ };
13077
+ function contentTypeFor(filePath) {
13078
+ return CONTENT_TYPES[path22.extname(filePath).toLowerCase()] ?? "application/octet-stream";
13079
+ }
13080
+ function isImmutableAsset(filePath) {
13081
+ return /\.[a-f0-9]{8,}\./i.test(path22.basename(filePath));
13082
+ }
13083
+ async function resolveFlintPath4(inputPath) {
13084
+ const resolved = path22.resolve(inputPath);
13085
+ const flintToml = path22.join(resolved, "flint.toml");
13086
+ const flintState = path22.join(resolved, ".flint");
13087
+ const hasConfig = await exists3(flintToml);
13088
+ const hasState = await exists3(flintState);
13089
+ if (!hasConfig && !hasState) {
13090
+ throw new Error(`Not a Flint workspace: ${resolved}`);
13091
+ }
13092
+ return resolved;
13093
+ }
13094
+ async function exists3(targetPath) {
13095
+ try {
13096
+ await stat22(targetPath);
13097
+ return true;
13098
+ } catch {
13099
+ return false;
13100
+ }
13101
+ }
13102
+ function toError(error3, fallbackMessage) {
13103
+ if (error3 instanceof Error) {
13104
+ return error3;
13105
+ }
13106
+ return new Error(typeof error3 === "string" ? error3 : fallbackMessage);
13107
+ }
13108
+ function isUnsupportedRecursiveWatchError(error3) {
13109
+ const code = typeof error3 === "object" && error3 !== null && "code" in error3 ? String(error3.code ?? "") : "";
13110
+ return code === "ERR_FEATURE_UNAVAILABLE_ON_PLATFORM" || code === "ENOSYS" || code === "ENOTSUP";
13111
+ }
13112
+ function createResilientWatcher({
13113
+ label,
13114
+ targetPath,
13115
+ recursive = false,
13116
+ retryMs = 1e3,
13117
+ onChange
13118
+ }) {
13119
+ let watcher = null;
13120
+ let retryTimer = null;
13121
+ let closed = false;
13122
+ const scheduleRestart = () => {
13123
+ if (closed || retryTimer) {
13124
+ return;
13125
+ }
13126
+ retryTimer = setTimeout(() => {
13127
+ retryTimer = null;
13128
+ start();
13129
+ }, retryMs);
13130
+ retryTimer.unref?.();
13131
+ };
13132
+ const handleWatchError = (error3) => {
13133
+ const resolved = toError(error3, `${label} watcher failed`);
13134
+ const unsupported = recursive && isUnsupportedRecursiveWatchError(error3);
13135
+ watcher?.close();
13136
+ watcher = null;
13137
+ if (unsupported) {
13138
+ console.warn(`[flint-server] ${label} watcher disabled: recursive fs.watch is not supported on this platform.`);
13139
+ return;
13140
+ }
13141
+ console.warn(`[flint-server] ${label} watcher error: ${resolved.message}. Retrying.`);
13142
+ scheduleRestart();
13143
+ };
13144
+ const start = () => {
13145
+ if (closed) {
13146
+ return;
13147
+ }
13148
+ if (!existsSync10(targetPath)) {
13149
+ scheduleRestart();
13150
+ return;
13151
+ }
13152
+ try {
13153
+ watcher = watch3(targetPath, { recursive }, (_eventType, filename) => {
13154
+ onChange(filename);
13155
+ });
13156
+ watcher.on("error", handleWatchError);
13157
+ } catch (error3) {
13158
+ handleWatchError(error3);
13159
+ }
13160
+ };
13161
+ start();
13162
+ return {
13163
+ close() {
13164
+ closed = true;
13165
+ if (retryTimer) {
13166
+ clearTimeout(retryTimer);
13167
+ retryTimer = null;
13168
+ }
13169
+ watcher?.close();
13170
+ watcher = null;
13171
+ }
13172
+ };
13173
+ }
13174
+ var RuntimeManager = class {
13175
+ runtimes = /* @__PURE__ */ new Map();
13176
+ async startRuntime(flintPath) {
13177
+ const resolved = await resolveFlintPath4(flintPath);
13178
+ const runtimeId = computeRuntimeId(resolved);
13179
+ const existing = this.runtimes.get(runtimeId);
13180
+ if (existing) {
13181
+ return existing.getStatus();
13182
+ }
13183
+ const runtime2 = createRuntime({ flintPath: resolved });
13184
+ await runtime2.start();
13185
+ this.runtimes.set(runtimeId, runtime2);
13186
+ return runtime2.getStatus();
13187
+ }
13188
+ listRuntimes() {
13189
+ return Array.from(this.runtimes.values()).map((runtime2) => runtime2.getStatus());
13190
+ }
13191
+ getRuntime(id) {
13192
+ return this.runtimes.get(id);
13193
+ }
13194
+ async stopRuntime(id) {
13195
+ const runtime2 = this.runtimes.get(id);
13196
+ if (!runtime2) {
13197
+ return false;
13198
+ }
13199
+ await runtime2.stop();
13200
+ this.runtimes.delete(id);
13201
+ return true;
13202
+ }
13203
+ async stopAll() {
13204
+ const entries = Array.from(this.runtimes.entries());
13205
+ await Promise.all(entries.map(async ([id, runtime2]) => {
13206
+ await runtime2.stop();
13207
+ this.runtimes.delete(id);
13208
+ }));
13209
+ }
13210
+ };
13211
+ var REGISTRY_PATH = join11(homedir6(), ".nuucognition", "servers.json");
13212
+ function getRegistryDir() {
13213
+ return join11(homedir6(), ".nuucognition");
13214
+ }
13215
+ async function readServerRegistry() {
13216
+ try {
13217
+ const content = await readFile22(REGISTRY_PATH, "utf-8");
13218
+ const data = JSON.parse(content);
13219
+ return data.servers ?? [];
13220
+ } catch (error3) {
13221
+ if (error3.code === "ENOENT") {
13222
+ return [];
13223
+ }
13224
+ return [];
13225
+ }
13226
+ }
13227
+ async function writeServerRegistry(servers) {
13228
+ await mkdir5(getRegistryDir(), { recursive: true });
13229
+ const data = { version: 1, servers };
13230
+ const content = JSON.stringify(data, null, 2);
10964
13231
  await writeFile3(REGISTRY_PATH, content, "utf-8");
10965
- const verification = await readFile6(REGISTRY_PATH, "utf-8");
13232
+ const verification = await readFile22(REGISTRY_PATH, "utf-8");
10966
13233
  const verified = JSON.parse(verification);
10967
13234
  if (verified.servers.length !== servers.length) {
10968
13235
  await writeFile3(REGISTRY_PATH, content, "utf-8");
@@ -11092,26 +13359,39 @@ function registerPlatesRoutes(app, ctx) {
11092
13359
  ...id ? { id } : {}
11093
13360
  });
11094
13361
  }
13362
+ function toPlateSummary(plate) {
13363
+ return {
13364
+ name: plate.manifest.name,
13365
+ title: plate.manifest.title,
13366
+ version: plate.manifest.version ?? "0.1.0",
13367
+ description: plate.manifest.description,
13368
+ icon: plate.manifest.icon,
13369
+ shard: plate.manifest.shard,
13370
+ handles: (plate.manifest.handles ?? []).map((handle) => ({
13371
+ tag: handle.tag,
13372
+ default: handle.default === true
13373
+ })),
13374
+ actions: (plate.manifest.actions ?? []).map((action) => ({
13375
+ id: action.id,
13376
+ label: action.label,
13377
+ description: action.description,
13378
+ icon: action.icon
13379
+ })),
13380
+ built: plate.built,
13381
+ stale: plate.stale,
13382
+ tools: (plate.manifest.tools ?? []).map((tool) => ({
13383
+ name: tool.name,
13384
+ description: tool.description
13385
+ }))
13386
+ };
13387
+ }
11095
13388
  app.get("/api/plates", async (_request, reply) => {
11096
13389
  if (!ctx.flintPath) {
11097
13390
  return sendApiError(reply, 500, "not_found", "No Flint workspace configured");
11098
13391
  }
11099
13392
  try {
11100
13393
  const plates = await listPlates(ctx.flintPath);
11101
- return plates.map((plate) => ({
11102
- name: plate.manifest.name,
11103
- title: plate.manifest.title,
11104
- version: plate.manifest.version ?? "0.1.0",
11105
- description: plate.manifest.description,
11106
- icon: plate.manifest.icon,
11107
- shard: plate.manifest.shard,
11108
- built: plate.built,
11109
- stale: plate.stale,
11110
- tools: (plate.manifest.tools ?? []).map((tool) => ({
11111
- name: tool.name,
11112
- description: tool.description
11113
- }))
11114
- }));
13394
+ return plates.map((plate) => toPlateSummary(plate));
11115
13395
  } catch (error3) {
11116
13396
  const message = error3 instanceof Error ? error3.message : String(error3);
11117
13397
  return sendApiError(reply, 500, "validation_error", message);
@@ -11125,20 +13405,7 @@ function registerPlatesRoutes(app, ctx) {
11125
13405
  if (!plate) {
11126
13406
  return sendApiError(reply, 404, "not_found", `Plate "${request.params.name}" was not found`);
11127
13407
  }
11128
- return {
11129
- name: plate.manifest.name,
11130
- title: plate.manifest.title,
11131
- version: plate.manifest.version ?? "0.1.0",
11132
- description: plate.manifest.description,
11133
- icon: plate.manifest.icon,
11134
- shard: plate.manifest.shard,
11135
- built: plate.built,
11136
- stale: plate.stale,
11137
- tools: (plate.manifest.tools ?? []).map((tool) => ({
11138
- name: tool.name,
11139
- description: tool.description
11140
- }))
11141
- };
13408
+ return toPlateSummary(plate);
11142
13409
  });
11143
13410
  async function servePlateAsset(plateName, requestedPath, reply) {
11144
13411
  if (!ctx.flintPath) {
@@ -11148,18 +13415,18 @@ function registerPlatesRoutes(app, ctx) {
11148
13415
  if (!plate) {
11149
13416
  return sendApiError(reply, 404, "not_found", `Plate "${plateName}" was not found`);
11150
13417
  }
11151
- const entryPath = path22.resolve(plate.path, plate.manifest.entry);
11152
- const distRoot = path22.dirname(entryPath);
11153
- if (!await stat22(distRoot).catch(() => null)) {
13418
+ const entryPath = path32.resolve(plate.path, plate.manifest.entry);
13419
+ const distRoot = path32.dirname(entryPath);
13420
+ if (!await stat32(distRoot).catch(() => null)) {
11154
13421
  return sendApiError(reply, 404, "plate_not_built", `Plate "${plate.manifest.name}" has not been built`, {
11155
13422
  plate: plate.manifest.name
11156
13423
  });
11157
13424
  }
11158
- const targetPath = requestedPath && requestedPath.length > 0 ? path22.resolve(distRoot, requestedPath) : entryPath;
11159
- if (!targetPath.startsWith(distRoot) || !await stat22(targetPath).catch(() => null)) {
13425
+ const targetPath = requestedPath && requestedPath.length > 0 ? path32.resolve(distRoot, requestedPath) : entryPath;
13426
+ if (!targetPath.startsWith(distRoot) || !await stat32(targetPath).catch(() => null)) {
11160
13427
  return sendApiError(reply, 404, "not_found", `Asset "${requestedPath ?? "/"}" was not found`);
11161
13428
  }
11162
- const content = await readFile22(targetPath);
13429
+ const content = await readFile32(targetPath);
11163
13430
  reply.header("Content-Type", contentTypeFor(targetPath));
11164
13431
  reply.header("Cache-Control", isImmutableAsset(targetPath) ? "public, max-age=31536000, immutable" : "no-store");
11165
13432
  return reply.send(content);
@@ -11237,7 +13504,7 @@ function registerPlatesRoutes(app, ctx) {
11237
13504
  template: request.body.template,
11238
13505
  data: request.body.data
11239
13506
  });
11240
- const absolutePath = path22.join(ctx.flintPath, artifact.path);
13507
+ const absolutePath = path32.join(ctx.flintPath, artifact.path);
11241
13508
  suppressPath(absolutePath);
11242
13509
  trackArtifactPath(absolutePath);
11243
13510
  broadcastArtifactEvent("artifact.created", artifact);
@@ -11260,7 +13527,7 @@ function registerPlatesRoutes(app, ctx) {
11260
13527
  if (!artifact) {
11261
13528
  return sendApiError(reply, 404, "not_found", `Artifact "${request.params.id}" was not found`);
11262
13529
  }
11263
- trackArtifactPath(path22.join(ctx.flintPath, artifact.path));
13530
+ trackArtifactPath(path32.join(ctx.flintPath, artifact.path));
11264
13531
  broadcastArtifactEvent("artifact.updated", artifact);
11265
13532
  return artifact;
11266
13533
  });
@@ -11302,7 +13569,7 @@ function registerPlatesRoutes(app, ctx) {
11302
13569
  return sendApiError(reply, 404, "not_found", `Artifact "${request.params.id}" was not found`);
11303
13570
  }
11304
13571
  if (ctx.flintPath) {
11305
- const newPath = path22.join(ctx.flintPath, result.artifact.path);
13572
+ const newPath = path32.join(ctx.flintPath, result.artifact.path);
11306
13573
  suppressPath(newPath);
11307
13574
  trackArtifactPath(newPath);
11308
13575
  }
@@ -11361,13 +13628,13 @@ function registerPlatesRoutes(app, ctx) {
11361
13628
  const fileDebounceTimers = /* @__PURE__ */ new Map();
11362
13629
  const SKIP_DIRS = /* @__PURE__ */ new Set(["Agents", "Archive", "node_modules", ".git"]);
11363
13630
  function shouldSkipPath(relativePath) {
11364
- const parts = relativePath.split(path22.sep);
13631
+ const parts = relativePath.split(path32.sep);
11365
13632
  return parts.some((p) => SKIP_DIRS.has(p));
11366
13633
  }
11367
13634
  const handleFileChange = (baseDir, filename) => {
11368
13635
  if (!filename || !ctx.flintPath) return;
11369
13636
  if (!filename.endsWith(".md")) return;
11370
- const absolutePath = path22.join(baseDir, filename);
13637
+ const absolutePath = path32.join(baseDir, filename);
11371
13638
  if (shouldSkipPath(filename)) return;
11372
13639
  if (suppressedPaths.has(absolutePath)) return;
11373
13640
  const existing = fileDebounceTimers.get(absolutePath);
@@ -11383,7 +13650,7 @@ function registerPlatesRoutes(app, ctx) {
11383
13650
  trackArtifactPath(absolutePath);
11384
13651
  broadcastArtifactEvent(event, artifact);
11385
13652
  } else {
11386
- const relPath = path22.relative(ctx.flintPath, absolutePath).replace(/\\/g, "/");
13653
+ const relPath = path32.relative(ctx.flintPath, absolutePath).replace(/\\/g, "/");
11387
13654
  untrackArtifactPath(absolutePath);
11388
13655
  broadcastArtifactDeletion(relPath);
11389
13656
  }
@@ -11392,11 +13659,11 @@ function registerPlatesRoutes(app, ctx) {
11392
13659
  }, 50));
11393
13660
  };
11394
13661
  if (ctx.flintPath) {
11395
- const meshDir = path22.join(ctx.flintPath, "Mesh");
11396
- const shardsDir = path22.join(ctx.flintPath, "Shards");
13662
+ const meshDir = path32.join(ctx.flintPath, "Mesh");
13663
+ const shardsDir = path32.join(ctx.flintPath, "Shards");
11397
13664
  void queryArtifacts(ctx.flintPath, { includeShards: true, limit: 1e4 }).then((result) => {
11398
13665
  for (const artifact of result.items) {
11399
- trackArtifactPath(path22.join(ctx.flintPath, artifact.path));
13666
+ trackArtifactPath(path32.join(ctx.flintPath, artifact.path));
11400
13667
  }
11401
13668
  }).catch(() => {
11402
13669
  });
@@ -11522,7 +13789,7 @@ async function readSessionTranscript(session, cwd) {
11522
13789
  if (!transcriptPath) {
11523
13790
  return { entries: [], turns: [], usage: null };
11524
13791
  }
11525
- const content = await readFile32(transcriptPath, "utf-8").catch(() => null);
13792
+ const content = await readFile42(transcriptPath, "utf-8").catch(() => null);
11526
13793
  if (content == null) {
11527
13794
  return { entries: [], turns: [], usage: null };
11528
13795
  }
@@ -11817,11 +14084,12 @@ function registerOrbhRoutes(app, ctx, options) {
11817
14084
  prompt: prompt6,
11818
14085
  extraArgs: session.runtime === "claude" ? ["--chrome"] : []
11819
14086
  });
11820
- const child = spawn5(harness.name, args, {
14087
+ const child = spawn22(harness.name, args, {
11821
14088
  cwd: ctx.flintPath,
11822
14089
  detached: true,
11823
14090
  stdio: ["ignore", "ignore", "pipe"],
11824
- env: buildHarnessSpawnEnv(ctx.flintPath, session.id)
14091
+ env: buildHarnessSpawnEnv(ctx.flintPath, session.id),
14092
+ shell: process.platform === "win32"
11825
14093
  });
11826
14094
  let stderr = "";
11827
14095
  child.stderr?.on("data", (chunk) => {
@@ -12233,7 +14501,7 @@ async function buildFlintIdentity(ctx) {
12233
14501
  ]);
12234
14502
  const sessions = ctx.orbhSessionsDir ? listSessions2(ctx.orbhSessionsDir) : [];
12235
14503
  const activeSessions = sessions.filter((session) => ACTIVE_SESSION_STATUSES.has(session.status)).length;
12236
- const name = config?.flint?.name ?? registryEntry?.name ?? path32.basename(ctx.flintPath);
14504
+ const name = config?.flint?.name ?? registryEntry?.name ?? path42.basename(ctx.flintPath);
12237
14505
  return {
12238
14506
  name,
12239
14507
  flintId: flintJson?.id ?? null,
@@ -12290,12 +14558,12 @@ function registerWorkspaceRoutes(app, ctx) {
12290
14558
  return;
12291
14559
  }
12292
14560
  for (const entry of entries) {
12293
- const fullPath = path4.join(dir, entry.name);
14561
+ const fullPath = path5.join(dir, entry.name);
12294
14562
  if (entry.isDirectory()) {
12295
14563
  if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist") continue;
12296
14564
  await walk(fullPath);
12297
14565
  } else if (entry.name.endsWith(".md")) {
12298
- allFiles.push(path4.relative(ctx.flintPath, fullPath));
14566
+ allFiles.push(path5.relative(ctx.flintPath, fullPath));
12299
14567
  }
12300
14568
  }
12301
14569
  }
@@ -12449,16 +14717,16 @@ function registerShardsRoutes(app, ctx) {
12449
14717
  return sendApiError(reply, 500, "no_workspace", "No Flint workspace configured");
12450
14718
  }
12451
14719
  const installed = await getInstalledShardsWithVersions(ctx.flintPath);
12452
- const match = resolveInstalledShardInfo(installed, request.params.identifier);
12453
- if (!match) {
14720
+ const match2 = resolveInstalledShardInfo(installed, request.params.identifier);
14721
+ if (!match2) {
12454
14722
  return sendApiError(reply, 404, "not_found", `Shard "${request.params.identifier}" not found`);
12455
14723
  }
12456
14724
  const allResults = await checkShardHealth(ctx.flintPath);
12457
14725
  const shardResults = allResults.filter(
12458
- (r) => r.check.includes(match.folderName) || r.check.includes(match.name)
14726
+ (r) => r.check.includes(match2.folderName) || r.check.includes(match2.name)
12459
14727
  );
12460
14728
  return {
12461
- shard: match.name,
14729
+ shard: match2.name,
12462
14730
  results: shardResults.map((r) => ({
12463
14731
  check: r.check,
12464
14732
  status: r.status,
@@ -12492,14 +14760,14 @@ function registerShardsRoutes(app, ctx) {
12492
14760
  return sendApiError(reply, 500, "no_workspace", "No Flint workspace configured");
12493
14761
  }
12494
14762
  const installed = await getInstalledShardsWithVersions(ctx.flintPath);
12495
- const match = resolveInstalledShardInfo(installed, request.params.identifier);
12496
- if (!match) {
14763
+ const match2 = resolveInstalledShardInfo(installed, request.params.identifier);
14764
+ if (!match2) {
12497
14765
  return sendApiError(reply, 404, "not_found", `Shard "${request.params.identifier}" not found`);
12498
14766
  }
12499
14767
  try {
12500
- const results = await healShard(ctx.flintPath, match.folderName);
14768
+ const results = await healShard(ctx.flintPath, match2.folderName);
12501
14769
  return {
12502
- shard: match.name,
14770
+ shard: match2.name,
12503
14771
  repairs: results.map((r) => ({
12504
14772
  check: r.check,
12505
14773
  status: r.status,
@@ -12533,6 +14801,152 @@ function registerShardsRoutes(app, ctx) {
12533
14801
  }
12534
14802
  });
12535
14803
  }
14804
+ function steelDir(flintPath) {
14805
+ return path6.join(flintPath, ".steel");
14806
+ }
14807
+ function preferencesPath(flintPath) {
14808
+ return path6.join(steelDir(flintPath), "preferences.json");
14809
+ }
14810
+ function plateStateDir(flintPath, plateName) {
14811
+ return path6.join(steelDir(flintPath), "plates", plateName);
14812
+ }
14813
+ function plateStatePath(flintPath, plateName, key) {
14814
+ return path6.join(plateStateDir(flintPath, plateName), `${key}.json`);
14815
+ }
14816
+ function plateBoardsDir(flintPath, plateName) {
14817
+ return path6.join(plateStateDir(flintPath, plateName), "boards");
14818
+ }
14819
+ function plateBoardPath(flintPath, plateName, board) {
14820
+ return path6.join(plateBoardsDir(flintPath, plateName), `${board}.json`);
14821
+ }
14822
+ async function readJsonFile(filePath) {
14823
+ try {
14824
+ const raw = await readFile52(filePath, "utf-8");
14825
+ return JSON.parse(raw);
14826
+ } catch {
14827
+ return null;
14828
+ }
14829
+ }
14830
+ async function writeJsonFile(filePath, data) {
14831
+ await mkdir22(path6.dirname(filePath), { recursive: true });
14832
+ const tempPath = `${filePath}.tmp-${process.pid}-${Date.now()}`;
14833
+ await writeFile22(tempPath, JSON.stringify(data, null, 2), "utf-8");
14834
+ await rename2(tempPath, filePath);
14835
+ }
14836
+ function registerSteelRoutes(app, ctx) {
14837
+ app.get("/api/steel/preferences", async (_request, reply) => {
14838
+ if (!ctx.flintPath) {
14839
+ return sendApiError(reply, 500, "no_workspace", "No Flint workspace configured");
14840
+ }
14841
+ const prefs = await readJsonFile(preferencesPath(ctx.flintPath));
14842
+ return prefs ?? {};
14843
+ });
14844
+ app.put("/api/steel/preferences", async (request, reply) => {
14845
+ if (!ctx.flintPath) {
14846
+ return sendApiError(reply, 500, "no_workspace", "No Flint workspace configured");
14847
+ }
14848
+ const body = request.body;
14849
+ await writeJsonFile(preferencesPath(ctx.flintPath), {
14850
+ ...body,
14851
+ updated: (/* @__PURE__ */ new Date()).toISOString()
14852
+ });
14853
+ return { ok: true };
14854
+ });
14855
+ app.get(
14856
+ "/api/steel/plates/:name/state/:key",
14857
+ async (request, reply) => {
14858
+ if (!ctx.flintPath) {
14859
+ return sendApiError(reply, 500, "no_workspace", "No Flint workspace configured");
14860
+ }
14861
+ const { name, key } = request.params;
14862
+ const data = await readJsonFile(plateStatePath(ctx.flintPath, name, key));
14863
+ return data ?? {};
14864
+ }
14865
+ );
14866
+ app.put(
14867
+ "/api/steel/plates/:name/state/:key",
14868
+ async (request, reply) => {
14869
+ if (!ctx.flintPath) {
14870
+ return sendApiError(reply, 500, "no_workspace", "No Flint workspace configured");
14871
+ }
14872
+ const { name, key } = request.params;
14873
+ const body = request.body;
14874
+ await writeJsonFile(plateStatePath(ctx.flintPath, name, key), {
14875
+ ...body,
14876
+ updated: (/* @__PURE__ */ new Date()).toISOString()
14877
+ });
14878
+ return { ok: true };
14879
+ }
14880
+ );
14881
+ app.get(
14882
+ "/api/steel/plates/:name/state",
14883
+ async (request, reply) => {
14884
+ if (!ctx.flintPath) {
14885
+ return sendApiError(reply, 500, "no_workspace", "No Flint workspace configured");
14886
+ }
14887
+ const { name } = request.params;
14888
+ const dir = plateStateDir(ctx.flintPath, name);
14889
+ if (!await exists3(dir)) return {};
14890
+ const entries = {};
14891
+ try {
14892
+ const files = await readdir3(dir, { withFileTypes: true });
14893
+ for (const file of files) {
14894
+ if (!file.isFile() || !file.name.endsWith(".json")) continue;
14895
+ const key = file.name.replace(/\.json$/, "");
14896
+ entries[key] = await readJsonFile(path6.join(dir, file.name));
14897
+ }
14898
+ } catch {
14899
+ }
14900
+ return entries;
14901
+ }
14902
+ );
14903
+ app.get(
14904
+ "/api/steel/plates/:name/boards",
14905
+ async (request, reply) => {
14906
+ if (!ctx.flintPath) {
14907
+ return sendApiError(reply, 500, "no_workspace", "No Flint workspace configured");
14908
+ }
14909
+ const { name } = request.params;
14910
+ const dir = plateBoardsDir(ctx.flintPath, name);
14911
+ if (!await exists3(dir)) return [];
14912
+ try {
14913
+ const files = await readdir3(dir);
14914
+ return files.filter((f) => f.endsWith(".json")).map((f) => f.replace(/\.json$/, ""));
14915
+ } catch {
14916
+ return [];
14917
+ }
14918
+ }
14919
+ );
14920
+ app.get(
14921
+ "/api/steel/plates/:name/boards/:board",
14922
+ async (request, reply) => {
14923
+ if (!ctx.flintPath) {
14924
+ return sendApiError(reply, 500, "no_workspace", "No Flint workspace configured");
14925
+ }
14926
+ const { name, board } = request.params;
14927
+ const data = await readJsonFile(plateBoardPath(ctx.flintPath, name, board));
14928
+ if (!data) {
14929
+ return sendApiError(reply, 404, "not_found", `Board config '${board}' not found for plate '${name}'`);
14930
+ }
14931
+ return data;
14932
+ }
14933
+ );
14934
+ app.put(
14935
+ "/api/steel/plates/:name/boards/:board",
14936
+ async (request, reply) => {
14937
+ if (!ctx.flintPath) {
14938
+ return sendApiError(reply, 500, "no_workspace", "No Flint workspace configured");
14939
+ }
14940
+ const { name, board } = request.params;
14941
+ const body = request.body;
14942
+ await writeJsonFile(plateBoardPath(ctx.flintPath, name, board), {
14943
+ ...body,
14944
+ updated: (/* @__PURE__ */ new Date()).toISOString()
14945
+ });
14946
+ return { ok: true };
14947
+ }
14948
+ );
14949
+ }
12536
14950
  var MAX_ENTRIES = 1e3;
12537
14951
  var nextId = 1;
12538
14952
  var buffer = [];
@@ -12542,29 +14956,29 @@ function pushEntry(entry) {
12542
14956
  }
12543
14957
  buffer.push(entry);
12544
14958
  }
12545
- function getLogEntries(filter) {
14959
+ function getLogEntries(filter2) {
12546
14960
  let result = buffer;
12547
- if (filter?.method) {
12548
- const method = filter.method.toUpperCase();
14961
+ if (filter2?.method) {
14962
+ const method = filter2.method.toUpperCase();
12549
14963
  result = result.filter((entry) => entry.method === method);
12550
14964
  }
12551
- if (filter?.minStatus != null) {
12552
- const minStatus = filter.minStatus;
14965
+ if (filter2?.minStatus != null) {
14966
+ const minStatus = filter2.minStatus;
12553
14967
  result = result.filter((entry) => entry.statusCode >= minStatus);
12554
14968
  }
12555
- if (filter?.maxStatus != null) {
12556
- const maxStatus = filter.maxStatus;
14969
+ if (filter2?.maxStatus != null) {
14970
+ const maxStatus = filter2.maxStatus;
12557
14971
  result = result.filter((entry) => entry.statusCode <= maxStatus);
12558
14972
  }
12559
- if (filter?.pathPattern) {
12560
- const pattern = filter.pathPattern.toLowerCase();
14973
+ if (filter2?.pathPattern) {
14974
+ const pattern = filter2.pathPattern.toLowerCase();
12561
14975
  result = result.filter((entry) => entry.path.toLowerCase().includes(pattern));
12562
14976
  }
12563
- if (filter?.since) {
12564
- result = result.filter((entry) => entry.timestamp >= filter.since);
14977
+ if (filter2?.since) {
14978
+ result = result.filter((entry) => entry.timestamp >= filter2.since);
12565
14979
  }
12566
- if (filter?.limit && filter.limit > 0) {
12567
- result = result.slice(-filter.limit);
14980
+ if (filter2?.limit && filter2.limit > 0) {
14981
+ result = result.slice(-filter2.limit);
12568
14982
  }
12569
14983
  return result;
12570
14984
  }
@@ -12573,8 +14987,8 @@ var EXCLUDED_PATHS = [
12573
14987
  "/events/stream",
12574
14988
  "/health"
12575
14989
  ];
12576
- function shouldLog(path62) {
12577
- return !EXCLUDED_PATHS.some((entry) => path62 === entry || path62.startsWith(`${entry}?`));
14990
+ function shouldLog(path82) {
14991
+ return !EXCLUDED_PATHS.some((entry) => path82 === entry || path82.startsWith(`${entry}?`));
12578
14992
  }
12579
14993
  var INTERESTING_REQUEST_HEADERS = [
12580
14994
  "accept",
@@ -12621,14 +15035,14 @@ function registerLogsRoutes(app, ctx) {
12621
15035
  return;
12622
15036
  }
12623
15037
  const queryIndex = fullUrl.indexOf("?");
12624
- const path62 = queryIndex >= 0 ? fullUrl.slice(0, queryIndex) : fullUrl;
15038
+ const path82 = queryIndex >= 0 ? fullUrl.slice(0, queryIndex) : fullUrl;
12625
15039
  const queryString = queryIndex >= 0 ? fullUrl.slice(queryIndex + 1) : null;
12626
15040
  const entry = {
12627
15041
  id: nextId++,
12628
15042
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
12629
15043
  method: request.method,
12630
15044
  url: fullUrl,
12631
- path: path62,
15045
+ path: path82,
12632
15046
  queryString,
12633
15047
  statusCode: reply.statusCode,
12634
15048
  responseTimeMs: Math.round(reply.elapsedTime * 100) / 100,
@@ -12899,7 +15313,7 @@ function registerEventStreamRoutes(app, ctx) {
12899
15313
  const raw = reply.raw;
12900
15314
  raw.writeHead(200, buildSseHeaders(request));
12901
15315
  const subscriber = {
12902
- id: randomUUID3(),
15316
+ id: randomUUID22(),
12903
15317
  raw,
12904
15318
  channels: new Set(channels),
12905
15319
  sessionIds,
@@ -13020,17 +15434,17 @@ var LiveTranscriptWriter = class {
13020
15434
  const agentsDir = join33(this.flintPath, "Mesh", "Agents");
13021
15435
  let runtimeDirs;
13022
15436
  try {
13023
- runtimeDirs = await readdir3(agentsDir);
15437
+ runtimeDirs = await readdir4(agentsDir);
13024
15438
  } catch {
13025
15439
  return;
13026
15440
  }
13027
15441
  for (const dir of runtimeDirs) {
13028
15442
  const dirPath = join33(agentsDir, dir);
13029
- const dirStat = await stat32(dirPath).catch(() => null);
15443
+ const dirStat = await stat42(dirPath).catch(() => null);
13030
15444
  if (!dirStat?.isDirectory()) continue;
13031
15445
  let files;
13032
15446
  try {
13033
- files = await readdir3(dirPath);
15447
+ files = await readdir4(dirPath);
13034
15448
  } catch {
13035
15449
  continue;
13036
15450
  }
@@ -13039,7 +15453,7 @@ var LiveTranscriptWriter = class {
13039
15453
  const filePath = join33(dirPath, file);
13040
15454
  let content;
13041
15455
  try {
13042
- content = await readFile42(filePath, "utf-8");
15456
+ content = await readFile62(filePath, "utf-8");
13043
15457
  } catch {
13044
15458
  continue;
13045
15459
  }
@@ -13057,7 +15471,7 @@ var LiveTranscriptWriter = class {
13057
15471
  const finalStatus = session?.status ?? "unknown";
13058
15472
  const statusUpdated = updatedContent.replace(/^status: .+$/m, `status: ${finalStatus}`);
13059
15473
  this.suppress(filePath);
13060
- await writeFile22(filePath, statusUpdated, "utf-8").catch(() => {
15474
+ await writeFile32(filePath, statusUpdated, "utf-8").catch(() => {
13061
15475
  });
13062
15476
  console.log(`[flint-server] finalized orphaned live transcript: ${file}`);
13063
15477
  }
@@ -13108,12 +15522,12 @@ var LiveTranscriptWriter = class {
13108
15522
  const outputDir = join33(this.flintPath, "Mesh", "Agents", dir);
13109
15523
  const outputPath = join33(outputDir, `${sessionId}.md`);
13110
15524
  try {
13111
- await mkdir22(outputDir, { recursive: true });
15525
+ await mkdir32(outputDir, { recursive: true });
13112
15526
  const frontmatter = buildLiveFrontmatter(session, live);
13113
15527
  const body = formatTranscriptMarkdown(entries);
13114
15528
  const markdown = frontmatter + body;
13115
15529
  this.suppress(outputPath);
13116
- await writeFile22(outputPath, markdown, "utf-8");
15530
+ await writeFile32(outputPath, markdown, "utf-8");
13117
15531
  this.writtenPaths.add(outputPath);
13118
15532
  } catch (error3) {
13119
15533
  console.warn(
@@ -13159,9 +15573,9 @@ async function shutdownPairedSteelHost(steelUrl) {
13159
15573
  async function startFlintServer(options = {}) {
13160
15574
  const host = "127.0.0.1";
13161
15575
  const port = options.port ?? 13040;
13162
- const flintPath = options.flintPath ? path5.resolve(options.flintPath) : void 0;
15576
+ const flintPath = options.flintPath ? path7.resolve(options.flintPath) : void 0;
13163
15577
  const runtimeManager = new RuntimeManager();
13164
- const orbhSessionsDir = flintPath ? path5.join(flintPath, ".flint", "sessions") : null;
15578
+ const orbhSessionsDir = flintPath ? path7.join(flintPath, ".flint", "sessions") : null;
13165
15579
  const channelRegistry = new ChannelRegistry();
13166
15580
  const app = Fastify({
13167
15581
  logger: options.logger ?? false,
@@ -13185,10 +15599,10 @@ async function startFlintServer(options = {}) {
13185
15599
  suppressedPaths,
13186
15600
  suppressPath
13187
15601
  };
13188
- const __dirname4 = path5.dirname(fileURLToPath2(import.meta.url));
13189
- const dashboardDist = path5.resolve(__dirname4, "..", "..", "..", "apps", "flint-dashboard", "dist");
15602
+ const __dirname4 = path7.dirname(fileURLToPath2(import.meta.url));
15603
+ const dashboardDist = path7.resolve(__dirname4, "..", "..", "..", "apps", "flint-dashboard", "dist");
13190
15604
  try {
13191
- await stat4(dashboardDist);
15605
+ await stat5(dashboardDist);
13192
15606
  await app.register(fastifyStatic, {
13193
15607
  root: dashboardDist,
13194
15608
  prefix: "/",
@@ -13218,6 +15632,7 @@ async function startFlintServer(options = {}) {
13218
15632
  registerIdentityRoutes(app, ctx);
13219
15633
  registerDashboardRoutes(app, ctx);
13220
15634
  registerShardsRoutes(app, ctx);
15635
+ registerSteelRoutes(app, ctx);
13221
15636
  registerWorkspaceRoutes(app, ctx);
13222
15637
  let liveTranscriptWriter = null;
13223
15638
  if (flintPath) {
@@ -13254,7 +15669,7 @@ async function startFlintServer(options = {}) {
13254
15669
  readFlintToml(flintPath)
13255
15670
  ]);
13256
15671
  registryFlintId = flintJson?.id ?? null;
13257
- registryName = config?.flint?.name ?? path5.basename(flintPath);
15672
+ registryName = config?.flint?.name ?? path7.basename(flintPath);
13258
15673
  } catch {
13259
15674
  }
13260
15675
  await registerServer({
@@ -13275,7 +15690,7 @@ async function startFlintServer(options = {}) {
13275
15690
  console.log(`[flint-server] ${needsBuild.length} plate(s) need building...`);
13276
15691
  for (const plate of needsBuild) {
13277
15692
  try {
13278
- const nodeModulesExists = await stat4(join43(plate.path, "node_modules")).then(() => true, () => false);
15693
+ const nodeModulesExists = await stat5(join43(plate.path, "node_modules")).then(() => true, () => false);
13279
15694
  if (!nodeModulesExists) {
13280
15695
  console.log(`[flint-server] installing deps for ${plate.manifest.title}...`);
13281
15696
  const installResult = await installPlateDeps(flintPath, plate.manifest.name);
@@ -13413,12 +15828,12 @@ serverCommand.command("dev").description("Start the server in dev mode with auto
13413
15828
  let serverPkgDir;
13414
15829
  try {
13415
15830
  const serverPkgJson = require2.resolve(`${FLINT_SERVER_PACKAGE}/package.json`);
13416
- serverPkgDir = path6.dirname(serverPkgJson);
15831
+ serverPkgDir = path8.dirname(serverPkgJson);
13417
15832
  } catch {
13418
15833
  console.error(pc25.red("Error: flint-server package not found."));
13419
15834
  process.exit(1);
13420
15835
  }
13421
- const devEntry = path6.join(serverPkgDir, "src", "dev.ts");
15836
+ const devEntry = path8.join(serverPkgDir, "src", "dev.ts");
13422
15837
  try {
13423
15838
  await stat6(devEntry);
13424
15839
  } catch {
@@ -13536,11 +15951,11 @@ serverCommand.command("list").description("List all running Flint servers from t
13536
15951
  // src/commands/runtime.ts
13537
15952
  import { Command as Command23 } from "commander";
13538
15953
  import pc26 from "picocolors";
13539
- import path7 from "path";
15954
+ import path9 from "path";
13540
15955
  var runtimeCommand = new Command23("runtime").description("Manage Flint runtimes");
13541
15956
  runtimeCommand.command("start [flintPath]").description("Start runtime for a Flint").option("--server <url>", "Server URL", "http://127.0.0.1:13040").action(async (flintPath, options) => {
13542
15957
  const serverUrl = options.server;
13543
- const resolvedPath = flintPath ? path7.resolve(flintPath) : await findFlintRoot(process.cwd());
15958
+ const resolvedPath = flintPath ? path9.resolve(flintPath) : await findFlintRoot(process.cwd());
13544
15959
  if (!resolvedPath) {
13545
15960
  console.error(pc26.red("Error: Not inside a Flint workspace. Provide a path or cd into one."));
13546
15961
  process.exit(1);
@@ -13572,7 +15987,7 @@ runtimeCommand.command("stop [runtimeId]").description("Stop a running runtime")
13572
15987
  let id = runtimeId;
13573
15988
  try {
13574
15989
  if (!id) {
13575
- const lookupPath = options.path ? path7.resolve(options.path) : await findFlintRoot(process.cwd());
15990
+ const lookupPath = options.path ? path9.resolve(options.path) : await findFlintRoot(process.cwd());
13576
15991
  if (!lookupPath) {
13577
15992
  console.error(pc26.red("Error: Provide a runtime ID or Flint path."));
13578
15993
  process.exit(1);
@@ -13583,10 +15998,10 @@ runtimeCommand.command("stop [runtimeId]").description("Stop a running runtime")
13583
15998
  process.exit(1);
13584
15999
  }
13585
16000
  const payload = await listResponse.json();
13586
- const match = (payload.runtimes ?? []).find(
16001
+ const match2 = (payload.runtimes ?? []).find(
13587
16002
  (runtime2) => runtime2.flintPath === lookupPath
13588
16003
  );
13589
- id = match?.id;
16004
+ id = match2?.id;
13590
16005
  }
13591
16006
  if (!id) {
13592
16007
  console.error(pc26.red("Error: Runtime not found."));
@@ -13706,23 +16121,23 @@ async function exportSession(flintPath, sessionId) {
13706
16121
  }
13707
16122
 
13708
16123
  // src/commands/export-codex-session.ts
13709
- import { writeFile as writeFile5, mkdir as mkdir7, readFile as readFile8, readdir as readdir4, stat as stat8 } from "fs/promises";
16124
+ import { writeFile as writeFile5, mkdir as mkdir7, readFile as readFile8, readdir as readdir5, stat as stat8 } from "fs/promises";
13710
16125
  import { join as join13 } from "path";
13711
16126
  import { homedir as homedir8 } from "os";
13712
16127
  import pc28 from "picocolors";
13713
16128
  async function findCodexTranscript(sessionId, startedAfter) {
13714
16129
  const sessionsDir = join13(homedir8(), ".codex", "sessions");
13715
16130
  try {
13716
- const years = await readdir4(sessionsDir);
16131
+ const years = await readdir5(sessionsDir);
13717
16132
  for (const year of years.reverse()) {
13718
16133
  const yearDir = join13(sessionsDir, year);
13719
- const months = await readdir4(yearDir).catch(() => []);
16134
+ const months = await readdir5(yearDir).catch(() => []);
13720
16135
  for (const month of months.reverse()) {
13721
16136
  const monthDir = join13(yearDir, month);
13722
- const days = await readdir4(monthDir).catch(() => []);
16137
+ const days = await readdir5(monthDir).catch(() => []);
13723
16138
  for (const day of days.reverse()) {
13724
16139
  const dayDir = join13(monthDir, day);
13725
- const files = await readdir4(dayDir).catch(() => []);
16140
+ const files = await readdir5(dayDir).catch(() => []);
13726
16141
  for (const file of files) {
13727
16142
  if (!file.endsWith(".jsonl")) continue;
13728
16143
  if (file.includes(sessionId)) {
@@ -13871,7 +16286,8 @@ async function bootstrapCodexSession(cwd, initPrompt) {
13871
16286
  return new Promise((resolve12, reject) => {
13872
16287
  const proc = spawn7("codex", ["app-server"], {
13873
16288
  stdio: ["pipe", "pipe", "pipe"],
13874
- cwd
16289
+ cwd,
16290
+ shell: process.platform === "win32"
13875
16291
  });
13876
16292
  const rl = createInterface5({ input: proc.stdout });
13877
16293
  const send = (msg) => proc.stdin.write(`${JSON.stringify(msg)}
@@ -13956,7 +16372,8 @@ codeCommand.command("claude").description("Open Claude Code TUI").option("-p, --
13956
16372
  }
13957
16373
  const child = spawn7("claude", args, {
13958
16374
  cwd: flintPath,
13959
- stdio: "inherit"
16375
+ stdio: "inherit",
16376
+ shell: process.platform === "win32"
13960
16377
  });
13961
16378
  child.on("error", (err) => {
13962
16379
  if (err.code === "ENOENT") {
@@ -14030,7 +16447,8 @@ codeCommand.command("codex").description("Open Codex TUI with session tracking")
14030
16447
  resumePrompt
14031
16448
  ], {
14032
16449
  cwd: flintPath,
14033
- stdio: "inherit"
16450
+ stdio: "inherit",
16451
+ shell: process.platform === "win32"
14034
16452
  });
14035
16453
  child.on("error", (err) => {
14036
16454
  console.error(pc29.red(`Error: ${err.message}`));
@@ -14124,7 +16542,8 @@ codeCommand.command("gemini").description("Open Gemini CLI with Orbh session tra
14124
16542
  const child = spawn7("gemini", args, {
14125
16543
  cwd: flintPath,
14126
16544
  stdio: "inherit",
14127
- env: { ...process.env, ORBH_SESSION_ID: session.id }
16545
+ env: { ...process.env, ORBH_SESSION_ID: session.id },
16546
+ shell: process.platform === "win32"
14128
16547
  });
14129
16548
  if (child.pid) {
14130
16549
  updateCurrentRun2(session, { pid: child.pid });
@@ -14189,8 +16608,8 @@ import { readdirSync as readdirSync6, existsSync as existsSync12, statSync as st
14189
16608
  import { join as join15, basename as basename5 } from "path";
14190
16609
  function extractNumberFromFile(filename, typeName) {
14191
16610
  const regex = new RegExp(`^\\(${typeName}\\)\\s+(\\d+)`, "i");
14192
- const match = filename.match(regex);
14193
- return match ? parseInt(match[1], 10) : null;
16611
+ const match2 = filename.match(regex);
16612
+ return match2 ? parseInt(match2[1], 10) : null;
14194
16613
  }
14195
16614
  function collectFilesRecursively(dirPath) {
14196
16615
  const files = [];
@@ -14585,9 +17004,9 @@ import pc35 from "picocolors";
14585
17004
  import { randomUUID as randomUUID5 } from "crypto";
14586
17005
  import { copyFile as copyFile2, mkdir as mkdir8, writeFile as writeFile6, unlink as unlink2, stat as stat10 } from "fs/promises";
14587
17006
  import { join as join17, basename as basename6, resolve as resolve10 } from "path";
14588
- async function exists4(path8) {
17007
+ async function exists4(path10) {
14589
17008
  try {
14590
- await stat10(path8);
17009
+ await stat10(path10);
14591
17010
  return true;
14592
17011
  } catch {
14593
17012
  return false;
@@ -14664,7 +17083,7 @@ var sendCommand = new Command30("send").description("Send files to another Flint
14664
17083
  console.log();
14665
17084
  let sourceFlintName = "Unknown";
14666
17085
  try {
14667
- const { readFlintToml: readFlintToml3 } = await import("./dist-RGQKIZQW.js");
17086
+ const { readFlintToml: readFlintToml3 } = await import("./dist-EAYA2DAP.js");
14668
17087
  const toml = await readFlintToml3(flintPath);
14669
17088
  if (toml?.flint?.name) {
14670
17089
  sourceFlintName = toml.flint.name;
@@ -14930,8 +17349,8 @@ async function validateEntries(entries) {
14930
17349
  continue;
14931
17350
  }
14932
17351
  seenPaths.set(entry.path, entry);
14933
- const exists5 = await checkPathExists(entry.path);
14934
- if (!exists5) {
17352
+ const exists6 = await checkPathExists(entry.path);
17353
+ if (!exists6) {
14935
17354
  issues.push({
14936
17355
  type: "broken_path",
14937
17356
  entry,
@@ -15383,7 +17802,7 @@ var tinderboxCommand = new Command35("tinderbox").description("Orchestrate opera
15383
17802
  // src/commands/orb.ts
15384
17803
  import { Command as Command36 } from "commander";
15385
17804
  import pc41 from "picocolors";
15386
- import { spawn as spawn8, spawnSync as spawnSync6, execSync as execSync5 } from "child_process";
17805
+ import { spawn as spawn8, spawnSync as spawnSync4, execSync as execSync5 } from "child_process";
15387
17806
  import { existsSync as existsSync14, mkdirSync as mkdirSync4, readFileSync as readFileSync10, readdirSync as readdirSync7, statSync as statSync5, writeFileSync as writeFileSync3 } from "fs";
15388
17807
  import { join as join18 } from "path";
15389
17808
  import { homedir as homedir10 } from "os";
@@ -15497,7 +17916,7 @@ function notify(title, message) {
15497
17916
  } catch {}
15498
17917
  }
15499
17918
 
15500
- const child = spawn(command, args, { cwd, stdio: ['ignore', 'ignore', 'pipe'] });
17919
+ const child = spawn(command, args, { cwd, stdio: ['ignore', 'ignore', 'pipe'], shell: process.platform === 'win32' });
15501
17920
 
15502
17921
  let stderr = '';
15503
17922
  child.stderr?.on('data', (chunk) => { stderr += chunk.toString(); });
@@ -16913,7 +19332,7 @@ orbCommand.command("ask").description("Ask a blocking question and wait for a re
16913
19332
  session.status = "blocked";
16914
19333
  writeSession(sessionsDir, session);
16915
19334
  try {
16916
- spawnSync6("osascript", ["-e", `display notification "${question.slice(0, 100)}" with title "Orbh Agent Needs Input"`], { stdio: "ignore" });
19335
+ spawnSync4("osascript", ["-e", `display notification "${question.slice(0, 100)}" with title "Orbh Agent Needs Input"`], { stdio: "ignore" });
16917
19336
  } catch {
16918
19337
  }
16919
19338
  const startTime = Date.now();
@@ -16947,7 +19366,7 @@ orbCommand.command("request").description("Post a deferred question and exit imm
16947
19366
  session.status = "deferred";
16948
19367
  writeSession(sessionsDir, session);
16949
19368
  try {
16950
- spawnSync6("osascript", ["-e", `display notification "${question.slice(0, 100)}" with title "Orbh Agent Needs Input"`], { stdio: "ignore" });
19369
+ spawnSync4("osascript", ["-e", `display notification "${question.slice(0, 100)}" with title "Orbh Agent Needs Input"`], { stdio: "ignore" });
16951
19370
  } catch {
16952
19371
  }
16953
19372
  console.log(`Question posted. Session ${shortId2(session.id)} is now deferred.`);
@@ -16983,7 +19402,7 @@ orbCommand.command("respond").description("Answer a pending question on a sessio
16983
19402
  console.log(`Response sent to session ${shortId2(session.id)}`);
16984
19403
  console.log(pc41.dim("Deferred question answered \u2014 auto-resuming session..."));
16985
19404
  const resumePrompt = `Your deferred question has been answered. Run \`flint orb requests ${session.id}\` to see the response, then continue working.`;
16986
- spawnSync6("flint", ["orb", "resume", session.id, resumePrompt], {
19405
+ spawnSync4("flint", ["orb", "resume", session.id, resumePrompt], {
16987
19406
  cwd: process.cwd(),
16988
19407
  stdio: "inherit"
16989
19408
  });
@@ -16994,14 +19413,141 @@ orbCommand.command("respond").description("Answer a pending question on a sessio
16994
19413
  }
16995
19414
  });
16996
19415
 
19416
+ // src/commands/steel.ts
19417
+ import { Command as Command37 } from "commander";
19418
+ import pc42 from "picocolors";
19419
+ import { readFile as readFile9, readdir as readdir6, rm as rm5 } from "fs/promises";
19420
+ import { join as join19 } from "path";
19421
+ async function exists5(path10) {
19422
+ try {
19423
+ const { stat: stat11 } = await import("fs/promises");
19424
+ await stat11(path10);
19425
+ return true;
19426
+ } catch {
19427
+ return false;
19428
+ }
19429
+ }
19430
+ async function readJsonFile2(filePath) {
19431
+ try {
19432
+ const raw = await readFile9(filePath, "utf-8");
19433
+ return JSON.parse(raw);
19434
+ } catch {
19435
+ return null;
19436
+ }
19437
+ }
19438
+ var steelCommand = new Command37("steel").description("Manage Steel UI state (.steel/ directory)").addCommand(
19439
+ new Command37("preferences").description("Show Steel preferences").option("-p, --path <dir>", "Path to flint (default: auto-detect)").option("--reset", "Clear all Steel preferences").action(async (options) => {
19440
+ try {
19441
+ const flintPath = options.path || await findFlintRoot(process.cwd());
19442
+ if (!flintPath) {
19443
+ console.error(pc42.red("Error: Not inside a Flint. Use --path or cd into a Flint."));
19444
+ process.exit(1);
19445
+ }
19446
+ const prefsPath = join19(flintPath, ".steel", "preferences.json");
19447
+ if (options.reset) {
19448
+ if (await exists5(prefsPath)) {
19449
+ await rm5(prefsPath);
19450
+ console.log(pc42.green("Steel preferences cleared."));
19451
+ } else {
19452
+ console.log(pc42.dim("No preferences file found."));
19453
+ }
19454
+ return;
19455
+ }
19456
+ const prefs = await readJsonFile2(prefsPath);
19457
+ if (!prefs) {
19458
+ console.log(pc42.dim("No Steel preferences set."));
19459
+ return;
19460
+ }
19461
+ console.log(JSON.stringify(prefs, null, 2));
19462
+ } catch (err) {
19463
+ const message = err instanceof Error ? err.message : String(err);
19464
+ console.error(pc42.red(`Error: ${message}`));
19465
+ process.exit(1);
19466
+ }
19467
+ })
19468
+ ).addCommand(
19469
+ new Command37("state").description("Show plate state").argument("<plate-name>", "Name of the plate").option("-p, --path <dir>", "Path to flint (default: auto-detect)").option("--reset", "Clear all state for this plate").action(async (plateName, options) => {
19470
+ try {
19471
+ const flintPath = options.path || await findFlintRoot(process.cwd());
19472
+ if (!flintPath) {
19473
+ console.error(pc42.red("Error: Not inside a Flint. Use --path or cd into a Flint."));
19474
+ process.exit(1);
19475
+ }
19476
+ const plateDir = join19(flintPath, ".steel", "plates", plateName);
19477
+ if (options.reset) {
19478
+ if (await exists5(plateDir)) {
19479
+ await rm5(plateDir, { recursive: true });
19480
+ console.log(pc42.green(`State cleared for plate: ${plateName}`));
19481
+ } else {
19482
+ console.log(pc42.dim(`No state found for plate: ${plateName}`));
19483
+ }
19484
+ return;
19485
+ }
19486
+ if (!await exists5(plateDir)) {
19487
+ console.log(pc42.dim(`No state found for plate: ${plateName}`));
19488
+ return;
19489
+ }
19490
+ const files = await readdir6(plateDir, { withFileTypes: true });
19491
+ const stateFiles = files.filter((f) => f.isFile() && f.name.endsWith(".json"));
19492
+ if (stateFiles.length === 0) {
19493
+ console.log(pc42.dim(`No state files for plate: ${plateName}`));
19494
+ return;
19495
+ }
19496
+ console.log(pc42.bold(`Plate state: ${plateName}`));
19497
+ console.log();
19498
+ for (const file of stateFiles) {
19499
+ const key = file.name.replace(/\.json$/, "");
19500
+ const data = await readJsonFile2(join19(plateDir, file.name));
19501
+ console.log(`${pc42.cyan(key)}:`);
19502
+ console.log(JSON.stringify(data, null, 2));
19503
+ console.log();
19504
+ }
19505
+ } catch (err) {
19506
+ const message = err instanceof Error ? err.message : String(err);
19507
+ console.error(pc42.red(`Error: ${message}`));
19508
+ process.exit(1);
19509
+ }
19510
+ })
19511
+ ).addCommand(
19512
+ new Command37("boards").description("List board/view configs for a plate").argument("<plate-name>", "Name of the plate").option("-p, --path <dir>", "Path to flint (default: auto-detect)").action(async (plateName, options) => {
19513
+ try {
19514
+ const flintPath = options.path || await findFlintRoot(process.cwd());
19515
+ if (!flintPath) {
19516
+ console.error(pc42.red("Error: Not inside a Flint. Use --path or cd into a Flint."));
19517
+ process.exit(1);
19518
+ }
19519
+ const boardsDir = join19(flintPath, ".steel", "plates", plateName, "boards");
19520
+ if (!await exists5(boardsDir)) {
19521
+ console.log(pc42.dim(`No board configs found for plate: ${plateName}`));
19522
+ return;
19523
+ }
19524
+ const files = await readdir6(boardsDir);
19525
+ const configs = files.filter((f) => f.endsWith(".json"));
19526
+ if (configs.length === 0) {
19527
+ console.log(pc42.dim(`No board configs found for plate: ${plateName}`));
19528
+ return;
19529
+ }
19530
+ console.log(pc42.bold(`Board configs: ${plateName}`));
19531
+ for (const file of configs) {
19532
+ const name = file.replace(/\.json$/, "");
19533
+ console.log(` ${pc42.cyan(name)}`);
19534
+ }
19535
+ } catch (err) {
19536
+ const message = err instanceof Error ? err.message : String(err);
19537
+ console.error(pc42.red(`Error: ${message}`));
19538
+ process.exit(1);
19539
+ }
19540
+ })
19541
+ );
19542
+
16997
19543
  // src/index.ts
16998
19544
  var __dirname3 = dirname4(fileURLToPath4(import.meta.url));
16999
- var pkg = JSON.parse(readFileSync11(join19(__dirname3, "..", "package.json"), "utf-8"));
19545
+ var pkg = JSON.parse(readFileSync11(join20(__dirname3, "..", "package.json"), "utf-8"));
17000
19546
  var runtime = resolveRuntimeSync({ cliname: "flint" });
17001
19547
  var devAvailable = runtime.mode === "dev";
17002
19548
  var newDir = getConfigDir("flint");
17003
- var oldDir = join19(homedir11(), ".flint");
17004
- var intermediateDir = join19(homedir11(), ".nuucognition", ".flint");
19549
+ var oldDir = join20(homedir11(), ".flint");
19550
+ var intermediateDir = join20(homedir11(), ".nuucognition", ".flint");
17005
19551
  function migrateDir(sourceDir, label) {
17006
19552
  if (!existsSync15(sourceDir)) return false;
17007
19553
  try {
@@ -17011,15 +19557,15 @@ function migrateDir(sourceDir, label) {
17011
19557
  mkdirSync5(newDir, { recursive: true });
17012
19558
  let migrated = 0;
17013
19559
  for (const entry of filesToMigrate) {
17014
- const src = join19(sourceDir, entry);
17015
- const dest = join19(newDir, entry);
19560
+ const src = join20(sourceDir, entry);
19561
+ const dest = join20(newDir, entry);
17016
19562
  if (!existsSync15(dest)) {
17017
19563
  cpSync(src, dest, { recursive: true });
17018
19564
  migrated++;
17019
19565
  }
17020
19566
  }
17021
19567
  if (migrated > 0) {
17022
- console.log(pc42.yellow(`Migrated ${migrated} item(s) from ${label} to ~/.nuucognition/flint/`));
19568
+ console.log(pc43.yellow(`Migrated ${migrated} item(s) from ${label} to ~/.nuucognition/flint/`));
17023
19569
  }
17024
19570
  return migrated > 0;
17025
19571
  } catch {
@@ -17055,7 +19601,7 @@ var authConfig = {
17055
19601
  defaultEnv: devAvailable ? "dev" : "prod",
17056
19602
  devAvailable
17057
19603
  };
17058
- var program = new Command37();
19604
+ var program = new Command38();
17059
19605
  program.name("flint").description("Flint cognitive workspace CLI").version(pkg.version).enablePositionalOptions().option("--verbose", "Show stack traces for errors");
17060
19606
  program.addCommand(createLoginCommand(authConfig));
17061
19607
  program.addCommand(createLogoutCommand(authConfig));
@@ -17095,6 +19641,7 @@ var COMMAND_MAP = [
17095
19641
  { featureId: "code", command: codeCommand },
17096
19642
  { featureId: "tinderbox", command: tinderboxCommand },
17097
19643
  { featureId: "orb", command: orbCommand },
19644
+ { featureId: "steel", command: steelCommand },
17098
19645
  // Dev commands
17099
19646
  { featureId: "runtime", command: runtimeCommand }
17100
19647
  ];
@@ -17109,11 +19656,11 @@ program.on("command:*", (operands) => {
17109
19656
  if (feature && !isFeatureEnabled(FEATURES, cmdName, runtime)) {
17110
19657
  error(`Feature '${cmdName}' requires dev mode.`);
17111
19658
  console.log("");
17112
- console.log(pc42.dim("Dev features are only available when running the dev binary."));
19659
+ console.log(pc43.dim("Dev features are only available when running the dev binary."));
17113
19660
  process.exit(1);
17114
19661
  }
17115
19662
  error(`Unknown command: ${cmdName}`);
17116
- console.log(pc42.dim(`Run 'flint --help' for available commands`));
19663
+ console.log(pc43.dim(`Run 'flint --help' for available commands`));
17117
19664
  process.exit(1);
17118
19665
  });
17119
19666
  await program.parseAsync(process.argv);