@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/{chunk-VAJMJ47E.js → chunk-6MPRSFXI.js} +2 -2
- package/dist/chunk-JSBRDJBE.js +30 -0
- package/dist/{chunk-XWUP7WHQ.js → chunk-WMXC6KO6.js} +70 -12
- package/dist/{chunk-C66KJDI7.js → chunk-X6OG5PEE.js} +1 -1
- package/dist/{dist-RGQKIZQW.js → dist-EAYA2DAP.js} +8 -3
- package/dist/{exports-FO5IMLM7-EN6H3N2A.js → exports-FO5IMLM7-4DUGQDXH.js} +2 -1
- package/dist/index.js +3022 -475
- package/dist/{mesh-config-BAIYF4KD-W2RGZQ2V.js → mesh-config-BAIYF4KD-Q3ZCQOCZ.js} +1 -0
- package/dist/{metadata-SJT4H53O-7W2752ZT.js → metadata-SJT4H53O-LEFHYM5Q.js} +1 -0
- package/dist/{registry-YN5W7EY7-SZNXPBV5.js → registry-YN5W7EY7-J52KXGG5.js} +2 -1
- package/dist/{utils-BBA2XQZO-YU5SL3JY.js → utils-BBA2XQZO-ETTV2PHU.js} +1 -0
- package/package.json +4 -4
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-
|
|
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-
|
|
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-
|
|
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
|
|
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
|
|
408
|
+
import { dirname as dirname4, join as join20 } from "path";
|
|
193
409
|
import { homedir as homedir11 } from "os";
|
|
194
|
-
import
|
|
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,
|
|
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 ===
|
|
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
|
|
329
|
-
if (
|
|
330
|
-
if (!
|
|
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 = !!
|
|
550
|
+
hasTime = !!match2[2];
|
|
335
551
|
hasTime && date[10] === " " && (date = date.replace(" ", "T"));
|
|
336
|
-
if (
|
|
552
|
+
if (match2[2] && +match2[2] > 23) {
|
|
337
553
|
date = "";
|
|
338
554
|
} else {
|
|
339
|
-
offset =
|
|
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
|
|
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
|
|
1193
|
-
const browserId =
|
|
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
|
|
1258
|
-
if (!
|
|
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 } =
|
|
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(
|
|
1785
|
+
async function readConfigFile(path10) {
|
|
1570
1786
|
try {
|
|
1571
|
-
const content = await fsReadFile(
|
|
1572
|
-
return
|
|
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(
|
|
1796
|
+
function readConfigFileSync(path10) {
|
|
1581
1797
|
try {
|
|
1582
|
-
const content = fsReadFileSync(
|
|
1583
|
-
return
|
|
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(
|
|
1592
|
-
await mkdir(dirname(
|
|
1593
|
-
await fsWriteFile(
|
|
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(
|
|
1597
|
-
const existing = await readConfigFile(
|
|
1812
|
+
async function setConfigField(path10, key, value) {
|
|
1813
|
+
const existing = await readConfigFile(path10) ?? {};
|
|
1598
1814
|
existing[key] = value;
|
|
1599
|
-
await writeConfigFile(
|
|
1815
|
+
await writeConfigFile(path10, existing);
|
|
1600
1816
|
}
|
|
1601
|
-
async function setFeatureOverride(
|
|
1602
|
-
const existing = await readConfigFile(
|
|
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(
|
|
1822
|
+
await writeConfigFile(path10, existing);
|
|
1607
1823
|
}
|
|
1608
|
-
async function removeFeatureOverride(
|
|
1609
|
-
const existing = await readConfigFile(
|
|
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(
|
|
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,
|
|
1632
|
-
if (!
|
|
1847
|
+
function mergeDefaults(config, defaults2) {
|
|
1848
|
+
if (!defaults2) return config;
|
|
1633
1849
|
return {
|
|
1634
|
-
...
|
|
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
|
|
1832
|
-
if (!existsSync(
|
|
1833
|
-
return normalizeCredentials(JSON.parse(readFileSync(
|
|
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(
|
|
2615
|
+
function abbreviatePath(path10) {
|
|
2399
2616
|
const home = homedir3();
|
|
2400
|
-
if (
|
|
2401
|
-
return
|
|
2617
|
+
if (path10.startsWith(home)) {
|
|
2618
|
+
return path10.replace(home, "~");
|
|
2402
2619
|
}
|
|
2403
|
-
return
|
|
2620
|
+
return path10;
|
|
2404
2621
|
}
|
|
2405
|
-
function expandPath(
|
|
2406
|
-
if (
|
|
2407
|
-
return
|
|
2622
|
+
function expandPath(path10) {
|
|
2623
|
+
if (path10.startsWith("~/")) {
|
|
2624
|
+
return path10.replace("~", homedir3());
|
|
2408
2625
|
}
|
|
2409
|
-
return
|
|
2626
|
+
return path10;
|
|
2410
2627
|
}
|
|
2411
2628
|
function padEnd(str, length) {
|
|
2412
2629
|
return str.padEnd(length);
|
|
2413
2630
|
}
|
|
2414
|
-
async function checkPathExists(
|
|
2631
|
+
async function checkPathExists(path10) {
|
|
2415
2632
|
try {
|
|
2416
|
-
await access(
|
|
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
|
|
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(
|
|
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
|
|
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(
|
|
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
|
|
3212
|
-
if (
|
|
3213
|
-
gitRemotes.set(shard.name,
|
|
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
|
|
3425
|
-
if (!
|
|
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[
|
|
3650
|
+
const decl = declarations[match2.name];
|
|
3434
3651
|
const source = decl?.source || "";
|
|
3435
3652
|
console.log(pc8.dim(`
|
|
3436
|
-
Transitioning ${
|
|
3437
|
-
const result = await editShard(flintPath,
|
|
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
|
|
3455
|
-
if (!
|
|
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 ${
|
|
3464
|
-
const result = await freezeShard(flintPath,
|
|
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
|
|
3482
|
-
if (!
|
|
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,
|
|
3706
|
+
const result = await addShardGitRemote(flintPath, match2.folderName, url);
|
|
3490
3707
|
console.log(pc8.green(`
|
|
3491
|
-
Remote added to ${pc8.bold(
|
|
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
|
|
3618
|
-
if (!
|
|
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(
|
|
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
|
|
3753
|
-
if (!
|
|
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[
|
|
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
|
-
"${
|
|
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
|
-
"${
|
|
3988
|
+
"${match2.folderName}" is not a dev shard.`));
|
|
3772
3989
|
console.log();
|
|
3773
3990
|
return;
|
|
3774
3991
|
}
|
|
3775
|
-
const shardPath = join5(flintPath, "Shards",
|
|
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
|
-
"${
|
|
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 ${
|
|
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(
|
|
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
|
|
3814
|
-
if (!
|
|
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[
|
|
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
|
-
"${
|
|
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
|
-
"${
|
|
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",
|
|
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
|
-
"${
|
|
3841
|
-
console.log(pc8.dim(` cd "Shards/${
|
|
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 ${
|
|
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 "${
|
|
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:
|
|
4092
|
+
const { readFile: readFile10, writeFile: writeFile7 } = await import("fs/promises");
|
|
3876
4093
|
const yamlPath = join5(shardPath, "shard.yaml");
|
|
3877
|
-
const yamlContent = await
|
|
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 ${
|
|
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 ${
|
|
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(
|
|
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
|
|
3928
|
-
if (!
|
|
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",
|
|
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[
|
|
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(
|
|
5192
|
+
async function exists(path10) {
|
|
4975
5193
|
try {
|
|
4976
|
-
await access2(
|
|
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(
|
|
5419
|
+
async function exists2(path10) {
|
|
5202
5420
|
try {
|
|
5203
|
-
await stat(
|
|
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(
|
|
5715
|
+
async function openInObsidian(path10) {
|
|
5498
5716
|
const os2 = platform3();
|
|
5499
5717
|
if (os2 === "darwin") {
|
|
5500
|
-
await execAsync2(`open -a "Obsidian" "${
|
|
5718
|
+
await execAsync2(`open -a "Obsidian" "${path10}"`);
|
|
5501
5719
|
} else if (os2 === "win32") {
|
|
5502
|
-
await execAsync2(`start "" "Obsidian" "${
|
|
5720
|
+
await execAsync2(`start "" "Obsidian" "${path10}"`);
|
|
5503
5721
|
} else {
|
|
5504
5722
|
try {
|
|
5505
|
-
await execAsync2(`obsidian "${
|
|
5723
|
+
await execAsync2(`obsidian "${path10}"`);
|
|
5506
5724
|
} catch {
|
|
5507
|
-
await execAsync2(`xdg-open "${
|
|
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
|
-
|
|
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
|
-
|
|
6468
|
-
execSync2("git
|
|
6469
|
-
|
|
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
|
|
6753
|
+
let exists6 = false;
|
|
6523
6754
|
try {
|
|
6524
6755
|
await stat2(obsidianDir);
|
|
6525
|
-
|
|
6756
|
+
exists6 = true;
|
|
6526
6757
|
} catch {
|
|
6527
6758
|
}
|
|
6528
|
-
if (
|
|
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 (
|
|
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
|
-
|
|
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-
|
|
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-
|
|
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-
|
|
7043
|
-
const { rm:
|
|
7044
|
-
const { join:
|
|
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
|
|
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-
|
|
7077
|
-
const { join:
|
|
7078
|
-
const { mkdtemp: mkdtemp2, rm:
|
|
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(
|
|
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
|
|
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
|
|
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 =
|
|
7103
|
-
await mkdir9(
|
|
7104
|
-
await
|
|
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-
|
|
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-
|
|
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(
|
|
7658
|
+
async function fileExists(path10) {
|
|
7428
7659
|
try {
|
|
7429
|
-
await stat3(
|
|
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
|
|
7449
|
-
if (
|
|
7450
|
-
|
|
7451
|
-
if (
|
|
7452
|
-
|
|
7453
|
-
if (
|
|
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
|
|
7716
|
-
while ((
|
|
7717
|
-
records.push({ id:
|
|
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
|
|
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
|
|
8058
|
-
import
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
10362
|
-
if (!
|
|
10595
|
+
const match2 = line.match(/^\s*(\d+)\.\s+.*\[(.+?)\]\s*$/);
|
|
10596
|
+
if (!match2) {
|
|
10363
10597
|
continue;
|
|
10364
10598
|
}
|
|
10365
|
-
const index =
|
|
10366
|
-
const sessionId =
|
|
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 =
|
|
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
|
|
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
|
-
|
|
10805
|
+
spawnSync32("osascript", ["-e", `display notification "${body}" with title "${title}"`], { stdio: "ignore" });
|
|
10572
10806
|
} else if (process.platform === "linux") {
|
|
10573
|
-
|
|
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
|
-
|
|
10771
|
-
|
|
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
|
|
10789
|
-
import {
|
|
10790
|
-
|
|
10791
|
-
|
|
10792
|
-
|
|
10793
|
-
|
|
10794
|
-
|
|
10795
|
-
|
|
10796
|
-
var
|
|
10797
|
-
"
|
|
10798
|
-
|
|
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
|
-
|
|
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
|
-
|
|
10840
|
-
|
|
10841
|
-
|
|
10842
|
-
|
|
10843
|
-
|
|
10844
|
-
}
|
|
10845
|
-
|
|
10846
|
-
|
|
10847
|
-
|
|
10848
|
-
|
|
10849
|
-
|
|
10850
|
-
|
|
10851
|
-
}
|
|
10852
|
-
|
|
10853
|
-
|
|
10854
|
-
|
|
10855
|
-
|
|
10856
|
-
|
|
10857
|
-
|
|
10858
|
-
|
|
10859
|
-
|
|
10860
|
-
|
|
10861
|
-
|
|
10862
|
-
|
|
10863
|
-
|
|
10864
|
-
|
|
10865
|
-
|
|
10866
|
-
|
|
10867
|
-
|
|
10868
|
-
|
|
10869
|
-
|
|
10870
|
-
|
|
10871
|
-
|
|
10872
|
-
|
|
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
|
-
|
|
10875
|
-
|
|
10876
|
-
|
|
10877
|
-
const start = () => {
|
|
10878
|
-
if (closed) {
|
|
10879
|
-
return;
|
|
11067
|
+
if (c === "]" && sawStart && !escaping) {
|
|
11068
|
+
endPos = i + 1;
|
|
11069
|
+
break;
|
|
10880
11070
|
}
|
|
10881
|
-
|
|
10882
|
-
|
|
10883
|
-
|
|
11071
|
+
sawStart = true;
|
|
11072
|
+
if (c === "\\") {
|
|
11073
|
+
if (!escaping) {
|
|
11074
|
+
escaping = true;
|
|
11075
|
+
i++;
|
|
11076
|
+
continue;
|
|
11077
|
+
}
|
|
10884
11078
|
}
|
|
10885
|
-
|
|
10886
|
-
|
|
10887
|
-
|
|
10888
|
-
|
|
10889
|
-
|
|
10890
|
-
|
|
10891
|
-
|
|
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
|
-
|
|
10895
|
-
|
|
10896
|
-
|
|
10897
|
-
|
|
10898
|
-
|
|
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
|
-
|
|
10903
|
-
|
|
11102
|
+
rangeStart = "";
|
|
11103
|
+
i++;
|
|
11104
|
+
continue;
|
|
10904
11105
|
}
|
|
10905
|
-
|
|
10906
|
-
|
|
10907
|
-
|
|
10908
|
-
|
|
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
|
-
|
|
10917
|
-
|
|
10918
|
-
|
|
10919
|
-
|
|
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
|
-
|
|
10922
|
-
return
|
|
11119
|
+
if (endPos < i) {
|
|
11120
|
+
return ["", false, 0, false];
|
|
10923
11121
|
}
|
|
10924
|
-
|
|
10925
|
-
return
|
|
11122
|
+
if (!ranges.length && !negs.length) {
|
|
11123
|
+
return ["$.", false, glob2.length - pos, true];
|
|
10926
11124
|
}
|
|
10927
|
-
|
|
10928
|
-
const
|
|
10929
|
-
|
|
10930
|
-
|
|
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
|
-
|
|
10933
|
-
this.runtimes.delete(id);
|
|
10934
|
-
return true;
|
|
11215
|
+
return this.#hasMagic;
|
|
10935
11216
|
}
|
|
10936
|
-
|
|
10937
|
-
|
|
10938
|
-
|
|
10939
|
-
|
|
10940
|
-
|
|
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
|
-
|
|
10945
|
-
|
|
10946
|
-
|
|
10947
|
-
|
|
10948
|
-
|
|
10949
|
-
|
|
10950
|
-
|
|
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
|
-
|
|
10961
|
-
|
|
10962
|
-
|
|
10963
|
-
|
|
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
|
|
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 =
|
|
11152
|
-
const distRoot =
|
|
11153
|
-
if (!await
|
|
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 ?
|
|
11159
|
-
if (!targetPath.startsWith(distRoot) || !await
|
|
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
|
|
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 =
|
|
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(
|
|
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 =
|
|
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(
|
|
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 =
|
|
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 =
|
|
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 =
|
|
11396
|
-
const shardsDir =
|
|
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(
|
|
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
|
|
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 =
|
|
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 ??
|
|
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 =
|
|
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(
|
|
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
|
|
12453
|
-
if (!
|
|
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(
|
|
14726
|
+
(r) => r.check.includes(match2.folderName) || r.check.includes(match2.name)
|
|
12459
14727
|
);
|
|
12460
14728
|
return {
|
|
12461
|
-
shard:
|
|
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
|
|
12496
|
-
if (!
|
|
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,
|
|
14768
|
+
const results = await healShard(ctx.flintPath, match2.folderName);
|
|
12501
14769
|
return {
|
|
12502
|
-
shard:
|
|
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(
|
|
14959
|
+
function getLogEntries(filter2) {
|
|
12546
14960
|
let result = buffer;
|
|
12547
|
-
if (
|
|
12548
|
-
const method =
|
|
14961
|
+
if (filter2?.method) {
|
|
14962
|
+
const method = filter2.method.toUpperCase();
|
|
12549
14963
|
result = result.filter((entry) => entry.method === method);
|
|
12550
14964
|
}
|
|
12551
|
-
if (
|
|
12552
|
-
const minStatus =
|
|
14965
|
+
if (filter2?.minStatus != null) {
|
|
14966
|
+
const minStatus = filter2.minStatus;
|
|
12553
14967
|
result = result.filter((entry) => entry.statusCode >= minStatus);
|
|
12554
14968
|
}
|
|
12555
|
-
if (
|
|
12556
|
-
const maxStatus =
|
|
14969
|
+
if (filter2?.maxStatus != null) {
|
|
14970
|
+
const maxStatus = filter2.maxStatus;
|
|
12557
14971
|
result = result.filter((entry) => entry.statusCode <= maxStatus);
|
|
12558
14972
|
}
|
|
12559
|
-
if (
|
|
12560
|
-
const pattern =
|
|
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 (
|
|
12564
|
-
result = result.filter((entry) => entry.timestamp >=
|
|
14977
|
+
if (filter2?.since) {
|
|
14978
|
+
result = result.filter((entry) => entry.timestamp >= filter2.since);
|
|
12565
14979
|
}
|
|
12566
|
-
if (
|
|
12567
|
-
result = result.slice(-
|
|
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(
|
|
12577
|
-
return !EXCLUDED_PATHS.some((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
|
|
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:
|
|
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:
|
|
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
|
|
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
|
|
15443
|
+
const dirStat = await stat42(dirPath).catch(() => null);
|
|
13030
15444
|
if (!dirStat?.isDirectory()) continue;
|
|
13031
15445
|
let files;
|
|
13032
15446
|
try {
|
|
13033
|
-
files = await
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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 ?
|
|
15576
|
+
const flintPath = options.flintPath ? path7.resolve(options.flintPath) : void 0;
|
|
13163
15577
|
const runtimeManager = new RuntimeManager();
|
|
13164
|
-
const orbhSessionsDir = flintPath ?
|
|
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 =
|
|
13189
|
-
const dashboardDist =
|
|
15602
|
+
const __dirname4 = path7.dirname(fileURLToPath2(import.meta.url));
|
|
15603
|
+
const dashboardDist = path7.resolve(__dirname4, "..", "..", "..", "apps", "flint-dashboard", "dist");
|
|
13190
15604
|
try {
|
|
13191
|
-
await
|
|
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 ??
|
|
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
|
|
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 =
|
|
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 =
|
|
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
|
|
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 ?
|
|
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 ?
|
|
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
|
|
16001
|
+
const match2 = (payload.runtimes ?? []).find(
|
|
13587
16002
|
(runtime2) => runtime2.flintPath === lookupPath
|
|
13588
16003
|
);
|
|
13589
|
-
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
14193
|
-
return
|
|
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(
|
|
17007
|
+
async function exists4(path10) {
|
|
14589
17008
|
try {
|
|
14590
|
-
await stat10(
|
|
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-
|
|
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
|
|
14934
|
-
if (!
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
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 =
|
|
17004
|
-
var intermediateDir =
|
|
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 =
|
|
17015
|
-
const dest =
|
|
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(
|
|
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
|
|
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(
|
|
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(
|
|
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);
|