@nuucognition/flint-cli 0.5.6-dev.4 → 0.5.6-dev.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-WMXC6KO6.js → chunk-BF3SKNVR.js} +448 -948
- package/dist/{chunk-6MPRSFXI.js → chunk-IUKEMLPH.js} +4 -4
- package/dist/chunk-JCALNZ4D.js +936 -0
- package/dist/{chunk-X6OG5PEE.js → chunk-JNIJ5JV6.js} +2 -2
- package/dist/{chunk-CBGQBE6C.js → chunk-LLLVBA4Q.js} +17 -3
- package/dist/{chunk-M3NSYVYR.js → chunk-RD3WIRZN.js} +2 -2
- package/dist/{dist-EAYA2DAP.js → dist-MNBUCH3R.js} +34 -20
- package/dist/{exports-FO5IMLM7-4DUGQDXH.js → exports-VR7XB6MC-5N77WY3S.js} +2 -2
- package/dist/index.js +2543 -1603
- package/dist/{mesh-config-BAIYF4KD-Q3ZCQOCZ.js → mesh-config-NTGFUNZL-BZ2GO3JY.js} +3 -1
- package/dist/{metadata-SJT4H53O-LEFHYM5Q.js → metadata-FASTWX6A-ITKM6C62.js} +2 -2
- package/dist/plates-UD55BGK4-HV7L7MQX.js +42 -0
- package/dist/{registry-YN5W7EY7-J52KXGG5.js → registry-5CNUVQN3-PCQZRXLB.js} +1 -1
- package/package.json +6 -4
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
registerFlint,
|
|
8
8
|
registerFlintByPath,
|
|
9
9
|
updateFlintEntry
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-JNIJ5JV6.js";
|
|
11
11
|
import {
|
|
12
12
|
exists,
|
|
13
13
|
runConcurrent
|
|
@@ -15,14 +15,15 @@ import {
|
|
|
15
15
|
import {
|
|
16
16
|
ensureMetadataDirs,
|
|
17
17
|
syncSourceRepoMetadata
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-RD3WIRZN.js";
|
|
19
|
+
import {
|
|
20
|
+
syncPlateRepos
|
|
21
|
+
} from "./chunk-JCALNZ4D.js";
|
|
19
22
|
import {
|
|
20
|
-
addPlateDeclaration,
|
|
21
23
|
addShardToConfig,
|
|
22
24
|
createFlintJson,
|
|
23
25
|
createFlintToml,
|
|
24
26
|
getFlintConfigDir,
|
|
25
|
-
getPlateDeclarations,
|
|
26
27
|
getShardDeclarations,
|
|
27
28
|
getShardDeclarationsFromConfig,
|
|
28
29
|
getSourceRepositories,
|
|
@@ -39,7 +40,7 @@ import {
|
|
|
39
40
|
toKebabCase,
|
|
40
41
|
writeFlintJson,
|
|
41
42
|
writeFlintToml
|
|
42
|
-
} from "./chunk-
|
|
43
|
+
} from "./chunk-LLLVBA4Q.js";
|
|
43
44
|
|
|
44
45
|
// ../../packages/flint/dist/index.js
|
|
45
46
|
import { mkdir as mkdir2, stat as stat9 } from "fs/promises";
|
|
@@ -57,35 +58,29 @@ import { homedir } from "os";
|
|
|
57
58
|
import { readFile as readFile5, writeFile as writeFile22, mkdir as mkdir32 } from "fs/promises";
|
|
58
59
|
import { readFileSync } from "fs";
|
|
59
60
|
import { join as join52 } from "path";
|
|
60
|
-
import {
|
|
61
|
+
import { createHash, randomUUID as randomUUID3 } from "crypto";
|
|
62
|
+
import { mkdir as mkdir52, readdir as readdir22, readFile as readFile32, rename as rename5, rm as rm6, writeFile as writeFile42 } from "fs/promises";
|
|
63
|
+
import { basename, dirname as dirname22, join as join72, relative } from "path";
|
|
64
|
+
import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
|
|
65
|
+
import { readFile as readFile22, writeFile as writeFile32, mkdir as mkdir42, access as access22 } from "fs/promises";
|
|
66
|
+
import { join as join62 } from "path";
|
|
67
|
+
import { mkdir as mkdir6, stat as stat42 } from "fs/promises";
|
|
68
|
+
import { join as join82 } from "path";
|
|
61
69
|
import { exec as exec2 } from "child_process";
|
|
62
|
-
import { mkdir as mkdir42, readdir as readdir22, readFile as readFile22, rm as rm6, stat as stat42, writeFile as writeFile32 } from "fs/promises";
|
|
63
|
-
import { basename, join as join62, relative, resolve as resolve2 } from "path";
|
|
64
70
|
import { promisify as promisify2 } from "util";
|
|
65
|
-
import {
|
|
66
|
-
import { createHash, randomUUID as randomUUID3 } from "crypto";
|
|
67
|
-
import { mkdir as mkdir6, readdir as readdir32, readFile as readFile42, rename as rename5, rm as rm22, writeFile as writeFile52 } from "fs/promises";
|
|
68
|
-
import { basename as basename2, dirname as dirname22, join as join82, relative as relative2 } from "path";
|
|
69
|
-
import { parse as parseYaml2, stringify as stringifyYaml2 } from "yaml";
|
|
70
|
-
import { readFile as readFile32, writeFile as writeFile42, mkdir as mkdir52, access as access22 } from "fs/promises";
|
|
71
|
-
import { join as join72 } from "path";
|
|
72
|
-
import { mkdir as mkdir7, stat as stat52 } from "fs/promises";
|
|
73
|
-
import { join as join92 } from "path";
|
|
74
|
-
import { exec as exec3 } from "child_process";
|
|
75
|
-
import { promisify as promisify3 } from "util";
|
|
76
|
-
import { rm as rm32 } from "fs/promises";
|
|
71
|
+
import { rm as rm22 } from "fs/promises";
|
|
77
72
|
import { execFile } from "child_process";
|
|
78
|
-
import { cp as cp3, mkdir as
|
|
73
|
+
import { cp as cp3, mkdir as mkdir8, readdir as readdir32, readFile as readFile52, rename as rename22, rm as rm42, stat as stat62, writeFile as writeFile6 } from "fs/promises";
|
|
79
74
|
import { homedir as homedir2 } from "os";
|
|
80
|
-
import { basename as
|
|
81
|
-
import { promisify as
|
|
82
|
-
import { readFile as
|
|
83
|
-
import { join as
|
|
75
|
+
import { basename as basename2, dirname as dirname3, join as join102, resolve as resolve3 } from "path";
|
|
76
|
+
import { promisify as promisify3 } from "util";
|
|
77
|
+
import { readFile as readFile42, writeFile as writeFile52, mkdir as mkdir7, rm as rm32, stat as stat52 } from "fs/promises";
|
|
78
|
+
import { join as join92 } from "path";
|
|
84
79
|
import { randomUUID as randomUUID22 } from "crypto";
|
|
85
|
-
import { mkdir as
|
|
86
|
-
import { join as
|
|
80
|
+
import { mkdir as mkdir9, readdir as readdir42, copyFile, rm as rm62, readFile as readFile7, writeFile as writeFile7, rmdir as rmdir2 } from "fs/promises";
|
|
81
|
+
import { join as join12, resolve as resolve5, dirname as dirname4 } from "path";
|
|
87
82
|
import { randomUUID as randomUUID32 } from "crypto";
|
|
88
|
-
import { parse as
|
|
83
|
+
import { parse as parseYaml3 } from "yaml";
|
|
89
84
|
|
|
90
85
|
// ../../packages/flint-migrations/dist/index.js
|
|
91
86
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
@@ -2356,38 +2351,38 @@ async function runSingleMigration(flintPath, migrationId, options = {}) {
|
|
|
2356
2351
|
}
|
|
2357
2352
|
|
|
2358
2353
|
// ../../packages/flint/dist/index.js
|
|
2359
|
-
import { join as
|
|
2360
|
-
import { mkdtemp, rm as
|
|
2354
|
+
import { join as join112, resolve as resolve4, isAbsolute as isAbsolute2 } from "path";
|
|
2355
|
+
import { mkdtemp, rm as rm52 } from "fs/promises";
|
|
2361
2356
|
import { tmpdir } from "os";
|
|
2362
|
-
import { exec as
|
|
2363
|
-
import { promisify as
|
|
2364
|
-
import { parse as
|
|
2365
|
-
import { readFile as
|
|
2366
|
-
import { join as
|
|
2367
|
-
import { readdir as
|
|
2368
|
-
import { writeFile as
|
|
2357
|
+
import { exec as exec3 } from "child_process";
|
|
2358
|
+
import { promisify as promisify4 } from "util";
|
|
2359
|
+
import { parse as parseYaml2 } from "yaml";
|
|
2360
|
+
import { readFile as readFile6 } from "fs/promises";
|
|
2361
|
+
import { join as join13 } from "path";
|
|
2362
|
+
import { readdir as readdir52, mkdir as mkdir10 } from "fs/promises";
|
|
2363
|
+
import { writeFile as writeFile8 } from "fs/promises";
|
|
2369
2364
|
import { execSync } from "child_process";
|
|
2370
2365
|
import { existsSync } from "fs";
|
|
2371
|
-
import { spawn
|
|
2372
|
-
import { readdir as
|
|
2373
|
-
import { join as
|
|
2366
|
+
import { spawn } from "child_process";
|
|
2367
|
+
import { readdir as readdir62, access as access3, constants } from "fs/promises";
|
|
2368
|
+
import { join as join14, resolve as resolve6 } from "path";
|
|
2374
2369
|
import { rename as rename32 } from "fs/promises";
|
|
2375
|
-
import { basename as
|
|
2376
|
-
import { exec as
|
|
2377
|
-
import { promisify as
|
|
2378
|
-
import { readFile as
|
|
2379
|
-
import { join as
|
|
2380
|
-
import { stat as
|
|
2381
|
-
import { readdir as
|
|
2382
|
-
import { join as
|
|
2370
|
+
import { basename as basename3, dirname as dirname5, join as join16 } from "path";
|
|
2371
|
+
import { exec as exec4 } from "child_process";
|
|
2372
|
+
import { promisify as promisify5 } from "util";
|
|
2373
|
+
import { readFile as readFile8, writeFile as writeFile9, readdir as readdir72 } from "fs/promises";
|
|
2374
|
+
import { join as join15 } from "path";
|
|
2375
|
+
import { stat as stat72, mkdir as mkdir11 } from "fs/promises";
|
|
2376
|
+
import { readdir as readdir82, readFile as readFile9, mkdir as mkdir12 } from "fs/promises";
|
|
2377
|
+
import { join as join17, dirname as dirname6, resolve as resolve7, sep } from "path";
|
|
2383
2378
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
2384
2379
|
import { fileURLToPath } from "url";
|
|
2385
2380
|
import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, writeFileSync, readdirSync } from "fs";
|
|
2386
|
-
import { join as
|
|
2381
|
+
import { join as join18 } from "path";
|
|
2387
2382
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
2388
2383
|
import { watch, watchFile, unwatchFile, statSync, openSync, readSync, closeSync } from "fs";
|
|
2389
2384
|
import { existsSync as existsSync3 } from "fs";
|
|
2390
|
-
import { join as
|
|
2385
|
+
import { join as join19 } from "path";
|
|
2391
2386
|
import { homedir as homedir3 } from "os";
|
|
2392
2387
|
import { existsSync as existsSync4 } from "fs";
|
|
2393
2388
|
var STANDARD_DIRECTORIES = ["Mesh", "Media", "Shards", "Plates", "Sources", "Exports", "Workspace", "Workspace/Bench"];
|
|
@@ -2707,541 +2702,16 @@ async function getOpenApps() {
|
|
|
2707
2702
|
const config = await readGlobalConfig();
|
|
2708
2703
|
return config.open?.apps ?? ["obsidian"];
|
|
2709
2704
|
}
|
|
2710
|
-
var execAsync2 = promisify2(exec2);
|
|
2711
|
-
function normalizePlateName(name) {
|
|
2712
|
-
return name.trim().toLowerCase();
|
|
2713
|
-
}
|
|
2714
|
-
function isSlug(value) {
|
|
2715
|
-
return /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(value);
|
|
2716
|
-
}
|
|
2717
|
-
async function fileExists2(path) {
|
|
2718
|
-
try {
|
|
2719
|
-
await stat42(path);
|
|
2720
|
-
return true;
|
|
2721
|
-
} catch {
|
|
2722
|
-
return false;
|
|
2723
|
-
}
|
|
2724
|
-
}
|
|
2725
|
-
function validateManifest(manifest, manifestPath) {
|
|
2726
|
-
if (!manifest || typeof manifest !== "object") {
|
|
2727
|
-
throw new Error(`Invalid plate.yaml at ${manifestPath}`);
|
|
2728
|
-
}
|
|
2729
|
-
const record = manifest;
|
|
2730
|
-
const name = typeof record.name === "string" ? record.name.trim() : "";
|
|
2731
|
-
const title = typeof record.title === "string" ? record.title.trim() : "";
|
|
2732
|
-
const entry = typeof record.entry === "string" ? record.entry.trim() : "";
|
|
2733
|
-
if (!name || !title || !entry) {
|
|
2734
|
-
throw new Error(`plate.yaml is missing required fields (name, title, entry): ${manifestPath}`);
|
|
2735
|
-
}
|
|
2736
|
-
if (!isSlug(name)) {
|
|
2737
|
-
throw new Error(`Invalid plate name "${name}" in ${manifestPath}`);
|
|
2738
|
-
}
|
|
2739
|
-
const tools = Array.isArray(record.tools) ? record.tools.map((tool) => {
|
|
2740
|
-
if (!tool || typeof tool !== "object") {
|
|
2741
|
-
throw new Error(`Invalid tool declaration in ${manifestPath}`);
|
|
2742
|
-
}
|
|
2743
|
-
const toolRecord = tool;
|
|
2744
|
-
const toolName = typeof toolRecord.name === "string" ? toolRecord.name.trim() : "";
|
|
2745
|
-
const command = typeof toolRecord.command === "string" ? toolRecord.command.trim() : "";
|
|
2746
|
-
const description = typeof toolRecord.description === "string" ? toolRecord.description.trim() : "";
|
|
2747
|
-
if (!toolName || !command || !description) {
|
|
2748
|
-
throw new Error(`Tool declaration is missing required fields in ${manifestPath}`);
|
|
2749
|
-
}
|
|
2750
|
-
return { name: toolName, command, description };
|
|
2751
|
-
}) : void 0;
|
|
2752
|
-
const handles = Array.isArray(record.handles) ? record.handles.map((handle) => {
|
|
2753
|
-
if (!handle || typeof handle !== "object") {
|
|
2754
|
-
throw new Error(`Invalid handle declaration in ${manifestPath}`);
|
|
2755
|
-
}
|
|
2756
|
-
const handleRecord = handle;
|
|
2757
|
-
const tag = typeof handleRecord.tag === "string" ? handleRecord.tag.trim() : "";
|
|
2758
|
-
if (!tag) {
|
|
2759
|
-
throw new Error(`Handle declaration is missing required tag in ${manifestPath}`);
|
|
2760
|
-
}
|
|
2761
|
-
return {
|
|
2762
|
-
tag,
|
|
2763
|
-
default: handleRecord.default === true
|
|
2764
|
-
};
|
|
2765
|
-
}) : void 0;
|
|
2766
|
-
const actions = Array.isArray(record.actions) ? record.actions.map((action) => {
|
|
2767
|
-
if (!action || typeof action !== "object") {
|
|
2768
|
-
throw new Error(`Invalid action declaration in ${manifestPath}`);
|
|
2769
|
-
}
|
|
2770
|
-
const actionRecord = action;
|
|
2771
|
-
const id = typeof actionRecord.id === "string" ? actionRecord.id.trim() : "";
|
|
2772
|
-
const label = typeof actionRecord.label === "string" ? actionRecord.label.trim() : "";
|
|
2773
|
-
if (!id || !label) {
|
|
2774
|
-
throw new Error(`Action declaration is missing required fields in ${manifestPath}`);
|
|
2775
|
-
}
|
|
2776
|
-
return {
|
|
2777
|
-
id,
|
|
2778
|
-
label,
|
|
2779
|
-
description: typeof actionRecord.description === "string" ? actionRecord.description : void 0,
|
|
2780
|
-
icon: typeof actionRecord.icon === "string" ? actionRecord.icon : void 0
|
|
2781
|
-
};
|
|
2782
|
-
}) : void 0;
|
|
2783
|
-
return {
|
|
2784
|
-
name,
|
|
2785
|
-
title,
|
|
2786
|
-
entry,
|
|
2787
|
-
version: typeof record.version === "string" ? record.version : void 0,
|
|
2788
|
-
description: typeof record.description === "string" ? record.description : void 0,
|
|
2789
|
-
icon: typeof record.icon === "string" ? record.icon : void 0,
|
|
2790
|
-
shard: typeof record.shard === "string" ? record.shard : void 0,
|
|
2791
|
-
dev: typeof record.dev === "string" ? record.dev : void 0,
|
|
2792
|
-
api: Array.isArray(record.api) ? record.api.filter((value) => typeof value === "string") : void 0,
|
|
2793
|
-
handles,
|
|
2794
|
-
actions,
|
|
2795
|
-
tools
|
|
2796
|
-
};
|
|
2797
|
-
}
|
|
2798
|
-
async function readPlateManifest(platePath) {
|
|
2799
|
-
const manifestPath = join62(platePath, "plate.yaml");
|
|
2800
|
-
const content = await readFile22(manifestPath, "utf8");
|
|
2801
|
-
return validateManifest(parseYaml(content, { logLevel: "error" }), manifestPath);
|
|
2802
|
-
}
|
|
2803
|
-
function resolvePlateEntryPath(platePath, manifest) {
|
|
2804
|
-
return resolve2(platePath, manifest.entry);
|
|
2805
|
-
}
|
|
2806
|
-
var PLATE_SKIP_DIRS = /* @__PURE__ */ new Set(["node_modules", "dist", ".git"]);
|
|
2807
|
-
async function getNewestMtime(dir) {
|
|
2808
|
-
let max = 0;
|
|
2809
|
-
try {
|
|
2810
|
-
const entries = await readdir22(dir, { withFileTypes: true });
|
|
2811
|
-
for (const entry of entries) {
|
|
2812
|
-
if (PLATE_SKIP_DIRS.has(entry.name)) continue;
|
|
2813
|
-
const full = join62(dir, entry.name);
|
|
2814
|
-
if (entry.isDirectory()) {
|
|
2815
|
-
const sub = await getNewestMtime(full);
|
|
2816
|
-
if (sub > max) max = sub;
|
|
2817
|
-
} else {
|
|
2818
|
-
const s = await stat42(full);
|
|
2819
|
-
if (s.mtimeMs > max) max = s.mtimeMs;
|
|
2820
|
-
}
|
|
2821
|
-
}
|
|
2822
|
-
} catch {
|
|
2823
|
-
}
|
|
2824
|
-
return max;
|
|
2825
|
-
}
|
|
2826
|
-
async function checkPlateStale(platePath, manifest) {
|
|
2827
|
-
const entryPath = resolvePlateEntryPath(platePath, manifest);
|
|
2828
|
-
const entryStat = await stat42(entryPath).catch(() => null);
|
|
2829
|
-
if (!entryStat) return false;
|
|
2830
|
-
const sourceMtime = await getNewestMtime(platePath);
|
|
2831
|
-
return sourceMtime > entryStat.mtimeMs;
|
|
2832
|
-
}
|
|
2833
|
-
async function resolvePlateInfoFromDeclaration(flintPath, declarationName, declarationPath) {
|
|
2834
|
-
const absolutePath = resolve2(flintPath, declarationPath);
|
|
2835
|
-
const manifest = await readPlateManifest(absolutePath);
|
|
2836
|
-
const built = await fileExists2(resolvePlateEntryPath(absolutePath, manifest));
|
|
2837
|
-
const stale = built ? await checkPlateStale(absolutePath, manifest) : false;
|
|
2838
|
-
return {
|
|
2839
|
-
declarationName,
|
|
2840
|
-
directoryName: basename(absolutePath),
|
|
2841
|
-
path: absolutePath,
|
|
2842
|
-
built,
|
|
2843
|
-
stale,
|
|
2844
|
-
manifest
|
|
2845
|
-
};
|
|
2846
|
-
}
|
|
2847
|
-
async function initPlateRepo(flintPath, plateName, url) {
|
|
2848
|
-
const plate = await getPlate(flintPath, plateName);
|
|
2849
|
-
if (!plate) {
|
|
2850
|
-
throw new Error(`Plate not found: ${plateName}`);
|
|
2851
|
-
}
|
|
2852
|
-
const plateDir = plate.path;
|
|
2853
|
-
const gitDir = join62(plateDir, ".git");
|
|
2854
|
-
const isGitRepo = await fileExists2(gitDir);
|
|
2855
|
-
if (!isGitRepo) {
|
|
2856
|
-
await execAsync2("git init", { cwd: plateDir });
|
|
2857
|
-
}
|
|
2858
|
-
const gitignorePath = join62(plateDir, ".gitignore");
|
|
2859
|
-
if (!await fileExists2(gitignorePath)) {
|
|
2860
|
-
await writeFile32(gitignorePath, "node_modules/\ndist/\n", "utf8");
|
|
2861
|
-
}
|
|
2862
|
-
try {
|
|
2863
|
-
const { stdout: existingRemote } = await execAsync2("git remote get-url origin", { cwd: plateDir });
|
|
2864
|
-
if (existingRemote.trim() !== url) {
|
|
2865
|
-
await execAsync2(`git remote set-url origin "${url}"`, { cwd: plateDir });
|
|
2866
|
-
}
|
|
2867
|
-
} catch {
|
|
2868
|
-
await execAsync2(`git remote add origin "${url}"`, { cwd: plateDir });
|
|
2869
|
-
}
|
|
2870
|
-
await execAsync2("git add .", { cwd: plateDir });
|
|
2871
|
-
let hasChanges = false;
|
|
2872
|
-
try {
|
|
2873
|
-
const { stdout: statusOut } = await execAsync2("git status --porcelain", { cwd: plateDir });
|
|
2874
|
-
hasChanges = statusOut.trim().length > 0;
|
|
2875
|
-
} catch {
|
|
2876
|
-
hasChanges = true;
|
|
2877
|
-
}
|
|
2878
|
-
if (hasChanges) {
|
|
2879
|
-
await execAsync2('git commit -m "Update plate"', { cwd: plateDir });
|
|
2880
|
-
}
|
|
2881
|
-
let pushed = false;
|
|
2882
|
-
try {
|
|
2883
|
-
await execAsync2("git push -u origin main", { cwd: plateDir, timeout: 6e4 });
|
|
2884
|
-
pushed = true;
|
|
2885
|
-
} catch {
|
|
2886
|
-
try {
|
|
2887
|
-
await execAsync2("git push -u origin HEAD", { cwd: plateDir, timeout: 6e4 });
|
|
2888
|
-
pushed = true;
|
|
2889
|
-
} catch {
|
|
2890
|
-
}
|
|
2891
|
-
}
|
|
2892
|
-
return { initialized: !isGitRepo, pushed, platePath: plateDir };
|
|
2893
|
-
}
|
|
2894
|
-
async function clonePlateFromRepo(flintPath, name, url, targetPath) {
|
|
2895
|
-
const absolutePath = resolve2(flintPath, targetPath);
|
|
2896
|
-
await mkdir42(join62(flintPath, "Plates"), { recursive: true });
|
|
2897
|
-
if (await fileExists2(absolutePath)) {
|
|
2898
|
-
throw new Error(`Plate directory already exists: ${targetPath}`);
|
|
2899
|
-
}
|
|
2900
|
-
try {
|
|
2901
|
-
await execAsync2(`git clone --depth 1 "${url}" "${absolutePath}"`, { timeout: 6e4 });
|
|
2902
|
-
} catch (error) {
|
|
2903
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
2904
|
-
throw new Error(`Failed to clone plate "${name}": ${message}`);
|
|
2905
|
-
}
|
|
2906
|
-
const gitDir = join62(absolutePath, ".git");
|
|
2907
|
-
try {
|
|
2908
|
-
await rm6(gitDir, { recursive: true, force: true });
|
|
2909
|
-
} catch {
|
|
2910
|
-
}
|
|
2911
|
-
return absolutePath;
|
|
2912
|
-
}
|
|
2913
|
-
async function updatePlateFromRepo(flintPath, name, url, targetPath) {
|
|
2914
|
-
const absolutePath = resolve2(flintPath, targetPath);
|
|
2915
|
-
if (await fileExists2(absolutePath)) {
|
|
2916
|
-
await rm6(absolutePath, { recursive: true, force: true });
|
|
2917
|
-
}
|
|
2918
|
-
return clonePlateFromRepo(flintPath, name, url, targetPath);
|
|
2919
|
-
}
|
|
2920
|
-
async function syncPlateRepos(flintPath, declarations) {
|
|
2921
|
-
const results = [];
|
|
2922
|
-
for (const [name, decl] of Object.entries(declarations)) {
|
|
2923
|
-
if (!decl.repo) continue;
|
|
2924
|
-
const absolutePath = resolve2(flintPath, decl.path);
|
|
2925
|
-
const exists2 = await fileExists2(absolutePath);
|
|
2926
|
-
try {
|
|
2927
|
-
if (exists2) {
|
|
2928
|
-
results.push({ name, status: "skipped" });
|
|
2929
|
-
} else {
|
|
2930
|
-
await clonePlateFromRepo(flintPath, name, decl.repo, decl.path);
|
|
2931
|
-
results.push({ name, status: "cloned" });
|
|
2932
|
-
}
|
|
2933
|
-
} catch (err) {
|
|
2934
|
-
results.push({
|
|
2935
|
-
name,
|
|
2936
|
-
status: "error",
|
|
2937
|
-
error: err instanceof Error ? err.message : String(err)
|
|
2938
|
-
});
|
|
2939
|
-
}
|
|
2940
|
-
}
|
|
2941
|
-
return results;
|
|
2942
|
-
}
|
|
2943
|
-
async function listPlates(flintPath) {
|
|
2944
|
-
const declarations = await getPlateDeclarations(flintPath);
|
|
2945
|
-
const infos = await Promise.all(
|
|
2946
|
-
Object.entries(declarations).map(([name, decl]) => resolvePlateInfoFromDeclaration(flintPath, name, decl.path))
|
|
2947
|
-
);
|
|
2948
|
-
const seenNames = /* @__PURE__ */ new Set();
|
|
2949
|
-
for (const info of infos) {
|
|
2950
|
-
const normalized = normalizePlateName(info.manifest.name);
|
|
2951
|
-
if (seenNames.has(normalized)) {
|
|
2952
|
-
throw new Error(`Duplicate plate manifest name detected: ${info.manifest.name}`);
|
|
2953
|
-
}
|
|
2954
|
-
seenNames.add(normalized);
|
|
2955
|
-
}
|
|
2956
|
-
return infos.sort((left, right) => left.manifest.title.localeCompare(right.manifest.title));
|
|
2957
|
-
}
|
|
2958
|
-
async function getPlate(flintPath, plateName) {
|
|
2959
|
-
const normalized = normalizePlateName(plateName);
|
|
2960
|
-
const plates = await listPlates(flintPath);
|
|
2961
|
-
return plates.find(
|
|
2962
|
-
(plate) => normalizePlateName(plate.declarationName) === normalized || normalizePlateName(plate.manifest.name) === normalized
|
|
2963
|
-
) ?? null;
|
|
2964
|
-
}
|
|
2965
|
-
function renderPlateManifestYaml(slug, title, shard) {
|
|
2966
|
-
const manifest = {
|
|
2967
|
-
name: slug,
|
|
2968
|
-
title,
|
|
2969
|
-
version: "0.1.0",
|
|
2970
|
-
description: `${title} Plate`,
|
|
2971
|
-
entry: "./dist/index.html",
|
|
2972
|
-
dev: "./src/index.tsx",
|
|
2973
|
-
api: ["GET /api/plates", "GET /api/artifacts"]
|
|
2974
|
-
};
|
|
2975
|
-
if (shard) {
|
|
2976
|
-
manifest.shard = shard;
|
|
2977
|
-
}
|
|
2978
|
-
return stringifyYaml(manifest).trimEnd() + "\n";
|
|
2979
|
-
}
|
|
2980
|
-
async function createPlate(flintPath, displayName, options = {}) {
|
|
2981
|
-
const { proper, slug } = nameFormats(displayName);
|
|
2982
|
-
if (!proper.trim()) {
|
|
2983
|
-
throw new Error("Plate name is required");
|
|
2984
|
-
}
|
|
2985
|
-
const existing = await getPlate(flintPath, slug);
|
|
2986
|
-
if (existing) {
|
|
2987
|
-
throw new Error(`Plate "${slug}" already exists`);
|
|
2988
|
-
}
|
|
2989
|
-
const platePath = join62(flintPath, "Plates", proper);
|
|
2990
|
-
if (await fileExists2(platePath)) {
|
|
2991
|
-
throw new Error(`Plate directory already exists: ${relative(flintPath, platePath)}`);
|
|
2992
|
-
}
|
|
2993
|
-
await mkdir42(join62(platePath, "src"), { recursive: true });
|
|
2994
|
-
await mkdir42(join62(platePath, "tools"), { recursive: true });
|
|
2995
|
-
await writeFile32(join62(platePath, "plate.yaml"), renderPlateManifestYaml(slug, proper, options.shard), "utf8");
|
|
2996
|
-
await writeFile32(join62(platePath, "package.json"), JSON.stringify({
|
|
2997
|
-
name: `@plates/${slug}`,
|
|
2998
|
-
private: true,
|
|
2999
|
-
version: "0.1.0",
|
|
3000
|
-
type: "module",
|
|
3001
|
-
scripts: {
|
|
3002
|
-
dev: "vite",
|
|
3003
|
-
build: "vite build"
|
|
3004
|
-
},
|
|
3005
|
-
dependencies: {
|
|
3006
|
-
"@nuucognition/plate-sdk": "workspace:*",
|
|
3007
|
-
react: "^19.0.0",
|
|
3008
|
-
"react-dom": "^19.0.0"
|
|
3009
|
-
},
|
|
3010
|
-
devDependencies: {
|
|
3011
|
-
"@types/react": "^19.0.0",
|
|
3012
|
-
"@types/react-dom": "^19.0.0",
|
|
3013
|
-
"@vitejs/plugin-react": "^4.0.0",
|
|
3014
|
-
typescript: "^5.0.0",
|
|
3015
|
-
vite: "^6.0.0"
|
|
3016
|
-
}
|
|
3017
|
-
}, null, 2) + "\n", "utf8");
|
|
3018
|
-
await writeFile32(join62(platePath, "tsconfig.json"), JSON.stringify({
|
|
3019
|
-
compilerOptions: {
|
|
3020
|
-
target: "ES2020",
|
|
3021
|
-
useDefineForClassFields: true,
|
|
3022
|
-
lib: ["DOM", "DOM.Iterable", "ES2020"],
|
|
3023
|
-
allowJs: false,
|
|
3024
|
-
skipLibCheck: true,
|
|
3025
|
-
esModuleInterop: true,
|
|
3026
|
-
allowSyntheticDefaultImports: true,
|
|
3027
|
-
strict: true,
|
|
3028
|
-
forceConsistentCasingInFileNames: true,
|
|
3029
|
-
module: "ESNext",
|
|
3030
|
-
moduleResolution: "Bundler",
|
|
3031
|
-
resolveJsonModule: true,
|
|
3032
|
-
isolatedModules: true,
|
|
3033
|
-
noEmit: true,
|
|
3034
|
-
jsx: "react-jsx"
|
|
3035
|
-
},
|
|
3036
|
-
include: ["src"]
|
|
3037
|
-
}, null, 2) + "\n", "utf8");
|
|
3038
|
-
await writeFile32(join62(platePath, "vite.config.ts"), `import { defineConfig } from 'vite';
|
|
3039
|
-
import react from '@vitejs/plugin-react';
|
|
3040
|
-
|
|
3041
|
-
export default defineConfig({
|
|
3042
|
-
base: '/plates/${slug}/',
|
|
3043
|
-
plugins: [react()],
|
|
3044
|
-
build: {
|
|
3045
|
-
outDir: 'dist',
|
|
3046
|
-
},
|
|
3047
|
-
});
|
|
3048
|
-
`, "utf8");
|
|
3049
|
-
await writeFile32(join62(platePath, "index.html"), `<!doctype html>
|
|
3050
|
-
<html lang="en">
|
|
3051
|
-
<head>
|
|
3052
|
-
<meta charset="UTF-8" />
|
|
3053
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
3054
|
-
<title>${proper}</title>
|
|
3055
|
-
</head>
|
|
3056
|
-
<body>
|
|
3057
|
-
<div id="root"></div>
|
|
3058
|
-
<script type="module" src="/src/index.tsx"></script>
|
|
3059
|
-
</body>
|
|
3060
|
-
</html>
|
|
3061
|
-
`, "utf8");
|
|
3062
|
-
await writeFile32(join62(platePath, ".gitignore"), "node_modules/\ndist/\n", "utf8");
|
|
3063
|
-
await writeFile32(join62(platePath, "src", "index.tsx"), `import React from 'react';
|
|
3064
|
-
import ReactDOM from 'react-dom/client';
|
|
3065
|
-
import { getPlateContext } from '@nuucognition/plate-sdk';
|
|
3066
|
-
import { App } from './App';
|
|
3067
|
-
|
|
3068
|
-
async function bootstrap() {
|
|
3069
|
-
let connected = false;
|
|
3070
|
-
|
|
3071
|
-
try {
|
|
3072
|
-
await getPlateContext();
|
|
3073
|
-
connected = true;
|
|
3074
|
-
} catch {
|
|
3075
|
-
connected = false;
|
|
3076
|
-
}
|
|
3077
|
-
|
|
3078
|
-
ReactDOM.createRoot(document.getElementById('root')!).render(
|
|
3079
|
-
<React.StrictMode>
|
|
3080
|
-
<App connected={connected} />
|
|
3081
|
-
</React.StrictMode>,
|
|
3082
|
-
);
|
|
3083
|
-
}
|
|
3084
|
-
|
|
3085
|
-
void bootstrap();
|
|
3086
|
-
`, "utf8");
|
|
3087
|
-
await writeFile32(join62(platePath, "src", "App.tsx"), `import { usePlateContext } from '@nuucognition/plate-sdk';
|
|
3088
|
-
|
|
3089
|
-
export function App({ connected }: { connected: boolean }) {
|
|
3090
|
-
let plateName = '${slug}';
|
|
3091
|
-
let serverUrl = 'Not connected';
|
|
3092
|
-
|
|
3093
|
-
try {
|
|
3094
|
-
const context = usePlateContext();
|
|
3095
|
-
plateName = context.plateName;
|
|
3096
|
-
serverUrl = context.serverUrl;
|
|
3097
|
-
} catch {
|
|
3098
|
-
// Render the disconnected state below.
|
|
3099
|
-
}
|
|
3100
|
-
|
|
3101
|
-
return (
|
|
3102
|
-
<main style={{ fontFamily: 'ui-sans-serif, system-ui, sans-serif', padding: 24 }}>
|
|
3103
|
-
<h1 style={{ margin: 0, fontSize: 28 }}>${proper}</h1>
|
|
3104
|
-
<p style={{ color: '#666', maxWidth: 640 }}>
|
|
3105
|
-
This is the starter Plate scaffold. Replace this view with your interface.
|
|
3106
|
-
</p>
|
|
3107
|
-
<div style={{ border: '1px solid #ddd', borderRadius: 12, padding: 16, marginTop: 24 }}>
|
|
3108
|
-
<div><strong>Plate:</strong> {plateName}</div>
|
|
3109
|
-
<div><strong>SDK:</strong> {connected ? 'Connected to Steel' : 'Standalone preview mode'}</div>
|
|
3110
|
-
<div><strong>Server:</strong> {serverUrl}</div>
|
|
3111
|
-
</div>
|
|
3112
|
-
</main>
|
|
3113
|
-
);
|
|
3114
|
-
}
|
|
3115
|
-
`, "utf8");
|
|
3116
|
-
await addPlateDeclaration(flintPath, slug, relative(flintPath, platePath), { title: proper });
|
|
3117
|
-
return await getPlate(flintPath, slug);
|
|
3118
|
-
}
|
|
3119
|
-
function resolveToolCommand(toolPath) {
|
|
3120
|
-
if (toolPath.endsWith(".ts")) {
|
|
3121
|
-
return { command: "npx", args: ["tsx", toolPath] };
|
|
3122
|
-
}
|
|
3123
|
-
if (toolPath.endsWith(".js") || toolPath.endsWith(".mjs")) {
|
|
3124
|
-
return { command: "node", args: [toolPath] };
|
|
3125
|
-
}
|
|
3126
|
-
return { command: toolPath, args: [] };
|
|
3127
|
-
}
|
|
3128
|
-
function spawnBufferedProcess(command, args, options) {
|
|
3129
|
-
return new Promise((resolvePromise, reject) => {
|
|
3130
|
-
const child = spawn(command, args, {
|
|
3131
|
-
cwd: options.cwd,
|
|
3132
|
-
env: {
|
|
3133
|
-
...process.env,
|
|
3134
|
-
...options.env
|
|
3135
|
-
},
|
|
3136
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
3137
|
-
});
|
|
3138
|
-
let stdout = "";
|
|
3139
|
-
let stderr = "";
|
|
3140
|
-
let settled = false;
|
|
3141
|
-
const finish = (result) => {
|
|
3142
|
-
if (settled) {
|
|
3143
|
-
return;
|
|
3144
|
-
}
|
|
3145
|
-
settled = true;
|
|
3146
|
-
resolvePromise(result);
|
|
3147
|
-
};
|
|
3148
|
-
const timer = options.timeoutMs ? setTimeout(() => {
|
|
3149
|
-
child.kill("SIGKILL");
|
|
3150
|
-
reject(new Error("tool_timeout"));
|
|
3151
|
-
}, options.timeoutMs) : null;
|
|
3152
|
-
child.stdout?.on("data", (chunk) => {
|
|
3153
|
-
stdout += chunk.toString();
|
|
3154
|
-
});
|
|
3155
|
-
child.stderr?.on("data", (chunk) => {
|
|
3156
|
-
stderr += chunk.toString();
|
|
3157
|
-
});
|
|
3158
|
-
child.on("error", (error) => {
|
|
3159
|
-
if (timer) clearTimeout(timer);
|
|
3160
|
-
reject(error);
|
|
3161
|
-
});
|
|
3162
|
-
child.on("close", (code) => {
|
|
3163
|
-
if (timer) clearTimeout(timer);
|
|
3164
|
-
finish({
|
|
3165
|
-
exitCode: code ?? 1,
|
|
3166
|
-
stdout: stdout.trim(),
|
|
3167
|
-
stderr: stderr.trim(),
|
|
3168
|
-
command: [command, ...args].join(" ")
|
|
3169
|
-
});
|
|
3170
|
-
});
|
|
3171
|
-
});
|
|
3172
|
-
}
|
|
3173
|
-
async function installPlateDeps(flintPath, plateName) {
|
|
3174
|
-
const plate = await getPlate(flintPath, plateName);
|
|
3175
|
-
if (!plate) {
|
|
3176
|
-
throw new Error(`Plate not found: ${plateName}`);
|
|
3177
|
-
}
|
|
3178
|
-
return spawnBufferedProcess("pnpm", ["install"], { cwd: plate.path });
|
|
3179
|
-
}
|
|
3180
|
-
async function buildPlate(flintPath, plateName) {
|
|
3181
|
-
const plate = await getPlate(flintPath, plateName);
|
|
3182
|
-
if (!plate) {
|
|
3183
|
-
throw new Error(`Plate not found: ${plateName}`);
|
|
3184
|
-
}
|
|
3185
|
-
const result = await spawnBufferedProcess("pnpm", ["build"], { cwd: plate.path });
|
|
3186
|
-
if (result.exitCode !== 0) {
|
|
3187
|
-
return result;
|
|
3188
|
-
}
|
|
3189
|
-
const entryPath = resolvePlateEntryPath(plate.path, plate.manifest);
|
|
3190
|
-
if (!await fileExists2(entryPath)) {
|
|
3191
|
-
throw new Error(`Plate build did not produce entry file: ${relative(plate.path, entryPath)}`);
|
|
3192
|
-
}
|
|
3193
|
-
return result;
|
|
3194
|
-
}
|
|
3195
|
-
async function runPlateTool(flintPath, plateName, toolName, args = [], options = {}) {
|
|
3196
|
-
const plate = await getPlate(flintPath, plateName);
|
|
3197
|
-
if (!plate) {
|
|
3198
|
-
throw new Error(`Plate not found: ${plateName}`);
|
|
3199
|
-
}
|
|
3200
|
-
const tool = plate.manifest.tools?.find((entry) => normalizePlateName(entry.name) === normalizePlateName(toolName));
|
|
3201
|
-
if (!tool) {
|
|
3202
|
-
throw new Error(`Tool not found: ${toolName}`);
|
|
3203
|
-
}
|
|
3204
|
-
const commandPath = resolve2(plate.path, tool.command);
|
|
3205
|
-
if (!await fileExists2(commandPath)) {
|
|
3206
|
-
throw new Error(`Tool command not found: ${relative(plate.path, commandPath)}`);
|
|
3207
|
-
}
|
|
3208
|
-
const runner = resolveToolCommand(commandPath);
|
|
3209
|
-
return spawnBufferedProcess(runner.command, [...runner.args, ...args], {
|
|
3210
|
-
cwd: flintPath,
|
|
3211
|
-
env: {
|
|
3212
|
-
FLINT_ROOT: resolve2(flintPath),
|
|
3213
|
-
PLATE_ROOT: plate.path,
|
|
3214
|
-
PLATE_NAME: plate.manifest.name
|
|
3215
|
-
},
|
|
3216
|
-
timeoutMs: options.timeoutMs
|
|
3217
|
-
});
|
|
3218
|
-
}
|
|
3219
|
-
async function listPlateTools(flintPath) {
|
|
3220
|
-
const plates = await listPlates(flintPath);
|
|
3221
|
-
return plates.flatMap((plate) => (plate.manifest.tools ?? []).map((tool) => ({ plate, tool })));
|
|
3222
|
-
}
|
|
3223
|
-
function spawnPlateDevServer(flintPath, plate) {
|
|
3224
|
-
return spawn("pnpm", ["dev"], {
|
|
3225
|
-
cwd: plate.path,
|
|
3226
|
-
env: {
|
|
3227
|
-
...process.env,
|
|
3228
|
-
FLINT_ROOT: resolve2(flintPath),
|
|
3229
|
-
PLATE_ROOT: plate.path,
|
|
3230
|
-
PLATE_NAME: plate.manifest.name
|
|
3231
|
-
},
|
|
3232
|
-
stdio: "inherit"
|
|
3233
|
-
});
|
|
3234
|
-
}
|
|
3235
2705
|
function getIdentityStatePath(flintPath) {
|
|
3236
|
-
return
|
|
2706
|
+
return join62(getFlintConfigDir(flintPath), "identity.json");
|
|
3237
2707
|
}
|
|
3238
2708
|
function getPersonFilePath(flintPath, name) {
|
|
3239
2709
|
const personName = name.startsWith("@") ? name : `@${name}`;
|
|
3240
|
-
return
|
|
2710
|
+
return join62(flintPath, "Mesh", "People", `${personName}.md`);
|
|
3241
2711
|
}
|
|
3242
2712
|
async function readIdentityState(flintPath) {
|
|
3243
2713
|
try {
|
|
3244
|
-
const content = await
|
|
2714
|
+
const content = await readFile22(getIdentityStatePath(flintPath), "utf-8");
|
|
3245
2715
|
return JSON.parse(content);
|
|
3246
2716
|
} catch {
|
|
3247
2717
|
return null;
|
|
@@ -3249,8 +2719,8 @@ async function readIdentityState(flintPath) {
|
|
|
3249
2719
|
}
|
|
3250
2720
|
async function writeIdentityState(flintPath, state) {
|
|
3251
2721
|
const statePath = getIdentityStatePath(flintPath);
|
|
3252
|
-
await
|
|
3253
|
-
await
|
|
2722
|
+
await mkdir42(getFlintConfigDir(flintPath), { recursive: true });
|
|
2723
|
+
await writeFile32(statePath, JSON.stringify(state, null, 2));
|
|
3254
2724
|
}
|
|
3255
2725
|
async function personExists(flintPath, name) {
|
|
3256
2726
|
try {
|
|
@@ -3262,9 +2732,9 @@ async function personExists(flintPath, name) {
|
|
|
3262
2732
|
}
|
|
3263
2733
|
async function createPersonFile(flintPath, name) {
|
|
3264
2734
|
const filePath = getPersonFilePath(flintPath, name);
|
|
3265
|
-
const dir =
|
|
3266
|
-
await
|
|
3267
|
-
await
|
|
2735
|
+
const dir = join62(flintPath, "Mesh", "People");
|
|
2736
|
+
await mkdir42(dir, { recursive: true });
|
|
2737
|
+
await writeFile32(filePath, "");
|
|
3268
2738
|
return filePath;
|
|
3269
2739
|
}
|
|
3270
2740
|
async function setIdentity(flintPath, name) {
|
|
@@ -3289,19 +2759,19 @@ function parseArtifactFile(content) {
|
|
|
3289
2759
|
return { frontmatter: {}, body: content };
|
|
3290
2760
|
}
|
|
3291
2761
|
const frontmatterSource = match[1] ?? "";
|
|
3292
|
-
const frontmatter =
|
|
2762
|
+
const frontmatter = parseYaml(frontmatterSource, { logLevel: "error" }) ?? {};
|
|
3293
2763
|
const body = content.slice(match[0].length);
|
|
3294
2764
|
return { frontmatter, body };
|
|
3295
2765
|
}
|
|
3296
2766
|
function stringifyArtifact(frontmatter, body) {
|
|
3297
2767
|
return `---
|
|
3298
|
-
${
|
|
2768
|
+
${stringifyYaml(frontmatter).trimEnd()}
|
|
3299
2769
|
---
|
|
3300
2770
|
|
|
3301
2771
|
${body.trimStart()}`;
|
|
3302
2772
|
}
|
|
3303
2773
|
function normalizeRelativePath(flintPath, filePath) {
|
|
3304
|
-
return
|
|
2774
|
+
return relative(flintPath, filePath).replace(/\\/g, "/");
|
|
3305
2775
|
}
|
|
3306
2776
|
function getArtifactTitleFromFilename(filename) {
|
|
3307
2777
|
return filename.endsWith(".md") ? filename.slice(0, -3) : filename;
|
|
@@ -3335,10 +2805,10 @@ function normalizeIncrement(value) {
|
|
|
3335
2805
|
}
|
|
3336
2806
|
var SKIP_DIRS = /* @__PURE__ */ new Set(["Agents", "Archive", "node_modules", ".git"]);
|
|
3337
2807
|
async function collectMarkdownFiles(dir, skipDirs = SKIP_DIRS) {
|
|
3338
|
-
const entries = await
|
|
2808
|
+
const entries = await readdir22(dir, { withFileTypes: true }).catch(() => []);
|
|
3339
2809
|
const files = [];
|
|
3340
2810
|
for (const entry of entries) {
|
|
3341
|
-
const entryPath =
|
|
2811
|
+
const entryPath = join72(dir, entry.name);
|
|
3342
2812
|
if (entry.isDirectory()) {
|
|
3343
2813
|
if (skipDirs.has(entry.name)) continue;
|
|
3344
2814
|
files.push(...await collectMarkdownFiles(entryPath, skipDirs));
|
|
@@ -3354,7 +2824,7 @@ function syntheticId(relativePath) {
|
|
|
3354
2824
|
return createHash("sha256").update(relativePath).digest("hex").slice(0, 32);
|
|
3355
2825
|
}
|
|
3356
2826
|
async function readArtifactAtPath(flintPath, filePath) {
|
|
3357
|
-
const content = await
|
|
2827
|
+
const content = await readFile32(filePath, "utf8").catch(() => null);
|
|
3358
2828
|
if (content === null) return null;
|
|
3359
2829
|
const parsed = parseArtifactFile(content);
|
|
3360
2830
|
const relPath = normalizeRelativePath(flintPath, filePath);
|
|
@@ -3362,15 +2832,15 @@ async function readArtifactAtPath(flintPath, filePath) {
|
|
|
3362
2832
|
return {
|
|
3363
2833
|
id,
|
|
3364
2834
|
path: relPath,
|
|
3365
|
-
filename:
|
|
2835
|
+
filename: basename(filePath),
|
|
3366
2836
|
frontmatter: parsed.frontmatter,
|
|
3367
2837
|
body: parsed.body
|
|
3368
2838
|
};
|
|
3369
2839
|
}
|
|
3370
2840
|
async function collectAllArtifactFiles(flintPath) {
|
|
3371
2841
|
const [meshFiles, shardFiles] = await Promise.all([
|
|
3372
|
-
collectMarkdownFiles(
|
|
3373
|
-
collectMarkdownFiles(
|
|
2842
|
+
collectMarkdownFiles(join72(flintPath, "Mesh")),
|
|
2843
|
+
collectMarkdownFiles(join72(flintPath, "Shards"))
|
|
3374
2844
|
]);
|
|
3375
2845
|
return [...meshFiles, ...shardFiles];
|
|
3376
2846
|
}
|
|
@@ -3452,7 +2922,7 @@ function sanitizeOffset(offset) {
|
|
|
3452
2922
|
return Math.max(0, Math.trunc(offset));
|
|
3453
2923
|
}
|
|
3454
2924
|
async function queryArtifacts(flintPath, query = {}) {
|
|
3455
|
-
const files = query.includeShards ? await collectAllArtifactFiles(flintPath) : await collectMarkdownFiles(
|
|
2925
|
+
const files = query.includeShards ? await collectAllArtifactFiles(flintPath) : await collectMarkdownFiles(join72(flintPath, "Mesh"));
|
|
3456
2926
|
const records = await Promise.all(files.map((filePath) => readArtifactAtPath(flintPath, filePath)));
|
|
3457
2927
|
const matching = records.filter((record) => record !== null).filter((record) => matchesArtifactQuery(record, query)).sort((left, right) => compareArtifactSearchMatch(left, right, query));
|
|
3458
2928
|
const limit = sanitizeLimit(query.limit);
|
|
@@ -3487,19 +2957,19 @@ async function updateArtifactById(flintPath, id, patch) {
|
|
|
3487
2957
|
...patch.frontmatter ?? {}
|
|
3488
2958
|
};
|
|
3489
2959
|
const nextBody = patch.body ?? found.artifact.body;
|
|
3490
|
-
await
|
|
2960
|
+
await writeFile42(found.absolutePath, stringifyArtifact(nextFrontmatter, nextBody), "utf8");
|
|
3491
2961
|
return (await getArtifactById(flintPath, id))?.artifact ?? null;
|
|
3492
2962
|
}
|
|
3493
2963
|
function getArchiveDestination(flintPath, absolutePath) {
|
|
3494
|
-
const meshRoot =
|
|
3495
|
-
const relativeToMesh =
|
|
2964
|
+
const meshRoot = join72(flintPath, "Mesh");
|
|
2965
|
+
const relativeToMesh = relative(meshRoot, absolutePath).replace(/\\/g, "/");
|
|
3496
2966
|
if (relativeToMesh.startsWith("Archive/")) {
|
|
3497
2967
|
throw new Error("Artifact is already archived");
|
|
3498
2968
|
}
|
|
3499
2969
|
if (relativeToMesh.startsWith("Types/")) {
|
|
3500
|
-
return
|
|
2970
|
+
return join72(meshRoot, "Archive", relativeToMesh.slice("Types/".length));
|
|
3501
2971
|
}
|
|
3502
|
-
return
|
|
2972
|
+
return join72(meshRoot, "Archive", relativeToMesh);
|
|
3503
2973
|
}
|
|
3504
2974
|
async function deleteArtifactById(flintPath, id, options = {}) {
|
|
3505
2975
|
const found = await getArtifactById(flintPath, id);
|
|
@@ -3507,18 +2977,18 @@ async function deleteArtifactById(flintPath, id, options = {}) {
|
|
|
3507
2977
|
return null;
|
|
3508
2978
|
}
|
|
3509
2979
|
if (!options.archive) {
|
|
3510
|
-
await
|
|
2980
|
+
await rm6(found.absolutePath);
|
|
3511
2981
|
return {
|
|
3512
2982
|
artifact: found.artifact,
|
|
3513
2983
|
archived: false
|
|
3514
2984
|
};
|
|
3515
2985
|
}
|
|
3516
2986
|
const destinationPath = getArchiveDestination(flintPath, found.absolutePath);
|
|
3517
|
-
const existing = await
|
|
2987
|
+
const existing = await readFile32(destinationPath, "utf8").then(() => true).catch(() => false);
|
|
3518
2988
|
if (existing) {
|
|
3519
2989
|
throw new Error(`Archive destination already exists: ${normalizeRelativePath(flintPath, destinationPath)}`);
|
|
3520
2990
|
}
|
|
3521
|
-
await
|
|
2991
|
+
await mkdir52(dirname22(destinationPath), { recursive: true });
|
|
3522
2992
|
await rename5(found.absolutePath, destinationPath);
|
|
3523
2993
|
const archivedArtifact = await readArtifactAtPath(flintPath, destinationPath);
|
|
3524
2994
|
if (!archivedArtifact) {
|
|
@@ -3577,7 +3047,7 @@ async function renameArtifact(flintPath, id, newTitle) {
|
|
|
3577
3047
|
return null;
|
|
3578
3048
|
}
|
|
3579
3049
|
const nextTitle = normalizeNewArtifactTitle(newTitle);
|
|
3580
|
-
const oldFilename =
|
|
3050
|
+
const oldFilename = basename(found.absolutePath);
|
|
3581
3051
|
const oldTitle = getArtifactTitleFromFilename(oldFilename);
|
|
3582
3052
|
const nextFilename = buildRenamedFilename(oldFilename, nextTitle);
|
|
3583
3053
|
const nextLinkTitle = getArtifactTitleFromFilename(nextFilename);
|
|
@@ -3589,19 +3059,19 @@ async function renameArtifact(flintPath, id, newTitle) {
|
|
|
3589
3059
|
modifiedFiles: []
|
|
3590
3060
|
};
|
|
3591
3061
|
}
|
|
3592
|
-
const destinationPath =
|
|
3593
|
-
const existing = await
|
|
3062
|
+
const destinationPath = join72(dirname22(found.absolutePath), nextFilename);
|
|
3063
|
+
const existing = await readFile32(destinationPath, "utf8").then(() => true).catch(() => false);
|
|
3594
3064
|
if (existing) {
|
|
3595
3065
|
throw new Error(`Artifact already exists at ${normalizeRelativePath(flintPath, destinationPath)}`);
|
|
3596
3066
|
}
|
|
3597
3067
|
await rename5(found.absolutePath, destinationPath);
|
|
3598
|
-
const meshFiles = await collectMarkdownFiles(
|
|
3068
|
+
const meshFiles = await collectMarkdownFiles(join72(flintPath, "Mesh"));
|
|
3599
3069
|
const modifiedFiles = /* @__PURE__ */ new Set([normalizeRelativePath(flintPath, destinationPath)]);
|
|
3600
3070
|
for (const filePath of meshFiles) {
|
|
3601
|
-
const content = await
|
|
3071
|
+
const content = await readFile32(filePath, "utf8");
|
|
3602
3072
|
const nextContent = rewriteWikilinks(content, oldTitle, nextLinkTitle);
|
|
3603
3073
|
if (nextContent !== content) {
|
|
3604
|
-
await
|
|
3074
|
+
await writeFile42(filePath, nextContent, "utf8");
|
|
3605
3075
|
modifiedFiles.add(normalizeRelativePath(flintPath, filePath));
|
|
3606
3076
|
}
|
|
3607
3077
|
}
|
|
@@ -3622,8 +3092,8 @@ function extractNumberFromFilename(filename, typeName) {
|
|
|
3622
3092
|
return number ? Number.parseInt(number, 10) : null;
|
|
3623
3093
|
}
|
|
3624
3094
|
async function getNextTypedArtifactNumber(flintPath, typeName) {
|
|
3625
|
-
const files = await collectMarkdownFiles(
|
|
3626
|
-
const numbers = files.map((filePath) => extractNumberFromFilename(
|
|
3095
|
+
const files = await collectMarkdownFiles(join72(flintPath, "Mesh"));
|
|
3096
|
+
const numbers = files.map((filePath) => extractNumberFromFilename(basename(filePath), typeName)).filter((value) => value !== null);
|
|
3627
3097
|
return numbers.length > 0 ? Math.max(...numbers) + 1 : 1;
|
|
3628
3098
|
}
|
|
3629
3099
|
function asStringArray(value) {
|
|
@@ -3708,9 +3178,9 @@ async function createTaskArtifact(flintPath, data) {
|
|
|
3708
3178
|
...notes.length > 0 ? notes.map((note) => `- ${note}`) : ["-"],
|
|
3709
3179
|
""
|
|
3710
3180
|
];
|
|
3711
|
-
const filePath =
|
|
3712
|
-
await
|
|
3713
|
-
await
|
|
3181
|
+
const filePath = join72(flintPath, "Mesh", "Types", "Tasks", `(Task) ${number} ${title}.md`);
|
|
3182
|
+
await mkdir52(dirname22(filePath), { recursive: true });
|
|
3183
|
+
await writeFile42(filePath, stringifyArtifact(frontmatter, bodyLines.join("\n")), "utf8");
|
|
3714
3184
|
const created = await readArtifactAtPath(flintPath, filePath);
|
|
3715
3185
|
if (!created) {
|
|
3716
3186
|
throw new Error("Failed to create task artifact");
|
|
@@ -3731,9 +3201,9 @@ async function createNoteArtifact(flintPath, tag, data) {
|
|
|
3731
3201
|
frontmatter.authors = [`[[${identity.person}]]`];
|
|
3732
3202
|
}
|
|
3733
3203
|
const body = typeof data.body === "string" && data.body.trim() ? data.body.trim() : "";
|
|
3734
|
-
const filePath =
|
|
3735
|
-
await
|
|
3736
|
-
await
|
|
3204
|
+
const filePath = join72(flintPath, "Mesh", "Notes", `${title}.md`);
|
|
3205
|
+
await mkdir52(dirname22(filePath), { recursive: true });
|
|
3206
|
+
await writeFile42(filePath, stringifyArtifact(frontmatter, body), "utf8");
|
|
3737
3207
|
const created = await readArtifactAtPath(flintPath, filePath);
|
|
3738
3208
|
if (!created) {
|
|
3739
3209
|
throw new Error("Failed to create note artifact");
|
|
@@ -3804,9 +3274,9 @@ async function createProposalArtifact(flintPath, data) {
|
|
|
3804
3274
|
...notes.length > 0 ? notes.map((note) => `- ${note}`) : ["-"],
|
|
3805
3275
|
""
|
|
3806
3276
|
];
|
|
3807
|
-
const filePath =
|
|
3808
|
-
await
|
|
3809
|
-
await
|
|
3277
|
+
const filePath = join72(flintPath, "Mesh", "Types", "Proposals", `(Proposal) ${number} ${title}.md`);
|
|
3278
|
+
await mkdir52(dirname22(filePath), { recursive: true });
|
|
3279
|
+
await writeFile42(filePath, stringifyArtifact(frontmatter, bodyLines.join("\n")), "utf8");
|
|
3810
3280
|
const created = await readArtifactAtPath(flintPath, filePath);
|
|
3811
3281
|
if (!created) {
|
|
3812
3282
|
throw new Error("Failed to create proposal artifact");
|
|
@@ -3814,9 +3284,9 @@ async function createProposalArtifact(flintPath, data) {
|
|
|
3814
3284
|
return created;
|
|
3815
3285
|
}
|
|
3816
3286
|
async function writeStubExclusive(basePath, content) {
|
|
3817
|
-
await
|
|
3287
|
+
await mkdir52(dirname22(basePath), { recursive: true });
|
|
3818
3288
|
try {
|
|
3819
|
-
await
|
|
3289
|
+
await writeFile42(basePath, content, { flag: "wx" });
|
|
3820
3290
|
return basePath;
|
|
3821
3291
|
} catch (err) {
|
|
3822
3292
|
if (err.code !== "EEXIST") throw err;
|
|
@@ -3826,7 +3296,7 @@ async function writeStubExclusive(basePath, content) {
|
|
|
3826
3296
|
for (let n = 2; n < 1e4; n++) {
|
|
3827
3297
|
const candidate = `${stem} ${n}${ext}`;
|
|
3828
3298
|
try {
|
|
3829
|
-
await
|
|
3299
|
+
await writeFile42(candidate, content, { flag: "wx" });
|
|
3830
3300
|
return candidate;
|
|
3831
3301
|
} catch (err) {
|
|
3832
3302
|
if (err.code !== "EEXIST") throw err;
|
|
@@ -3834,6 +3304,33 @@ async function writeStubExclusive(basePath, content) {
|
|
|
3834
3304
|
}
|
|
3835
3305
|
throw new Error(`Could not find available stub number for ${basePath}`);
|
|
3836
3306
|
}
|
|
3307
|
+
async function createNotepadArtifact(flintPath, data) {
|
|
3308
|
+
const title = typeof data.title === "string" && data.title.trim() ? data.title.trim() : "New Notepad";
|
|
3309
|
+
const number = String(await getNextTypedArtifactNumber(flintPath, "Notepad")).padStart(3, "0");
|
|
3310
|
+
const identity = await getIdentity(flintPath);
|
|
3311
|
+
const frontmatter = {
|
|
3312
|
+
id: randomUUID3(),
|
|
3313
|
+
tags: ["#ntpd/notepad"],
|
|
3314
|
+
status: "active",
|
|
3315
|
+
template: "[[tmp-ntpd-notepad-v1.0]]"
|
|
3316
|
+
};
|
|
3317
|
+
if (identity) frontmatter.authors = [`[[${identity.person}]]`];
|
|
3318
|
+
const initialMessage = typeof data.initialMessage === "string" && data.initialMessage.trim() ? data.initialMessage.trim() : "";
|
|
3319
|
+
const bodyLines = [
|
|
3320
|
+
"# 1",
|
|
3321
|
+
"",
|
|
3322
|
+
initialMessage,
|
|
3323
|
+
""
|
|
3324
|
+
];
|
|
3325
|
+
const filePath = join72(flintPath, "Mesh", "Types", "Notepads", `(Notepad) ${number} ${title}.md`);
|
|
3326
|
+
await mkdir52(dirname22(filePath), { recursive: true });
|
|
3327
|
+
await writeFile42(filePath, stringifyArtifact(frontmatter, bodyLines.join("\n")), "utf8");
|
|
3328
|
+
const created = await readArtifactAtPath(flintPath, filePath);
|
|
3329
|
+
if (!created) {
|
|
3330
|
+
throw new Error("Failed to create notepad artifact");
|
|
3331
|
+
}
|
|
3332
|
+
return created;
|
|
3333
|
+
}
|
|
3837
3334
|
async function createStubArtifact(flintPath, data) {
|
|
3838
3335
|
const relativePath = typeof data.path === "string" ? data.path : "";
|
|
3839
3336
|
if (!relativePath) {
|
|
@@ -3855,7 +3352,7 @@ async function createStubArtifact(flintPath, data) {
|
|
|
3855
3352
|
|
|
3856
3353
|
This artifact is being created by an agent session. Content will replace this stub shortly.
|
|
3857
3354
|
`;
|
|
3858
|
-
const basePath =
|
|
3355
|
+
const basePath = join72(flintPath, relativePath);
|
|
3859
3356
|
const filePath = await writeStubExclusive(basePath, stringifyArtifact(frontmatter, body));
|
|
3860
3357
|
const created = await readArtifactAtPath(flintPath, filePath);
|
|
3861
3358
|
if (!created) {
|
|
@@ -3871,6 +3368,9 @@ async function createArtifactFromTemplate(flintPath, request) {
|
|
|
3871
3368
|
case "tmp-prop-proposal-v0.1":
|
|
3872
3369
|
case "tmp-prop-proposal":
|
|
3873
3370
|
return createProposalArtifact(flintPath, request.data);
|
|
3371
|
+
case "tmp-ntpd-notepad-v1.0":
|
|
3372
|
+
case "tmp-ntpd-notepad":
|
|
3373
|
+
return createNotepadArtifact(flintPath, request.data);
|
|
3874
3374
|
case "tmp-f-concept-v0.1":
|
|
3875
3375
|
return createNoteArtifact(flintPath, "#note/concept", request.data);
|
|
3876
3376
|
case "tmp-f-record-v0.1":
|
|
@@ -3881,24 +3381,24 @@ async function createArtifactFromTemplate(flintPath, request) {
|
|
|
3881
3381
|
throw new Error(`Unsupported template: ${request.template}`);
|
|
3882
3382
|
}
|
|
3883
3383
|
}
|
|
3884
|
-
var
|
|
3384
|
+
var execAsync2 = promisify2(exec2);
|
|
3885
3385
|
async function pathExists2(path) {
|
|
3886
3386
|
try {
|
|
3887
|
-
await
|
|
3387
|
+
await stat42(path);
|
|
3888
3388
|
return true;
|
|
3889
3389
|
} catch {
|
|
3890
3390
|
return false;
|
|
3891
3391
|
}
|
|
3892
3392
|
}
|
|
3893
3393
|
function getWorkspaceRepositoriesDir(flintPath) {
|
|
3894
|
-
return
|
|
3394
|
+
return join82(flintPath, "Workspace", "Repos");
|
|
3895
3395
|
}
|
|
3896
3396
|
function getRepositoryPath(flintPath, name) {
|
|
3897
|
-
return
|
|
3397
|
+
return join82(getWorkspaceRepositoriesDir(flintPath), name);
|
|
3898
3398
|
}
|
|
3899
3399
|
async function createRepository(flintPath, name, remote) {
|
|
3900
3400
|
const repositoriesDir = getWorkspaceRepositoriesDir(flintPath);
|
|
3901
|
-
await
|
|
3401
|
+
await mkdir6(repositoriesDir, { recursive: true });
|
|
3902
3402
|
const repoPath = getRepositoryPath(flintPath, name);
|
|
3903
3403
|
if (await pathExists2(repoPath)) {
|
|
3904
3404
|
throw new Error(`Repository folder already exists: ${repoPath}`);
|
|
@@ -3906,25 +3406,25 @@ async function createRepository(flintPath, name, remote) {
|
|
|
3906
3406
|
if (remote) {
|
|
3907
3407
|
return cloneRepository(flintPath, name, remote);
|
|
3908
3408
|
}
|
|
3909
|
-
await
|
|
3409
|
+
await mkdir6(repoPath, { recursive: true });
|
|
3910
3410
|
try {
|
|
3911
|
-
await
|
|
3411
|
+
await execAsync2("git init", { cwd: repoPath });
|
|
3912
3412
|
} catch (error) {
|
|
3913
3413
|
const message = error instanceof Error ? error.message : String(error);
|
|
3914
|
-
await
|
|
3414
|
+
await rm22(repoPath, { recursive: true, force: true });
|
|
3915
3415
|
throw new Error(`Failed to initialize repository: ${message}`);
|
|
3916
3416
|
}
|
|
3917
3417
|
return repoPath;
|
|
3918
3418
|
}
|
|
3919
3419
|
async function cloneRepository(flintPath, name, url) {
|
|
3920
3420
|
const repositoriesDir = getWorkspaceRepositoriesDir(flintPath);
|
|
3921
|
-
await
|
|
3421
|
+
await mkdir6(repositoriesDir, { recursive: true });
|
|
3922
3422
|
const repoPath = getRepositoryPath(flintPath, name);
|
|
3923
3423
|
if (await pathExists2(repoPath)) {
|
|
3924
3424
|
throw new Error(`Repository folder already exists: ${repoPath}`);
|
|
3925
3425
|
}
|
|
3926
3426
|
try {
|
|
3927
|
-
await
|
|
3427
|
+
await execAsync2(`git clone "${url}" "${repoPath}"`);
|
|
3928
3428
|
} catch (error) {
|
|
3929
3429
|
const message = error instanceof Error ? error.message : String(error);
|
|
3930
3430
|
throw new Error(`Failed to clone repository: ${message}`);
|
|
@@ -3936,19 +3436,19 @@ async function removeRepositoryFolder(flintPath, name) {
|
|
|
3936
3436
|
if (!await pathExists2(repoPath)) {
|
|
3937
3437
|
return false;
|
|
3938
3438
|
}
|
|
3939
|
-
await
|
|
3439
|
+
await rm22(repoPath, { recursive: true, force: true });
|
|
3940
3440
|
return true;
|
|
3941
3441
|
}
|
|
3942
3442
|
async function updateRepository(flintPath, name, url) {
|
|
3943
3443
|
const repoPath = getRepositoryPath(flintPath, name);
|
|
3944
3444
|
if (await pathExists2(repoPath)) {
|
|
3945
3445
|
try {
|
|
3946
|
-
await
|
|
3446
|
+
await execAsync2("git rev-parse HEAD", { cwd: repoPath });
|
|
3947
3447
|
} catch {
|
|
3948
|
-
await
|
|
3448
|
+
await rm22(repoPath, { recursive: true, force: true });
|
|
3949
3449
|
return cloneRepository(flintPath, name, url);
|
|
3950
3450
|
}
|
|
3951
|
-
await
|
|
3451
|
+
await execAsync2("git pull", { cwd: repoPath });
|
|
3952
3452
|
return repoPath;
|
|
3953
3453
|
}
|
|
3954
3454
|
return cloneRepository(flintPath, name, url);
|
|
@@ -3969,27 +3469,27 @@ async function getRepositoryStatus(flintPath) {
|
|
|
3969
3469
|
return statuses;
|
|
3970
3470
|
}
|
|
3971
3471
|
function getSourceRepositoriesDir(flintPath) {
|
|
3972
|
-
return
|
|
3472
|
+
return join82(flintPath, "Sources", "Repos");
|
|
3973
3473
|
}
|
|
3974
3474
|
function getSourceRepositoryPath(flintPath, name) {
|
|
3975
|
-
return
|
|
3475
|
+
return join82(getSourceRepositoriesDir(flintPath), name);
|
|
3976
3476
|
}
|
|
3977
3477
|
async function cloneSourceRepository(flintPath, name, url) {
|
|
3978
3478
|
const repositoriesDir = getSourceRepositoriesDir(flintPath);
|
|
3979
|
-
await
|
|
3479
|
+
await mkdir6(repositoriesDir, { recursive: true });
|
|
3980
3480
|
const repoPath = getSourceRepositoryPath(flintPath, name);
|
|
3981
3481
|
if (await pathExists2(repoPath)) {
|
|
3982
3482
|
throw new Error(`Source repository folder already exists: ${repoPath}`);
|
|
3983
3483
|
}
|
|
3984
3484
|
try {
|
|
3985
|
-
await
|
|
3485
|
+
await execAsync2(`git clone --depth 1 "${url}" "${repoPath}"`);
|
|
3986
3486
|
} catch (error) {
|
|
3987
3487
|
const message = error instanceof Error ? error.message : String(error);
|
|
3988
3488
|
throw new Error(`Failed to clone source repository: ${message}`);
|
|
3989
3489
|
}
|
|
3990
|
-
const gitDir =
|
|
3490
|
+
const gitDir = join82(repoPath, ".git");
|
|
3991
3491
|
try {
|
|
3992
|
-
await
|
|
3492
|
+
await rm22(gitDir, { recursive: true, force: true });
|
|
3993
3493
|
} catch {
|
|
3994
3494
|
}
|
|
3995
3495
|
return repoPath;
|
|
@@ -3999,7 +3499,7 @@ async function removeSourceRepositoryFolder(flintPath, name) {
|
|
|
3999
3499
|
if (!await pathExists2(repoPath)) {
|
|
4000
3500
|
return false;
|
|
4001
3501
|
}
|
|
4002
|
-
await
|
|
3502
|
+
await rm22(repoPath, { recursive: true, force: true });
|
|
4003
3503
|
return true;
|
|
4004
3504
|
}
|
|
4005
3505
|
async function updateSourceRepository(flintPath, name, url) {
|
|
@@ -4022,12 +3522,12 @@ async function getSourceRepositoryStatus(flintPath) {
|
|
|
4022
3522
|
return statuses;
|
|
4023
3523
|
}
|
|
4024
3524
|
function getStatePath(flintPath) {
|
|
4025
|
-
return
|
|
3525
|
+
return join92(getFlintConfigDir(flintPath), "references.json");
|
|
4026
3526
|
}
|
|
4027
3527
|
async function readReferencesState(flintPath) {
|
|
4028
3528
|
const statePath = getStatePath(flintPath);
|
|
4029
3529
|
try {
|
|
4030
|
-
const content = await
|
|
3530
|
+
const content = await readFile42(statePath, "utf-8");
|
|
4031
3531
|
const parsed = JSON.parse(content);
|
|
4032
3532
|
if (parsed.version === 2) {
|
|
4033
3533
|
return parsed;
|
|
@@ -4040,8 +3540,8 @@ async function readReferencesState(flintPath) {
|
|
|
4040
3540
|
async function writeReferencesState(flintPath, state) {
|
|
4041
3541
|
const statePath = getStatePath(flintPath);
|
|
4042
3542
|
const dir = getFlintConfigDir(flintPath);
|
|
4043
|
-
await
|
|
4044
|
-
await
|
|
3543
|
+
await mkdir7(dir, { recursive: true });
|
|
3544
|
+
await writeFile52(statePath, JSON.stringify(state, null, 2) + "\n");
|
|
4045
3545
|
}
|
|
4046
3546
|
async function getCodebaseDeclarations(flintPath) {
|
|
4047
3547
|
const config = await readFlintToml(flintPath);
|
|
@@ -4103,7 +3603,7 @@ async function removeDeclaration(flintPath, name) {
|
|
|
4103
3603
|
}
|
|
4104
3604
|
async function pathExists22(p) {
|
|
4105
3605
|
try {
|
|
4106
|
-
await
|
|
3606
|
+
await stat52(p);
|
|
4107
3607
|
return true;
|
|
4108
3608
|
} catch {
|
|
4109
3609
|
return false;
|
|
@@ -4159,7 +3659,7 @@ async function unfulfill(flintPath, name) {
|
|
|
4159
3659
|
state.flints = state.flints.filter((f) => f.name.toLowerCase() !== name.toLowerCase());
|
|
4160
3660
|
await writeReferencesState(flintPath, state);
|
|
4161
3661
|
}
|
|
4162
|
-
async function
|
|
3662
|
+
async function resolve2(flintPath, type, name) {
|
|
4163
3663
|
const state = await readReferencesState(flintPath);
|
|
4164
3664
|
const normalized = name.toLowerCase();
|
|
4165
3665
|
if (type === "codebase") {
|
|
@@ -4262,29 +3762,29 @@ async function autoFulfillFlints(flintPath) {
|
|
|
4262
3762
|
return { fulfilled, failed };
|
|
4263
3763
|
}
|
|
4264
3764
|
function getReferencesMetadataDir(flintPath) {
|
|
4265
|
-
return
|
|
3765
|
+
return join92(flintPath, "Mesh", "Metadata", "References");
|
|
4266
3766
|
}
|
|
4267
3767
|
function getCodebaseMetadataDir(flintPath) {
|
|
4268
|
-
return
|
|
3768
|
+
return join92(flintPath, "Mesh", "Metadata", "References", "Codebase");
|
|
4269
3769
|
}
|
|
4270
3770
|
function getFlintMetadataDir(flintPath) {
|
|
4271
|
-
return
|
|
3771
|
+
return join92(flintPath, "Mesh", "Metadata", "References", "Flints");
|
|
4272
3772
|
}
|
|
4273
3773
|
function getCodebaseMetadataPath(flintPath, name) {
|
|
4274
3774
|
const { snake } = nameFormats(name);
|
|
4275
|
-
return
|
|
3775
|
+
return join92(getCodebaseMetadataDir(flintPath), `rf-cb-${snake}.md`);
|
|
4276
3776
|
}
|
|
4277
3777
|
function getFlintMetadataPath(flintPath, name) {
|
|
4278
3778
|
const { snake } = nameFormats(name);
|
|
4279
|
-
return
|
|
3779
|
+
return join92(getFlintMetadataDir(flintPath), `rf-fl-${snake}.md`);
|
|
4280
3780
|
}
|
|
4281
3781
|
async function ensureReferenceMetadataDirs(flintPath) {
|
|
4282
|
-
await
|
|
4283
|
-
await
|
|
3782
|
+
await mkdir7(getCodebaseMetadataDir(flintPath), { recursive: true });
|
|
3783
|
+
await mkdir7(getFlintMetadataDir(flintPath), { recursive: true });
|
|
4284
3784
|
}
|
|
4285
3785
|
async function extractMetadataPreserved(filePath) {
|
|
4286
3786
|
try {
|
|
4287
|
-
const content = await
|
|
3787
|
+
const content = await readFile42(filePath, "utf-8");
|
|
4288
3788
|
const idMatch = content.match(/^id:\s*(.+)$/m);
|
|
4289
3789
|
const id = idMatch ? idMatch[1].trim() : randomUUID22();
|
|
4290
3790
|
const notesMatch = content.match(/## Notes\n([\s\S]*)$/);
|
|
@@ -4311,11 +3811,11 @@ Execute \`flint resolve codebase "${name}"\` to get the local path.
|
|
|
4311
3811
|
${notes}
|
|
4312
3812
|
`;
|
|
4313
3813
|
try {
|
|
4314
|
-
const existing = await
|
|
3814
|
+
const existing = await readFile42(filePath, "utf-8");
|
|
4315
3815
|
if (existing === content) return false;
|
|
4316
3816
|
} catch {
|
|
4317
3817
|
}
|
|
4318
|
-
await
|
|
3818
|
+
await writeFile52(filePath, content);
|
|
4319
3819
|
return true;
|
|
4320
3820
|
}
|
|
4321
3821
|
async function generateFlintMetadata(flintPath, name) {
|
|
@@ -4335,11 +3835,11 @@ Execute \`flint resolve flint "${name}"\` to get the local path.
|
|
|
4335
3835
|
${notes}
|
|
4336
3836
|
`;
|
|
4337
3837
|
try {
|
|
4338
|
-
const existing = await
|
|
3838
|
+
const existing = await readFile42(filePath, "utf-8");
|
|
4339
3839
|
if (existing === content) return false;
|
|
4340
3840
|
} catch {
|
|
4341
3841
|
}
|
|
4342
|
-
await
|
|
3842
|
+
await writeFile52(filePath, content);
|
|
4343
3843
|
return true;
|
|
4344
3844
|
}
|
|
4345
3845
|
async function syncReferenceMetadata(flintPath) {
|
|
@@ -4367,14 +3867,14 @@ async function syncReferenceMetadata(flintPath) {
|
|
|
4367
3867
|
}
|
|
4368
3868
|
}
|
|
4369
3869
|
const removed = [];
|
|
4370
|
-
const { readdir:
|
|
3870
|
+
const { readdir: readdir9 } = await import("fs/promises");
|
|
4371
3871
|
try {
|
|
4372
3872
|
const cbDir = getCodebaseMetadataDir(flintPath);
|
|
4373
|
-
const files = await
|
|
3873
|
+
const files = await readdir9(cbDir);
|
|
4374
3874
|
const declaredSnakes = new Set(codebaseDecls.map((d) => `rf-cb-${nameFormats(d.name).snake}.md`));
|
|
4375
3875
|
for (const file of files) {
|
|
4376
3876
|
if (file.startsWith("rf-cb-") && !declaredSnakes.has(file)) {
|
|
4377
|
-
await
|
|
3877
|
+
await rm32(join92(cbDir, file)).catch(() => {
|
|
4378
3878
|
});
|
|
4379
3879
|
removed.push(file.replace(".md", ""));
|
|
4380
3880
|
}
|
|
@@ -4383,11 +3883,11 @@ async function syncReferenceMetadata(flintPath) {
|
|
|
4383
3883
|
}
|
|
4384
3884
|
try {
|
|
4385
3885
|
const flDir = getFlintMetadataDir(flintPath);
|
|
4386
|
-
const files = await
|
|
3886
|
+
const files = await readdir9(flDir);
|
|
4387
3887
|
const declaredSnakes = new Set(flintDecls.map((d) => `rf-fl-${nameFormats(d.name).snake}.md`));
|
|
4388
3888
|
for (const file of files) {
|
|
4389
3889
|
if (file.startsWith("rf-fl-") && !declaredSnakes.has(file)) {
|
|
4390
|
-
await
|
|
3890
|
+
await rm32(join92(flDir, file)).catch(() => {
|
|
4391
3891
|
});
|
|
4392
3892
|
removed.push(file.replace(".md", ""));
|
|
4393
3893
|
}
|
|
@@ -4396,7 +3896,7 @@ async function syncReferenceMetadata(flintPath) {
|
|
|
4396
3896
|
}
|
|
4397
3897
|
return { created, removed, unchanged };
|
|
4398
3898
|
}
|
|
4399
|
-
var execFileAsync =
|
|
3899
|
+
var execFileAsync = promisify3(execFile);
|
|
4400
3900
|
var TINDERBOX_CONFIG_FILENAME = "tinderbox.toml";
|
|
4401
3901
|
function isRecord(value) {
|
|
4402
3902
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
@@ -4414,7 +3914,7 @@ function isDirectionalConnection(value) {
|
|
|
4414
3914
|
return "from" in value && "to" in value;
|
|
4415
3915
|
}
|
|
4416
3916
|
function getConfigPath(root) {
|
|
4417
|
-
return
|
|
3917
|
+
return join102(root, TINDERBOX_CONFIG_FILENAME);
|
|
4418
3918
|
}
|
|
4419
3919
|
function getTinderboxFlintMode(declaration) {
|
|
4420
3920
|
if (declaration.mode) {
|
|
@@ -4427,7 +3927,7 @@ function getTinderboxFolderName(name) {
|
|
|
4427
3927
|
}
|
|
4428
3928
|
async function pathExists3(path) {
|
|
4429
3929
|
try {
|
|
4430
|
-
await
|
|
3930
|
+
await stat62(path);
|
|
4431
3931
|
return true;
|
|
4432
3932
|
} catch {
|
|
4433
3933
|
return false;
|
|
@@ -4474,7 +3974,7 @@ function formatTinderboxToml(config) {
|
|
|
4474
3974
|
`;
|
|
4475
3975
|
}
|
|
4476
3976
|
async function writeTinderboxToml(root, config) {
|
|
4477
|
-
await
|
|
3977
|
+
await writeFile6(getConfigPath(root), formatTinderboxToml(config));
|
|
4478
3978
|
}
|
|
4479
3979
|
function parseTinderboxToml(content) {
|
|
4480
3980
|
const parsed = parse(content);
|
|
@@ -4543,7 +4043,7 @@ function parseTinderboxToml(content) {
|
|
|
4543
4043
|
};
|
|
4544
4044
|
}
|
|
4545
4045
|
async function readTinderboxToml(root) {
|
|
4546
|
-
const content = await
|
|
4046
|
+
const content = await readFile52(getConfigPath(root), "utf-8");
|
|
4547
4047
|
const config = parseTinderboxToml(content);
|
|
4548
4048
|
await validateTinderboxToml(root, config);
|
|
4549
4049
|
return config;
|
|
@@ -4552,7 +4052,7 @@ async function validateTinderboxToml(root, config) {
|
|
|
4552
4052
|
if (!config.tinderbox.name.trim()) {
|
|
4553
4053
|
throw new Error("Invalid tinderbox.toml: [tinderbox].name must be a non-empty string");
|
|
4554
4054
|
}
|
|
4555
|
-
if (await pathExists3(
|
|
4055
|
+
if (await pathExists3(join102(root, "flint.toml"))) {
|
|
4556
4056
|
throw new Error("Invalid tinderbox root: the tinderbox root must not also be a Flint");
|
|
4557
4057
|
}
|
|
4558
4058
|
if (!config.flints.required.length) {
|
|
@@ -4624,17 +4124,17 @@ function resolveTinderboxConnections(config) {
|
|
|
4624
4124
|
return edges;
|
|
4625
4125
|
}
|
|
4626
4126
|
async function findTinderboxRoot(startPath) {
|
|
4627
|
-
let current =
|
|
4628
|
-
const home =
|
|
4127
|
+
let current = resolve3(startPath);
|
|
4128
|
+
const home = resolve3(homedir2());
|
|
4629
4129
|
try {
|
|
4630
|
-
const currentStat = await
|
|
4130
|
+
const currentStat = await stat62(current);
|
|
4631
4131
|
if (!currentStat.isDirectory()) {
|
|
4632
4132
|
current = dirname3(current);
|
|
4633
4133
|
}
|
|
4634
4134
|
} catch {
|
|
4635
4135
|
current = dirname3(current);
|
|
4636
4136
|
}
|
|
4637
|
-
let currentDevice = (await
|
|
4137
|
+
let currentDevice = (await stat62(current)).dev;
|
|
4638
4138
|
while (true) {
|
|
4639
4139
|
if (await pathExists3(getConfigPath(current))) {
|
|
4640
4140
|
return current;
|
|
@@ -4643,7 +4143,7 @@ async function findTinderboxRoot(startPath) {
|
|
|
4643
4143
|
if (current === parent || current === home) {
|
|
4644
4144
|
return null;
|
|
4645
4145
|
}
|
|
4646
|
-
const parentStat = await
|
|
4146
|
+
const parentStat = await stat62(parent);
|
|
4647
4147
|
if (parentStat.dev !== currentDevice) {
|
|
4648
4148
|
return null;
|
|
4649
4149
|
}
|
|
@@ -4652,13 +4152,13 @@ async function findTinderboxRoot(startPath) {
|
|
|
4652
4152
|
}
|
|
4653
4153
|
}
|
|
4654
4154
|
async function scanTinderboxFlints(root) {
|
|
4655
|
-
const entries = await
|
|
4155
|
+
const entries = await readdir32(root, { withFileTypes: true });
|
|
4656
4156
|
const flints = [];
|
|
4657
4157
|
for (const entry of entries) {
|
|
4658
4158
|
if (!entry.isDirectory()) continue;
|
|
4659
4159
|
if (entry.name.startsWith(".")) continue;
|
|
4660
|
-
const flintPath =
|
|
4661
|
-
if (!await pathExists3(
|
|
4160
|
+
const flintPath = join102(root, entry.name);
|
|
4161
|
+
if (!await pathExists3(join102(flintPath, "flint.toml"))) {
|
|
4662
4162
|
continue;
|
|
4663
4163
|
}
|
|
4664
4164
|
const config = await readFlintToml(flintPath);
|
|
@@ -4688,8 +4188,8 @@ async function reconcileTinderbox(root, config) {
|
|
|
4688
4188
|
matched.push({ declaration, actual });
|
|
4689
4189
|
continue;
|
|
4690
4190
|
}
|
|
4691
|
-
const expectedPath =
|
|
4692
|
-
if (await pathExists3(
|
|
4191
|
+
const expectedPath = join102(root, getTinderboxFolderName(declaration.name));
|
|
4192
|
+
if (await pathExists3(join102(expectedPath, "flint.toml"))) {
|
|
4693
4193
|
const expectedConfig = await readFlintToml(expectedPath);
|
|
4694
4194
|
const actualName = expectedConfig?.flint?.name;
|
|
4695
4195
|
if (actualName && actualName !== declaration.name) {
|
|
@@ -4698,10 +4198,10 @@ async function reconcileTinderbox(root, config) {
|
|
|
4698
4198
|
actual: {
|
|
4699
4199
|
name: actualName,
|
|
4700
4200
|
path: expectedPath,
|
|
4701
|
-
folderName:
|
|
4201
|
+
folderName: basename2(expectedPath)
|
|
4702
4202
|
}
|
|
4703
4203
|
});
|
|
4704
|
-
renamedPaths.add(
|
|
4204
|
+
renamedPaths.add(resolve3(expectedPath));
|
|
4705
4205
|
continue;
|
|
4706
4206
|
}
|
|
4707
4207
|
}
|
|
@@ -4714,14 +4214,14 @@ async function reconcileTinderbox(root, config) {
|
|
|
4714
4214
|
if (ownedNames.has(flint.name)) {
|
|
4715
4215
|
return false;
|
|
4716
4216
|
}
|
|
4717
|
-
return !renamedPaths.has(
|
|
4217
|
+
return !renamedPaths.has(resolve3(flint.path));
|
|
4718
4218
|
});
|
|
4719
4219
|
return { matched, undeclared, missing, renamed };
|
|
4720
4220
|
}
|
|
4721
4221
|
function buildFlintEntry(path, name, toml) {
|
|
4722
4222
|
const entry = {
|
|
4723
4223
|
name,
|
|
4724
|
-
path:
|
|
4224
|
+
path: resolve3(path),
|
|
4725
4225
|
source: "local"
|
|
4726
4226
|
};
|
|
4727
4227
|
if (toml?.flint.tags?.length) {
|
|
@@ -4737,7 +4237,7 @@ async function syncRegistryForFlint(flint) {
|
|
|
4737
4237
|
const entry = buildFlintEntry(flint.path, flint.name, toml);
|
|
4738
4238
|
const byPath = await findFlintByPath(flint.path);
|
|
4739
4239
|
if (byPath) {
|
|
4740
|
-
if (byPath.name === entry.name &&
|
|
4240
|
+
if (byPath.name === entry.name && resolve3(byPath.path) === entry.path) {
|
|
4741
4241
|
return false;
|
|
4742
4242
|
}
|
|
4743
4243
|
await updateFlintEntry(byPath.path, entry);
|
|
@@ -4745,7 +4245,7 @@ async function syncRegistryForFlint(flint) {
|
|
|
4745
4245
|
}
|
|
4746
4246
|
const byName = await findFlintByName(flint.name);
|
|
4747
4247
|
if (byName) {
|
|
4748
|
-
if (
|
|
4248
|
+
if (resolve3(byName.path) === entry.path) {
|
|
4749
4249
|
return false;
|
|
4750
4250
|
}
|
|
4751
4251
|
await updateFlintEntry(byName.path, entry);
|
|
@@ -4766,11 +4266,11 @@ var REQUIRED_FLINT_DIRS = [
|
|
|
4766
4266
|
];
|
|
4767
4267
|
async function ensureFlintStructure(flintPath) {
|
|
4768
4268
|
for (const dir of REQUIRED_FLINT_DIRS) {
|
|
4769
|
-
await
|
|
4269
|
+
await mkdir8(join102(flintPath, dir), { recursive: true });
|
|
4770
4270
|
}
|
|
4771
4271
|
}
|
|
4772
4272
|
async function materializeGitFlint(root, declaration) {
|
|
4773
|
-
const tempPath =
|
|
4273
|
+
const tempPath = join102(root, `.tinderbox-clone-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`);
|
|
4774
4274
|
try {
|
|
4775
4275
|
await execFileAsync("git", ["clone", declaration.source, tempPath]);
|
|
4776
4276
|
const config = await readFlintToml(tempPath);
|
|
@@ -4781,7 +4281,7 @@ async function materializeGitFlint(root, declaration) {
|
|
|
4781
4281
|
if (actualName !== declaration.name) {
|
|
4782
4282
|
throw new Error(`Cloned Flint name "${actualName}" does not match declared name "${declaration.name}"`);
|
|
4783
4283
|
}
|
|
4784
|
-
const destination =
|
|
4284
|
+
const destination = join102(root, getTinderboxFolderName(actualName));
|
|
4785
4285
|
if (await pathExists3(destination)) {
|
|
4786
4286
|
throw new Error(`Destination already exists: ${destination}`);
|
|
4787
4287
|
}
|
|
@@ -4790,11 +4290,11 @@ async function materializeGitFlint(root, declaration) {
|
|
|
4790
4290
|
return {
|
|
4791
4291
|
name: actualName,
|
|
4792
4292
|
path: destination,
|
|
4793
|
-
folderName:
|
|
4293
|
+
folderName: basename2(destination)
|
|
4794
4294
|
};
|
|
4795
4295
|
} finally {
|
|
4796
4296
|
if (await pathExists3(tempPath)) {
|
|
4797
|
-
await
|
|
4297
|
+
await rm42(tempPath, { recursive: true, force: true });
|
|
4798
4298
|
}
|
|
4799
4299
|
}
|
|
4800
4300
|
}
|
|
@@ -4816,7 +4316,7 @@ async function resolveDeclaredFlints(root, config, reconciliation) {
|
|
|
4816
4316
|
path: actual.path,
|
|
4817
4317
|
available: true,
|
|
4818
4318
|
presentInRoot: true,
|
|
4819
|
-
registered: !!registryEntry &&
|
|
4319
|
+
registered: !!registryEntry && resolve3(registryEntry.path) === resolve3(actual.path)
|
|
4820
4320
|
});
|
|
4821
4321
|
continue;
|
|
4822
4322
|
}
|
|
@@ -4915,7 +4415,7 @@ async function wireTinderboxConnections(config, resolvedFlints) {
|
|
|
4915
4415
|
}
|
|
4916
4416
|
const state = await readReferencesState(from.path);
|
|
4917
4417
|
const existing = state.flints.find((entry) => entry.name.toLowerCase() === edge.to.toLowerCase());
|
|
4918
|
-
const isCurrent = !!existing &&
|
|
4418
|
+
const isCurrent = !!existing && resolve3(existing.path) === resolve3(to.path) && await pathExists3(existing.path);
|
|
4919
4419
|
if (!isCurrent) {
|
|
4920
4420
|
await fulfillFlint(from.path, edge.to, to.path);
|
|
4921
4421
|
changed = true;
|
|
@@ -4946,7 +4446,7 @@ async function syncTinderbox(root) {
|
|
|
4946
4446
|
try {
|
|
4947
4447
|
const existingEntry = await findFlintByName(declaration.name);
|
|
4948
4448
|
if (existingEntry && await pathExists3(existingEntry.path)) {
|
|
4949
|
-
const destination =
|
|
4449
|
+
const destination = join102(root, getTinderboxFolderName(declaration.name));
|
|
4950
4450
|
const moveResult = await moveFlint(existingEntry.path, destination);
|
|
4951
4451
|
moved.push({ name: declaration.name, from: moveResult.from, to: moveResult.to });
|
|
4952
4452
|
continue;
|
|
@@ -5009,7 +4509,7 @@ async function getConnectionDrift(config, resolvedFlints) {
|
|
|
5009
4509
|
const state = await readReferencesState(from.path);
|
|
5010
4510
|
const declarationExists = declarations.some((entry) => entry.name.toLowerCase() === edge.to.toLowerCase());
|
|
5011
4511
|
const fulfillment = state.flints.find((entry) => entry.name.toLowerCase() === edge.to.toLowerCase());
|
|
5012
|
-
const fulfillmentValid = !!fulfillment &&
|
|
4512
|
+
const fulfillmentValid = !!fulfillment && resolve3(fulfillment.path) === resolve3(to.path) && await pathExists3(fulfillment.path);
|
|
5013
4513
|
if (!declarationExists || !fulfillmentValid) {
|
|
5014
4514
|
drift.push({
|
|
5015
4515
|
from: edge.from,
|
|
@@ -5029,7 +4529,7 @@ async function checkTinderbox(root) {
|
|
|
5029
4529
|
const staleRegistry = [];
|
|
5030
4530
|
for (const flint of discovered) {
|
|
5031
4531
|
const entry = await findFlintByName(flint.name);
|
|
5032
|
-
if (!entry ||
|
|
4532
|
+
if (!entry || resolve3(entry.path) !== resolve3(flint.path)) {
|
|
5033
4533
|
staleRegistry.push({
|
|
5034
4534
|
name: flint.name,
|
|
5035
4535
|
actualPath: flint.path,
|
|
@@ -5096,7 +4596,7 @@ async function getTinderboxStatus(root) {
|
|
|
5096
4596
|
for (const edge of expectedEdges) {
|
|
5097
4597
|
const target = resolvedByName.get(edge.to);
|
|
5098
4598
|
const fulfillment = state.flints.find((entry) => entry.name.toLowerCase() === edge.to.toLowerCase());
|
|
5099
|
-
if (target?.available && target.path && fulfillment &&
|
|
4599
|
+
if (target?.available && target.path && fulfillment && resolve3(fulfillment.path) === resolve3(target.path) && await pathExists3(fulfillment.path)) {
|
|
5100
4600
|
connectionsFulfilled++;
|
|
5101
4601
|
}
|
|
5102
4602
|
}
|
|
@@ -5137,20 +4637,20 @@ async function setTinderboxIdentity(root, name) {
|
|
|
5137
4637
|
return { applied, failed };
|
|
5138
4638
|
}
|
|
5139
4639
|
async function countFiles(path) {
|
|
5140
|
-
const stats = await
|
|
4640
|
+
const stats = await stat62(path);
|
|
5141
4641
|
if (!stats.isDirectory()) {
|
|
5142
4642
|
return 1;
|
|
5143
4643
|
}
|
|
5144
|
-
const entries = await
|
|
4644
|
+
const entries = await readdir32(path, { withFileTypes: true });
|
|
5145
4645
|
let count = 1;
|
|
5146
4646
|
for (const entry of entries) {
|
|
5147
|
-
count += await countFiles(
|
|
4647
|
+
count += await countFiles(join102(path, entry.name));
|
|
5148
4648
|
}
|
|
5149
4649
|
return count;
|
|
5150
4650
|
}
|
|
5151
4651
|
async function resolveMoveSource(nameOrPath) {
|
|
5152
|
-
const directPath =
|
|
5153
|
-
if (await pathExists3(
|
|
4652
|
+
const directPath = resolve3(nameOrPath);
|
|
4653
|
+
if (await pathExists3(join102(directPath, "flint.toml"))) {
|
|
5154
4654
|
const config = await readFlintToml(directPath);
|
|
5155
4655
|
const name = config?.flint?.name;
|
|
5156
4656
|
if (!name) {
|
|
@@ -5162,23 +4662,23 @@ async function resolveMoveSource(nameOrPath) {
|
|
|
5162
4662
|
if (!entry) {
|
|
5163
4663
|
throw new Error(`Flint not found: ${nameOrPath}`);
|
|
5164
4664
|
}
|
|
5165
|
-
return { path:
|
|
4665
|
+
return { path: resolve3(entry.path), name: entry.name };
|
|
5166
4666
|
}
|
|
5167
4667
|
async function moveFlint(nameOrPath, destination, options = {}) {
|
|
5168
4668
|
const source = await resolveMoveSource(nameOrPath);
|
|
5169
|
-
const targetPath =
|
|
4669
|
+
const targetPath = resolve3(destination);
|
|
5170
4670
|
const targetParent = dirname3(targetPath);
|
|
5171
4671
|
if (!await pathExists3(targetParent)) {
|
|
5172
4672
|
throw new Error(`Destination parent does not exist: ${targetParent}`);
|
|
5173
4673
|
}
|
|
5174
|
-
if (
|
|
4674
|
+
if (resolve3(source.path) === targetPath) {
|
|
5175
4675
|
throw new Error(`Destination is the same as source: ${targetPath}`);
|
|
5176
4676
|
}
|
|
5177
4677
|
if (await pathExists3(targetPath)) {
|
|
5178
4678
|
if (!options.force) {
|
|
5179
4679
|
throw new Error(`Destination already exists: ${targetPath}`);
|
|
5180
4680
|
}
|
|
5181
|
-
await
|
|
4681
|
+
await rm42(targetPath, { recursive: true, force: true });
|
|
5182
4682
|
}
|
|
5183
4683
|
let crossDevice = false;
|
|
5184
4684
|
try {
|
|
@@ -5195,10 +4695,10 @@ async function moveFlint(nameOrPath, destination, options = {}) {
|
|
|
5195
4695
|
countFiles(targetPath)
|
|
5196
4696
|
]);
|
|
5197
4697
|
if (sourceCount !== destinationCount) {
|
|
5198
|
-
await
|
|
4698
|
+
await rm42(targetPath, { recursive: true, force: true });
|
|
5199
4699
|
throw new Error("Cross-device move verification failed");
|
|
5200
4700
|
}
|
|
5201
|
-
await
|
|
4701
|
+
await rm42(source.path, { recursive: true, force: true });
|
|
5202
4702
|
}
|
|
5203
4703
|
const config = await readFlintToml(targetPath);
|
|
5204
4704
|
const entry = buildFlintEntry(targetPath, config?.flint?.name ?? source.name, config);
|
|
@@ -5221,12 +4721,12 @@ async function moveFlint(nameOrPath, destination, options = {}) {
|
|
|
5221
4721
|
async function removeTinderboxFlint(flint) {
|
|
5222
4722
|
const entry = await findFlintByPath(flint.path);
|
|
5223
4723
|
if (entry) {
|
|
5224
|
-
const { unregisterFlint: unregisterFlint2 } = await import("./registry-
|
|
4724
|
+
const { unregisterFlint: unregisterFlint2 } = await import("./registry-5CNUVQN3-PCQZRXLB.js");
|
|
5225
4725
|
await unregisterFlint2(entry.path);
|
|
5226
4726
|
}
|
|
5227
|
-
await
|
|
4727
|
+
await rm42(flint.path, { recursive: true, force: true });
|
|
5228
4728
|
}
|
|
5229
|
-
var
|
|
4729
|
+
var execAsync3 = promisify4(exec3);
|
|
5230
4730
|
function normalizeManifest(raw, context) {
|
|
5231
4731
|
const { repos, ...rest } = raw;
|
|
5232
4732
|
if (repos !== void 0) {
|
|
@@ -5292,7 +4792,7 @@ async function resolveShardSource(source, flintPath, version) {
|
|
|
5292
4792
|
return cloneAndResolve(url, source, version);
|
|
5293
4793
|
}
|
|
5294
4794
|
case "path": {
|
|
5295
|
-
const resolvedPath = isAbsolute2(source.path) ? source.path :
|
|
4795
|
+
const resolvedPath = isAbsolute2(source.path) ? source.path : resolve4(flintPath, source.path);
|
|
5296
4796
|
if (!await exists(resolvedPath)) {
|
|
5297
4797
|
throw new Error(`Shard path does not exist: ${resolvedPath}`);
|
|
5298
4798
|
}
|
|
@@ -5310,15 +4810,15 @@ async function resolveShardSource(source, flintPath, version) {
|
|
|
5310
4810
|
}
|
|
5311
4811
|
}
|
|
5312
4812
|
async function cloneAndResolve(url, source, version) {
|
|
5313
|
-
const tempDir = await mkdtemp(
|
|
4813
|
+
const tempDir = await mkdtemp(join112(tmpdir(), "flint-shard-"));
|
|
5314
4814
|
try {
|
|
5315
4815
|
const branchArgs = version ? `--branch v${version}` : "";
|
|
5316
|
-
await
|
|
4816
|
+
await execAsync3(`git clone --depth 1 ${branchArgs} ${url} "${tempDir}"`, {
|
|
5317
4817
|
timeout: 6e4
|
|
5318
4818
|
// 60 second timeout
|
|
5319
4819
|
});
|
|
5320
4820
|
} catch (err) {
|
|
5321
|
-
await
|
|
4821
|
+
await rm52(tempDir, { recursive: true, force: true });
|
|
5322
4822
|
const message = err instanceof Error ? err.message : String(err);
|
|
5323
4823
|
if (version && message.includes("not found")) {
|
|
5324
4824
|
throw new Error(`Version v${version} not found for shard. Check available versions with: flint shard versions <name>`);
|
|
@@ -5327,7 +4827,7 @@ async function cloneAndResolve(url, source, version) {
|
|
|
5327
4827
|
}
|
|
5328
4828
|
const manifest = await readManifest(tempDir);
|
|
5329
4829
|
if (!manifest) {
|
|
5330
|
-
await
|
|
4830
|
+
await rm52(tempDir, { recursive: true, force: true });
|
|
5331
4831
|
throw new Error(`No shard.yaml found in cloned repository: ${url}`);
|
|
5332
4832
|
}
|
|
5333
4833
|
return {
|
|
@@ -5338,11 +4838,11 @@ async function cloneAndResolve(url, source, version) {
|
|
|
5338
4838
|
};
|
|
5339
4839
|
}
|
|
5340
4840
|
async function readManifest(dir) {
|
|
5341
|
-
const yamlPath =
|
|
4841
|
+
const yamlPath = join112(dir, "shard.yaml");
|
|
5342
4842
|
try {
|
|
5343
|
-
const content = await
|
|
4843
|
+
const content = await readFile6(yamlPath, "utf-8");
|
|
5344
4844
|
return normalizeManifest(
|
|
5345
|
-
|
|
4845
|
+
parseYaml2(content),
|
|
5346
4846
|
yamlPath
|
|
5347
4847
|
);
|
|
5348
4848
|
} catch {
|
|
@@ -5351,13 +4851,13 @@ async function readManifest(dir) {
|
|
|
5351
4851
|
}
|
|
5352
4852
|
async function cleanupResolvedSource(resolved) {
|
|
5353
4853
|
if (resolved.isTemp) {
|
|
5354
|
-
await
|
|
4854
|
+
await rm52(resolved.path, { recursive: true, force: true });
|
|
5355
4855
|
}
|
|
5356
4856
|
}
|
|
5357
4857
|
async function listRemoteVersionTags(source) {
|
|
5358
4858
|
const url = `https://github.com/${source.owner}/${source.repo}.git`;
|
|
5359
4859
|
try {
|
|
5360
|
-
const { stdout } = await
|
|
4860
|
+
const { stdout } = await execAsync3(`git ls-remote --tags ${url}`, { timeout: 3e4 });
|
|
5361
4861
|
const tags = [];
|
|
5362
4862
|
for (const line of stdout.trim().split("\n")) {
|
|
5363
4863
|
if (!line) continue;
|
|
@@ -5400,7 +4900,7 @@ async function fetchRemoteShardVersion(source) {
|
|
|
5400
4900
|
return null;
|
|
5401
4901
|
}
|
|
5402
4902
|
const content = await response.text();
|
|
5403
|
-
const manifest =
|
|
4903
|
+
const manifest = parseYaml2(content);
|
|
5404
4904
|
return manifest?.version ?? null;
|
|
5405
4905
|
} catch {
|
|
5406
4906
|
if (attempt === 0) {
|
|
@@ -5424,11 +4924,11 @@ function normalizeManifest2(raw, context) {
|
|
|
5424
4924
|
};
|
|
5425
4925
|
}
|
|
5426
4926
|
function getShardVersionStatePath(flintPath, shardName) {
|
|
5427
|
-
return
|
|
4927
|
+
return join12(getFlintConfigDir(flintPath), "shards", `${shardName}.json`);
|
|
5428
4928
|
}
|
|
5429
4929
|
async function readShardVersionState(flintPath, shardName) {
|
|
5430
4930
|
try {
|
|
5431
|
-
const content = await
|
|
4931
|
+
const content = await readFile7(getShardVersionStatePath(flintPath, shardName), "utf-8");
|
|
5432
4932
|
return JSON.parse(content);
|
|
5433
4933
|
} catch {
|
|
5434
4934
|
return null;
|
|
@@ -5440,14 +4940,14 @@ async function getRecordedShardVersion(flintPath, shardName) {
|
|
|
5440
4940
|
}
|
|
5441
4941
|
async function recordShardVersion(flintPath, shardName, version) {
|
|
5442
4942
|
const statePath = getShardVersionStatePath(flintPath, shardName);
|
|
5443
|
-
await
|
|
4943
|
+
await mkdir9(dirname4(statePath), { recursive: true });
|
|
5444
4944
|
const state = {
|
|
5445
4945
|
version: 1,
|
|
5446
4946
|
shard: shardName,
|
|
5447
4947
|
currentVersion: version,
|
|
5448
4948
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
5449
4949
|
};
|
|
5450
|
-
await
|
|
4950
|
+
await writeFile7(statePath, JSON.stringify(state, null, 2) + "\n");
|
|
5451
4951
|
}
|
|
5452
4952
|
async function getDependencyWarnings(flintPath, manifest) {
|
|
5453
4953
|
if (!manifest.dependencies?.length) return [];
|
|
@@ -5469,12 +4969,12 @@ async function getDependencyWarnings(flintPath, manifest) {
|
|
|
5469
4969
|
return warnings;
|
|
5470
4970
|
}
|
|
5471
4971
|
async function copyDir2(src, dest, skip = []) {
|
|
5472
|
-
await
|
|
5473
|
-
const entries = await
|
|
4972
|
+
await mkdir9(dest, { recursive: true });
|
|
4973
|
+
const entries = await readdir42(src, { withFileTypes: true });
|
|
5474
4974
|
for (const entry of entries) {
|
|
5475
4975
|
if (skip.includes(entry.name)) continue;
|
|
5476
|
-
const srcPath =
|
|
5477
|
-
const destPath =
|
|
4976
|
+
const srcPath = join12(src, entry.name);
|
|
4977
|
+
const destPath = join12(dest, entry.name);
|
|
5478
4978
|
if (entry.isDirectory()) {
|
|
5479
4979
|
await copyDir2(srcPath, destPath, skip);
|
|
5480
4980
|
} else {
|
|
@@ -5483,12 +4983,12 @@ async function copyDir2(src, dest, skip = []) {
|
|
|
5483
4983
|
}
|
|
5484
4984
|
}
|
|
5485
4985
|
async function createShardStateFile(flintPath, name, shorthand) {
|
|
5486
|
-
const stateDir =
|
|
5487
|
-
const statePath =
|
|
4986
|
+
const stateDir = join12(flintPath, "Mesh", "Shards");
|
|
4987
|
+
const statePath = join12(stateDir, `(Shard) ${name}.md`);
|
|
5488
4988
|
if (await exists(statePath)) {
|
|
5489
4989
|
return false;
|
|
5490
4990
|
}
|
|
5491
|
-
await
|
|
4991
|
+
await mkdir9(stateDir, { recursive: true });
|
|
5492
4992
|
const content = `---
|
|
5493
4993
|
id: ${randomUUID32()}
|
|
5494
4994
|
tags:
|
|
@@ -5500,7 +5000,7 @@ shard: ${shorthand}
|
|
|
5500
5000
|
|
|
5501
5001
|
State for the ${name} shard.
|
|
5502
5002
|
`;
|
|
5503
|
-
await
|
|
5003
|
+
await writeFile7(statePath, content);
|
|
5504
5004
|
return true;
|
|
5505
5005
|
}
|
|
5506
5006
|
function processTemplate(content) {
|
|
@@ -5515,10 +5015,10 @@ function extractIdFromFrontmatter(content) {
|
|
|
5515
5015
|
return idMatch?.[1]?.trim() ?? null;
|
|
5516
5016
|
}
|
|
5517
5017
|
async function detectMigrations(shardPath, shorthand, fromVersion, toVersion) {
|
|
5518
|
-
const migrationsDir =
|
|
5018
|
+
const migrationsDir = join12(shardPath, "migrations");
|
|
5519
5019
|
if (!await exists(migrationsDir)) return [];
|
|
5520
5020
|
try {
|
|
5521
|
-
const entries = await
|
|
5021
|
+
const entries = await readdir42(migrationsDir, { withFileTypes: true });
|
|
5522
5022
|
const prefix = `mig-${shorthand}-`;
|
|
5523
5023
|
const allMigrations = [];
|
|
5524
5024
|
for (const entry of entries) {
|
|
@@ -5550,11 +5050,11 @@ async function detectMigrations(shardPath, shorthand, fromVersion, toVersion) {
|
|
|
5550
5050
|
}
|
|
5551
5051
|
}
|
|
5552
5052
|
async function readShardManifest(shardPath) {
|
|
5553
|
-
const yamlPath =
|
|
5053
|
+
const yamlPath = join12(shardPath, "shard.yaml");
|
|
5554
5054
|
try {
|
|
5555
|
-
const content = await
|
|
5055
|
+
const content = await readFile7(yamlPath, "utf-8");
|
|
5556
5056
|
return normalizeManifest2(
|
|
5557
|
-
|
|
5057
|
+
parseYaml3(content),
|
|
5558
5058
|
yamlPath
|
|
5559
5059
|
);
|
|
5560
5060
|
} catch {
|
|
@@ -5562,14 +5062,14 @@ async function readShardManifest(shardPath) {
|
|
|
5562
5062
|
}
|
|
5563
5063
|
}
|
|
5564
5064
|
async function applyShardManifestContent(flintPath, sourcePath, manifest, options = {}) {
|
|
5565
|
-
const resolvedFlintPath =
|
|
5065
|
+
const resolvedFlintPath = resolve5(flintPath);
|
|
5566
5066
|
let foldersCreated = 0;
|
|
5567
5067
|
let filesInstalled = 0;
|
|
5568
5068
|
let stateCreated = false;
|
|
5569
5069
|
if (manifest.folders?.length) {
|
|
5570
5070
|
for (const folder of manifest.folders) {
|
|
5571
|
-
const folderPath =
|
|
5572
|
-
const resolvedFolderPath =
|
|
5071
|
+
const folderPath = join12(flintPath, folder);
|
|
5072
|
+
const resolvedFolderPath = resolve5(folderPath);
|
|
5573
5073
|
if (!resolvedFolderPath.startsWith(resolvedFlintPath)) {
|
|
5574
5074
|
console.warn(`Skipping folder outside flint: ${folder}`);
|
|
5575
5075
|
continue;
|
|
@@ -5577,15 +5077,15 @@ async function applyShardManifestContent(flintPath, sourcePath, manifest, option
|
|
|
5577
5077
|
if (!await exists(folderPath)) {
|
|
5578
5078
|
foldersCreated++;
|
|
5579
5079
|
}
|
|
5580
|
-
await
|
|
5080
|
+
await mkdir9(folderPath, { recursive: true });
|
|
5581
5081
|
}
|
|
5582
5082
|
}
|
|
5583
5083
|
if (manifest.install?.length) {
|
|
5584
|
-
const installFolderPath =
|
|
5084
|
+
const installFolderPath = join12(sourcePath, "install");
|
|
5585
5085
|
for (const entry of manifest.install) {
|
|
5586
|
-
const srcFilePath =
|
|
5587
|
-
const destFilePath =
|
|
5588
|
-
const resolvedDestFilePath =
|
|
5086
|
+
const srcFilePath = join12(installFolderPath, entry.source);
|
|
5087
|
+
const destFilePath = join12(flintPath, entry.dest);
|
|
5088
|
+
const resolvedDestFilePath = resolve5(destFilePath);
|
|
5589
5089
|
if (!resolvedDestFilePath.startsWith(resolvedFlintPath)) {
|
|
5590
5090
|
console.warn(`Skipping file outside flint: ${entry.dest}`);
|
|
5591
5091
|
continue;
|
|
@@ -5598,7 +5098,7 @@ async function applyShardManifestContent(flintPath, sourcePath, manifest, option
|
|
|
5598
5098
|
}
|
|
5599
5099
|
let content;
|
|
5600
5100
|
try {
|
|
5601
|
-
content = await
|
|
5101
|
+
content = await readFile7(srcFilePath, "utf-8");
|
|
5602
5102
|
} catch {
|
|
5603
5103
|
console.warn(`Failed to read install file: ${entry.source}`);
|
|
5604
5104
|
continue;
|
|
@@ -5606,7 +5106,7 @@ async function applyShardManifestContent(flintPath, sourcePath, manifest, option
|
|
|
5606
5106
|
let existingId = null;
|
|
5607
5107
|
if (await exists(destFilePath)) {
|
|
5608
5108
|
try {
|
|
5609
|
-
const existingContent = await
|
|
5109
|
+
const existingContent = await readFile7(destFilePath, "utf-8");
|
|
5610
5110
|
existingId = extractIdFromFrontmatter(existingContent);
|
|
5611
5111
|
} catch {
|
|
5612
5112
|
}
|
|
@@ -5615,8 +5115,8 @@ async function applyShardManifestContent(flintPath, sourcePath, manifest, option
|
|
|
5615
5115
|
if (existingId) {
|
|
5616
5116
|
content = content.replace(/^(id:\s*)[a-f0-9-]{36}/m, `$1${existingId}`);
|
|
5617
5117
|
}
|
|
5618
|
-
await
|
|
5619
|
-
await
|
|
5118
|
+
await mkdir9(dirname4(destFilePath), { recursive: true });
|
|
5119
|
+
await writeFile7(destFilePath, content);
|
|
5620
5120
|
filesInstalled++;
|
|
5621
5121
|
}
|
|
5622
5122
|
}
|
|
@@ -5626,16 +5126,16 @@ async function applyShardManifestContent(flintPath, sourcePath, manifest, option
|
|
|
5626
5126
|
return { foldersCreated, filesInstalled, stateCreated };
|
|
5627
5127
|
}
|
|
5628
5128
|
async function installShardFromSource(flintPath, sourcePath, manifest, options = {}) {
|
|
5629
|
-
const destPath =
|
|
5630
|
-
const resolvedFlintPath =
|
|
5631
|
-
const resolvedDestPath =
|
|
5129
|
+
const destPath = join12(flintPath, "Shards", manifest.name);
|
|
5130
|
+
const resolvedFlintPath = resolve5(flintPath);
|
|
5131
|
+
const resolvedDestPath = resolve5(destPath);
|
|
5632
5132
|
if (!resolvedDestPath.startsWith(resolvedFlintPath)) {
|
|
5633
5133
|
throw new Error("Invalid shard path: outside flint directory");
|
|
5634
5134
|
}
|
|
5635
|
-
await
|
|
5636
|
-
await
|
|
5637
|
-
const shardYamlSrc =
|
|
5638
|
-
const shardYamlDest =
|
|
5135
|
+
await rm62(destPath, { recursive: true, force: true });
|
|
5136
|
+
await mkdir9(destPath, { recursive: true });
|
|
5137
|
+
const shardYamlSrc = join12(sourcePath, "shard.yaml");
|
|
5138
|
+
const shardYamlDest = join12(destPath, "shard.yaml");
|
|
5639
5139
|
if (await exists(shardYamlSrc)) {
|
|
5640
5140
|
await copyFile(shardYamlSrc, shardYamlDest);
|
|
5641
5141
|
}
|
|
@@ -5652,23 +5152,23 @@ async function installShardFromSource(flintPath, sourcePath, manifest, options =
|
|
|
5652
5152
|
return { name: manifest.name, path: destPath };
|
|
5653
5153
|
}
|
|
5654
5154
|
async function listInstalledShards(flintPath) {
|
|
5655
|
-
const shardsPath =
|
|
5155
|
+
const shardsPath = join12(flintPath, "Shards");
|
|
5656
5156
|
try {
|
|
5657
|
-
const entries = await
|
|
5157
|
+
const entries = await readdir42(shardsPath, { withFileTypes: true });
|
|
5658
5158
|
return entries.filter((e) => e.isDirectory() && !e.name.startsWith("(System)")).map((e) => e.name);
|
|
5659
5159
|
} catch {
|
|
5660
5160
|
return [];
|
|
5661
5161
|
}
|
|
5662
5162
|
}
|
|
5663
5163
|
async function getInstalledShardsWithVersions(flintPath) {
|
|
5664
|
-
const shardsPath =
|
|
5164
|
+
const shardsPath = join12(flintPath, "Shards");
|
|
5665
5165
|
const results = [];
|
|
5666
5166
|
try {
|
|
5667
|
-
const entries = await
|
|
5167
|
+
const entries = await readdir42(shardsPath, { withFileTypes: true });
|
|
5668
5168
|
const folders = entries.filter((e) => e.isDirectory() && !e.name.startsWith("(System)")).map((e) => e.name);
|
|
5669
5169
|
for (const folder of folders) {
|
|
5670
5170
|
try {
|
|
5671
|
-
const manifest = await readShardManifest(
|
|
5171
|
+
const manifest = await readShardManifest(join12(shardsPath, folder));
|
|
5672
5172
|
if (!manifest?.name || !manifest.shorthand || !manifest.version) {
|
|
5673
5173
|
continue;
|
|
5674
5174
|
}
|
|
@@ -5718,7 +5218,7 @@ async function updateShards(flintPath, options = {}) {
|
|
|
5718
5218
|
if (pinnedVersion && pinnedVersion === info.version && !options.reinstall) {
|
|
5719
5219
|
return {
|
|
5720
5220
|
name: info.folderName,
|
|
5721
|
-
path:
|
|
5221
|
+
path: join12(flintPath, "Shards", info.folderName),
|
|
5722
5222
|
status: "skipped",
|
|
5723
5223
|
localVersion: info.version,
|
|
5724
5224
|
remoteVersion: pinnedVersion,
|
|
@@ -5731,7 +5231,7 @@ async function updateShards(flintPath, options = {}) {
|
|
|
5731
5231
|
if (remoteVersion && compareVersions(remoteVersion, info.version) <= 0) {
|
|
5732
5232
|
return {
|
|
5733
5233
|
name: info.folderName,
|
|
5734
|
-
path:
|
|
5234
|
+
path: join12(flintPath, "Shards", info.folderName),
|
|
5735
5235
|
status: "skipped",
|
|
5736
5236
|
localVersion: info.version,
|
|
5737
5237
|
remoteVersion,
|
|
@@ -5742,7 +5242,7 @@ async function updateShards(flintPath, options = {}) {
|
|
|
5742
5242
|
if (!source || !isGitHubSourceSpecifier(source)) {
|
|
5743
5243
|
return {
|
|
5744
5244
|
name: info.folderName,
|
|
5745
|
-
path:
|
|
5245
|
+
path: join12(flintPath, "Shards", info.folderName),
|
|
5746
5246
|
status: "skipped",
|
|
5747
5247
|
localVersion: info.version,
|
|
5748
5248
|
reason: "no source configured"
|
|
@@ -5755,7 +5255,7 @@ async function updateShards(flintPath, options = {}) {
|
|
|
5755
5255
|
} catch {
|
|
5756
5256
|
return {
|
|
5757
5257
|
name: info.folderName,
|
|
5758
|
-
path:
|
|
5258
|
+
path: join12(flintPath, "Shards", info.folderName),
|
|
5759
5259
|
status: "failed",
|
|
5760
5260
|
localVersion: info.version,
|
|
5761
5261
|
reason: "failed to resolve source"
|
|
@@ -5767,7 +5267,7 @@ async function updateShards(flintPath, options = {}) {
|
|
|
5767
5267
|
source,
|
|
5768
5268
|
version: pinnedVersion
|
|
5769
5269
|
});
|
|
5770
|
-
const shardPath =
|
|
5270
|
+
const shardPath = join12(flintPath, "Shards", info.folderName);
|
|
5771
5271
|
const shorthand = resolved.manifest.shorthand || info.shorthand;
|
|
5772
5272
|
const migrations2 = await detectMigrations(
|
|
5773
5273
|
shardPath,
|
|
@@ -5777,7 +5277,7 @@ async function updateShards(flintPath, options = {}) {
|
|
|
5777
5277
|
);
|
|
5778
5278
|
return {
|
|
5779
5279
|
name: info.folderName,
|
|
5780
|
-
path:
|
|
5280
|
+
path: join12(flintPath, "Shards", info.folderName),
|
|
5781
5281
|
status: "updated",
|
|
5782
5282
|
localVersion: info.version,
|
|
5783
5283
|
remoteVersion: resolved.manifest.version,
|
|
@@ -5787,7 +5287,7 @@ async function updateShards(flintPath, options = {}) {
|
|
|
5787
5287
|
} catch {
|
|
5788
5288
|
return {
|
|
5789
5289
|
name: info.folderName,
|
|
5790
|
-
path:
|
|
5290
|
+
path: join12(flintPath, "Shards", info.folderName),
|
|
5791
5291
|
status: "failed",
|
|
5792
5292
|
localVersion: info.version,
|
|
5793
5293
|
reason: "failed to install from source"
|
|
@@ -5809,7 +5309,7 @@ async function updateShards(flintPath, options = {}) {
|
|
|
5809
5309
|
if (r.status === "error") {
|
|
5810
5310
|
results.push({
|
|
5811
5311
|
name: r.name,
|
|
5812
|
-
path:
|
|
5312
|
+
path: join12(flintPath, "Shards", r.name),
|
|
5813
5313
|
status: "failed",
|
|
5814
5314
|
localVersion: "",
|
|
5815
5315
|
reason: r.error?.message || "Unknown error"
|
|
@@ -5825,7 +5325,7 @@ async function updateShards(flintPath, options = {}) {
|
|
|
5825
5325
|
}
|
|
5826
5326
|
async function isDirectoryEmpty(dirPath) {
|
|
5827
5327
|
try {
|
|
5828
|
-
const entries = await
|
|
5328
|
+
const entries = await readdir42(dirPath);
|
|
5829
5329
|
return entries.length === 0;
|
|
5830
5330
|
} catch {
|
|
5831
5331
|
return true;
|
|
@@ -5839,23 +5339,23 @@ async function uninstallShard(flintPath, identifier) {
|
|
|
5839
5339
|
throw new Error(`Shard "${identifier}" is not installed.`);
|
|
5840
5340
|
}
|
|
5841
5341
|
const shardName = matchingFolder;
|
|
5842
|
-
const shardPath =
|
|
5342
|
+
const shardPath = join12(flintPath, "Shards", matchingFolder);
|
|
5843
5343
|
const folderExists = await exists(shardPath);
|
|
5844
5344
|
if (!folderExists) {
|
|
5845
5345
|
throw new Error(`Shard "${shardName}" is not installed.`);
|
|
5846
5346
|
}
|
|
5847
|
-
const resolvedFlintPath =
|
|
5347
|
+
const resolvedFlintPath = resolve5(flintPath);
|
|
5848
5348
|
const manifest = await readShardManifest(shardPath);
|
|
5849
5349
|
if (manifest) {
|
|
5850
5350
|
if (manifest.install?.length) {
|
|
5851
5351
|
for (const entry of manifest.install) {
|
|
5852
|
-
const filePath =
|
|
5853
|
-
const resolvedFilePath =
|
|
5352
|
+
const filePath = join12(flintPath, entry.dest);
|
|
5353
|
+
const resolvedFilePath = resolve5(filePath);
|
|
5854
5354
|
if (!resolvedFilePath.startsWith(resolvedFlintPath)) {
|
|
5855
5355
|
continue;
|
|
5856
5356
|
}
|
|
5857
5357
|
try {
|
|
5858
|
-
await
|
|
5358
|
+
await rm62(filePath, { force: true });
|
|
5859
5359
|
} catch {
|
|
5860
5360
|
}
|
|
5861
5361
|
}
|
|
@@ -5863,8 +5363,8 @@ async function uninstallShard(flintPath, identifier) {
|
|
|
5863
5363
|
if (manifest.folders?.length) {
|
|
5864
5364
|
const sortedFolders = [...manifest.folders].sort((a, b) => b.length - a.length);
|
|
5865
5365
|
for (const folder of sortedFolders) {
|
|
5866
|
-
const folderPath =
|
|
5867
|
-
const resolvedFolderPath =
|
|
5366
|
+
const folderPath = join12(flintPath, folder);
|
|
5367
|
+
const resolvedFolderPath = resolve5(folderPath);
|
|
5868
5368
|
if (!resolvedFolderPath.startsWith(resolvedFlintPath)) {
|
|
5869
5369
|
continue;
|
|
5870
5370
|
}
|
|
@@ -5877,11 +5377,11 @@ async function uninstallShard(flintPath, identifier) {
|
|
|
5877
5377
|
}
|
|
5878
5378
|
}
|
|
5879
5379
|
}
|
|
5880
|
-
const resolvedShardPath =
|
|
5380
|
+
const resolvedShardPath = resolve5(shardPath);
|
|
5881
5381
|
if (!resolvedShardPath.startsWith(resolvedFlintPath)) {
|
|
5882
5382
|
throw new Error(`Invalid shard path: outside flint directory`);
|
|
5883
5383
|
}
|
|
5884
|
-
await
|
|
5384
|
+
await rm62(shardPath, { recursive: true, force: true });
|
|
5885
5385
|
await removeShardFromConfig(flintPath, shardName);
|
|
5886
5386
|
return { name: shardName, removed: true };
|
|
5887
5387
|
}
|
|
@@ -5891,11 +5391,11 @@ async function removeOrphanedShard(flintPath, kebabName) {
|
|
|
5891
5391
|
(folder) => toKebabCase(folder) === kebabName
|
|
5892
5392
|
);
|
|
5893
5393
|
if (matchingFolder) {
|
|
5894
|
-
const shardPath =
|
|
5895
|
-
const resolvedFlintPath =
|
|
5896
|
-
const resolvedShardPath =
|
|
5394
|
+
const shardPath = join12(flintPath, "Shards", matchingFolder);
|
|
5395
|
+
const resolvedFlintPath = resolve5(flintPath);
|
|
5396
|
+
const resolvedShardPath = resolve5(shardPath);
|
|
5897
5397
|
if (resolvedShardPath.startsWith(resolvedFlintPath)) {
|
|
5898
|
-
await
|
|
5398
|
+
await rm62(shardPath, { recursive: true, force: true });
|
|
5899
5399
|
}
|
|
5900
5400
|
}
|
|
5901
5401
|
return { name: kebabName, removed: true };
|
|
@@ -5915,7 +5415,7 @@ async function pullShard(flintPath, identifier, options) {
|
|
|
5915
5415
|
shardFolders = await listInstalledShards(flintPath);
|
|
5916
5416
|
}
|
|
5917
5417
|
for (const folder of shardFolders) {
|
|
5918
|
-
const shardPath =
|
|
5418
|
+
const shardPath = join12(flintPath, "Shards", folder);
|
|
5919
5419
|
const manifest = await readShardManifest(shardPath);
|
|
5920
5420
|
if (!manifest) continue;
|
|
5921
5421
|
const shardName = toKebabCase(manifest.name || folder);
|
|
@@ -5951,23 +5451,23 @@ async function scaffoldNewShard(flintPath, name, shorthand, description, options
|
|
|
5951
5451
|
const shardMode = options.mode || "dev";
|
|
5952
5452
|
const prefix = shardMode === "custom" ? "(Custom)" : "(Dev)";
|
|
5953
5453
|
const folderName = `${prefix} ${name}`;
|
|
5954
|
-
const shardPath =
|
|
5454
|
+
const shardPath = join12(flintPath, "Shards", folderName);
|
|
5955
5455
|
if (await exists(shardPath)) {
|
|
5956
5456
|
throw new Error(`Shard already exists: ${folderName}`);
|
|
5957
5457
|
}
|
|
5958
5458
|
const dirs = [
|
|
5959
5459
|
shardPath,
|
|
5960
|
-
|
|
5961
|
-
|
|
5962
|
-
|
|
5963
|
-
|
|
5964
|
-
|
|
5965
|
-
|
|
5966
|
-
|
|
5967
|
-
|
|
5460
|
+
join12(shardPath, "skills"),
|
|
5461
|
+
join12(shardPath, "workflows"),
|
|
5462
|
+
join12(shardPath, "templates"),
|
|
5463
|
+
join12(shardPath, "knowledge"),
|
|
5464
|
+
join12(shardPath, "assets"),
|
|
5465
|
+
join12(shardPath, "install"),
|
|
5466
|
+
join12(shardPath, "migrations"),
|
|
5467
|
+
join12(shardPath, "scripts")
|
|
5968
5468
|
];
|
|
5969
5469
|
for (const dir of dirs) {
|
|
5970
|
-
await
|
|
5470
|
+
await mkdir9(dir, { recursive: true });
|
|
5971
5471
|
}
|
|
5972
5472
|
let shardYaml = `shard-spec: "0.1.0"
|
|
5973
5473
|
version: "0.1.0"
|
|
@@ -5979,7 +5479,7 @@ description: ${description}
|
|
|
5979
5479
|
shardYaml += `state: true
|
|
5980
5480
|
`;
|
|
5981
5481
|
}
|
|
5982
|
-
await
|
|
5482
|
+
await writeFile7(join12(shardPath, "shard.yaml"), shardYaml);
|
|
5983
5483
|
const setupLine = options.setup ? ` setup-${shorthand}.md # One-time setup guide
|
|
5984
5484
|
` : "";
|
|
5985
5485
|
const readmeContent = `# ${name}
|
|
@@ -6000,7 +5500,7 @@ ${setupLine} skills/ # sk-${shorthand}-{name}.md
|
|
|
6000
5500
|
install/ # Files to install into Mesh/
|
|
6001
5501
|
\`\`\`
|
|
6002
5502
|
`;
|
|
6003
|
-
await
|
|
5503
|
+
await writeFile7(join12(shardPath, "README.md"), readmeContent);
|
|
6004
5504
|
const setupRow = options.setup ? `
|
|
6005
5505
|
| Setup | \`setup-${shorthand}.md\` | One-time setup guide |` : "";
|
|
6006
5506
|
const stateRow = options.state ? `
|
|
@@ -6031,7 +5531,7 @@ ${description}
|
|
|
6031
5531
|
|
|
6032
5532
|
(No knowledge files yet)
|
|
6033
5533
|
`;
|
|
6034
|
-
await
|
|
5534
|
+
await writeFile7(join12(shardPath, `init-${shorthand}.md`), initContent);
|
|
6035
5535
|
if (options.setup) {
|
|
6036
5536
|
const setupContent = `# Setup ${name}
|
|
6037
5537
|
|
|
@@ -6041,11 +5541,11 @@ One-time setup actions for ${name}.
|
|
|
6041
5541
|
|
|
6042
5542
|
1. (Define setup actions here)
|
|
6043
5543
|
`;
|
|
6044
|
-
await
|
|
5544
|
+
await writeFile7(join12(shardPath, `setup-${shorthand}.md`), setupContent);
|
|
6045
5545
|
}
|
|
6046
5546
|
if (options.state) {
|
|
6047
|
-
const stateDir =
|
|
6048
|
-
await
|
|
5547
|
+
const stateDir = join12(flintPath, "Mesh", "Shards");
|
|
5548
|
+
await mkdir9(stateDir, { recursive: true });
|
|
6049
5549
|
const stateContent = `---
|
|
6050
5550
|
id: ${randomUUID32()}
|
|
6051
5551
|
tags:
|
|
@@ -6057,7 +5557,7 @@ shard: ${shorthand}
|
|
|
6057
5557
|
|
|
6058
5558
|
State for the ${name} shard.
|
|
6059
5559
|
`;
|
|
6060
|
-
await
|
|
5560
|
+
await writeFile7(join12(stateDir, `(Shard) ${name}.md`), stateContent);
|
|
6061
5561
|
}
|
|
6062
5562
|
if (shardMode === "dev") {
|
|
6063
5563
|
const { execSync: execSync2 } = await import("child_process");
|
|
@@ -6069,7 +5569,7 @@ State for the ${name} shard.
|
|
|
6069
5569
|
}
|
|
6070
5570
|
async function cloneShardToDev(flintPath, sourcePath, manifest) {
|
|
6071
5571
|
const devFolderName = `(Dev) ${manifest.name}`;
|
|
6072
|
-
const devPath =
|
|
5572
|
+
const devPath = join12(flintPath, "Shards", devFolderName);
|
|
6073
5573
|
if (await exists(devPath)) {
|
|
6074
5574
|
await addShardToConfig(flintPath, devFolderName, `path:./Shards/${devFolderName}`, { mode: "dev" });
|
|
6075
5575
|
await recordShardVersion(flintPath, toKebabCase(manifest.name), manifest.version);
|
|
@@ -6081,7 +5581,7 @@ async function cloneShardToDev(flintPath, sourcePath, manifest) {
|
|
|
6081
5581
|
return { name: devFolderName, path: devPath };
|
|
6082
5582
|
}
|
|
6083
5583
|
async function registerExistingShard(flintPath, folderName) {
|
|
6084
|
-
const shardPath =
|
|
5584
|
+
const shardPath = join12(flintPath, "Shards", folderName);
|
|
6085
5585
|
if (!await exists(shardPath)) {
|
|
6086
5586
|
throw new Error(`Shard folder not found: Shards/${folderName}`);
|
|
6087
5587
|
}
|
|
@@ -6103,7 +5603,7 @@ async function registerExistingShard(flintPath, folderName) {
|
|
|
6103
5603
|
async function editShard(flintPath, folderName, source) {
|
|
6104
5604
|
const { execSync: execSync2 } = await import("child_process");
|
|
6105
5605
|
const { rename: rename42 } = await import("fs/promises");
|
|
6106
|
-
const shardPath =
|
|
5606
|
+
const shardPath = join12(flintPath, "Shards", folderName);
|
|
6107
5607
|
if (!await exists(shardPath)) {
|
|
6108
5608
|
throw new Error(`Shard folder not found: Shards/${folderName}`);
|
|
6109
5609
|
}
|
|
@@ -6115,21 +5615,21 @@ async function editShard(flintPath, folderName, source) {
|
|
|
6115
5615
|
}
|
|
6116
5616
|
const baseName = folderName.replace(/^\([^)]*\)\s*/, "");
|
|
6117
5617
|
const devFolderName = `(Dev) ${baseName}`;
|
|
6118
|
-
const devPath =
|
|
5618
|
+
const devPath = join12(flintPath, "Shards", devFolderName);
|
|
6119
5619
|
if (await exists(devPath)) {
|
|
6120
5620
|
throw new Error(`Dev folder already exists: Shards/${devFolderName}`);
|
|
6121
5621
|
}
|
|
6122
5622
|
await rename42(shardPath, devPath);
|
|
6123
5623
|
if (isGitHubSourceSpecifier(source)) {
|
|
6124
|
-
const tmpDir =
|
|
5624
|
+
const tmpDir = join12(flintPath, ".flint", "_tmp_edit_" + Date.now());
|
|
6125
5625
|
try {
|
|
6126
5626
|
const parsed = parseShardSource(source);
|
|
6127
5627
|
execSync2(`git clone --depth 1 "https://github.com/${parsed.owner}/${parsed.repo}.git" "${tmpDir}"`, { stdio: "pipe", timeout: 6e4 });
|
|
6128
|
-
await copyDir2(
|
|
5628
|
+
await copyDir2(join12(tmpDir, ".git"), join12(devPath, ".git"));
|
|
6129
5629
|
} catch {
|
|
6130
5630
|
execSync2("git init", { cwd: devPath, stdio: "pipe" });
|
|
6131
5631
|
} finally {
|
|
6132
|
-
await
|
|
5632
|
+
await rm62(tmpDir, { recursive: true, force: true });
|
|
6133
5633
|
}
|
|
6134
5634
|
} else {
|
|
6135
5635
|
execSync2("git init", { cwd: devPath, stdio: "pipe" });
|
|
@@ -6142,14 +5642,14 @@ async function editShard(flintPath, folderName, source) {
|
|
|
6142
5642
|
async function freezeShard(flintPath, folderName) {
|
|
6143
5643
|
const { execSync: execSync2 } = await import("child_process");
|
|
6144
5644
|
const { rename: rename42 } = await import("fs/promises");
|
|
6145
|
-
const shardPath =
|
|
5645
|
+
const shardPath = join12(flintPath, "Shards", folderName);
|
|
6146
5646
|
if (!await exists(shardPath)) {
|
|
6147
5647
|
throw new Error(`Shard folder not found: Shards/${folderName}`);
|
|
6148
5648
|
}
|
|
6149
5649
|
if (!folderName.startsWith("(Dev)")) {
|
|
6150
5650
|
throw new Error(`"${folderName}" is not a dev shard.`);
|
|
6151
5651
|
}
|
|
6152
|
-
const gitDir =
|
|
5652
|
+
const gitDir = join12(shardPath, ".git");
|
|
6153
5653
|
if (!await exists(gitDir)) {
|
|
6154
5654
|
throw new Error(`"${folderName}" has no .git directory.`);
|
|
6155
5655
|
}
|
|
@@ -6177,11 +5677,11 @@ async function freezeShard(flintPath, folderName) {
|
|
|
6177
5677
|
const decl = declarations[kebab];
|
|
6178
5678
|
const source = decl?.source || "";
|
|
6179
5679
|
const baseName = folderName.replace(/^\(Dev\)\s*/, "");
|
|
6180
|
-
const normalPath =
|
|
5680
|
+
const normalPath = join12(flintPath, "Shards", baseName);
|
|
6181
5681
|
if (await exists(normalPath)) {
|
|
6182
5682
|
throw new Error(`Normal folder already exists: Shards/${baseName}`);
|
|
6183
5683
|
}
|
|
6184
|
-
await
|
|
5684
|
+
await rm62(gitDir, { recursive: true, force: true });
|
|
6185
5685
|
await rename42(shardPath, normalPath);
|
|
6186
5686
|
await removeShardFromConfig(flintPath, kebab);
|
|
6187
5687
|
const normalSource = isGitHubSourceSpecifier(source) ? source : `path:./Shards/${baseName}`;
|
|
@@ -6190,14 +5690,14 @@ async function freezeShard(flintPath, folderName) {
|
|
|
6190
5690
|
}
|
|
6191
5691
|
async function addShardGitRemote(flintPath, folderName, url) {
|
|
6192
5692
|
const { execSync: execSync2 } = await import("child_process");
|
|
6193
|
-
const shardPath =
|
|
5693
|
+
const shardPath = join12(flintPath, "Shards", folderName);
|
|
6194
5694
|
if (!await exists(shardPath)) {
|
|
6195
5695
|
throw new Error(`Shard folder not found: Shards/${folderName}`);
|
|
6196
5696
|
}
|
|
6197
5697
|
if (!folderName.startsWith("(Dev)")) {
|
|
6198
5698
|
throw new Error(`"${folderName}" is not a dev shard. Only dev shards can have git remotes added.`);
|
|
6199
5699
|
}
|
|
6200
|
-
const gitDir =
|
|
5700
|
+
const gitDir = join12(shardPath, ".git");
|
|
6201
5701
|
if (!await exists(gitDir)) {
|
|
6202
5702
|
throw new Error(`"${folderName}" has no .git directory. Run git init first.`);
|
|
6203
5703
|
}
|
|
@@ -6236,7 +5736,7 @@ async function installDependency(flintPath, source, version) {
|
|
|
6236
5736
|
}
|
|
6237
5737
|
async function countFiles2(dirPath) {
|
|
6238
5738
|
try {
|
|
6239
|
-
const entries = await
|
|
5739
|
+
const entries = await readdir52(dirPath, { withFileTypes: true });
|
|
6240
5740
|
return entries.filter((e) => e.isFile() && e.name.endsWith(".md")).length;
|
|
6241
5741
|
} catch {
|
|
6242
5742
|
return 0;
|
|
@@ -6250,7 +5750,7 @@ async function checkShardHealth(flintPath) {
|
|
|
6250
5750
|
for (const folder of installedFolders) {
|
|
6251
5751
|
const kebab = toKebabCase(folder);
|
|
6252
5752
|
if (!declaredKebabNames.has(kebab)) {
|
|
6253
|
-
const shardPath =
|
|
5753
|
+
const shardPath = join13(flintPath, "Shards", folder);
|
|
6254
5754
|
const manifest = await readShardManifest(shardPath);
|
|
6255
5755
|
if (manifest?.name && manifest?.shorthand) {
|
|
6256
5756
|
const detectedMode = folder.startsWith("(Custom)") ? "custom" : "dev";
|
|
@@ -6276,7 +5776,7 @@ async function checkShardHealth(flintPath) {
|
|
|
6276
5776
|
for (const [name, decl] of Object.entries(declarations)) {
|
|
6277
5777
|
if (decl.source.startsWith("path:")) {
|
|
6278
5778
|
const relativePath = decl.source.slice(5);
|
|
6279
|
-
const fullPath =
|
|
5779
|
+
const fullPath = join13(flintPath, relativePath);
|
|
6280
5780
|
if (!await exists(fullPath)) {
|
|
6281
5781
|
results.push({
|
|
6282
5782
|
check: `${name} (${decl.source})`,
|
|
@@ -6293,7 +5793,7 @@ async function checkShardHealth(flintPath) {
|
|
|
6293
5793
|
for (const [name, decl] of Object.entries(declarations)) {
|
|
6294
5794
|
if (decl.source.startsWith("path:") && resolveShardMode(decl) === "dev") {
|
|
6295
5795
|
const relativePath = decl.source.slice(5);
|
|
6296
|
-
const fullPath =
|
|
5796
|
+
const fullPath = join13(flintPath, relativePath);
|
|
6297
5797
|
if (await exists(fullPath)) {
|
|
6298
5798
|
const remoteUrl = getGitRemoteUrl(fullPath);
|
|
6299
5799
|
if (remoteUrl) {
|
|
@@ -6316,7 +5816,7 @@ async function checkShardHealth(flintPath) {
|
|
|
6316
5816
|
}
|
|
6317
5817
|
}
|
|
6318
5818
|
for (const folder of installedFolders) {
|
|
6319
|
-
const shardPath =
|
|
5819
|
+
const shardPath = join13(flintPath, "Shards", folder);
|
|
6320
5820
|
const manifest = await readShardManifest(shardPath);
|
|
6321
5821
|
if (!manifest) {
|
|
6322
5822
|
results.push({
|
|
@@ -6332,7 +5832,7 @@ name: ${name}
|
|
|
6332
5832
|
shorthand: ${shorthand}
|
|
6333
5833
|
description: ${name} shard
|
|
6334
5834
|
`;
|
|
6335
|
-
await
|
|
5835
|
+
await writeFile8(join13(shardPath, "shard.yaml"), yaml);
|
|
6336
5836
|
},
|
|
6337
5837
|
actionLabel: `Create minimal shard.yaml for ${folder}`
|
|
6338
5838
|
});
|
|
@@ -6351,21 +5851,21 @@ description: ${name} shard
|
|
|
6351
5851
|
const SHARD_SPEC_DIRS_CONSUMER = ["skills", "workflows", "templates", "knowledge"];
|
|
6352
5852
|
const SHARD_SPEC_DIRS_DEV = [...SHARD_SPEC_DIRS_CONSUMER, "assets", "install", "migrations", "scripts"];
|
|
6353
5853
|
for (const folder of installedFolders) {
|
|
6354
|
-
const shardPath =
|
|
5854
|
+
const shardPath = join13(flintPath, "Shards", folder);
|
|
6355
5855
|
const manifest = await readShardManifest(shardPath);
|
|
6356
5856
|
const kebab = toKebabCase(folder);
|
|
6357
5857
|
const decl = declarations[kebab];
|
|
6358
5858
|
const mode = decl ? resolveShardMode(decl) : void 0;
|
|
6359
5859
|
const expectedDirs = mode === "dev" ? SHARD_SPEC_DIRS_DEV : SHARD_SPEC_DIRS_CONSUMER;
|
|
6360
5860
|
for (const dir of expectedDirs) {
|
|
6361
|
-
const dirPath =
|
|
5861
|
+
const dirPath = join13(shardPath, dir);
|
|
6362
5862
|
if (!await exists(dirPath)) {
|
|
6363
5863
|
results.push({
|
|
6364
5864
|
check: `Shards/${folder}/${dir}/`,
|
|
6365
5865
|
status: "warning",
|
|
6366
5866
|
message: "Missing shard-spec directory",
|
|
6367
5867
|
action: async () => {
|
|
6368
|
-
await
|
|
5868
|
+
await mkdir10(dirPath, { recursive: true });
|
|
6369
5869
|
},
|
|
6370
5870
|
actionLabel: `Create ${dir}/ in ${folder}`
|
|
6371
5871
|
});
|
|
@@ -6375,7 +5875,7 @@ description: ${name} shard
|
|
|
6375
5875
|
const installedWithVersions = await getInstalledShardsWithVersions(flintPath);
|
|
6376
5876
|
const installedVersionMap = new Map(installedWithVersions.map((s) => [s.name, s.version]));
|
|
6377
5877
|
for (const folder of installedFolders) {
|
|
6378
|
-
const shardPath =
|
|
5878
|
+
const shardPath = join13(flintPath, "Shards", folder);
|
|
6379
5879
|
const manifest = await readShardManifest(shardPath);
|
|
6380
5880
|
if (!manifest?.dependencies?.length) continue;
|
|
6381
5881
|
for (const dep of manifest.dependencies) {
|
|
@@ -6430,7 +5930,7 @@ description: ${name} shard
|
|
|
6430
5930
|
}
|
|
6431
5931
|
function getGitRemoteUrl(shardPath) {
|
|
6432
5932
|
try {
|
|
6433
|
-
const gitDir =
|
|
5933
|
+
const gitDir = join13(shardPath, ".git");
|
|
6434
5934
|
if (!existsSync(gitDir)) return null;
|
|
6435
5935
|
return execSync("git remote get-url origin", {
|
|
6436
5936
|
cwd: shardPath,
|
|
@@ -6443,7 +5943,7 @@ function getGitRemoteUrl(shardPath) {
|
|
|
6443
5943
|
}
|
|
6444
5944
|
async function healShard(flintPath, folderName) {
|
|
6445
5945
|
const results = [];
|
|
6446
|
-
const shardPath =
|
|
5946
|
+
const shardPath = join13(flintPath, "Shards", folderName);
|
|
6447
5947
|
const kebab = toKebabCase(folderName);
|
|
6448
5948
|
const manifest = await readShardManifest(shardPath);
|
|
6449
5949
|
if (!manifest) {
|
|
@@ -6460,7 +5960,7 @@ name: ${name}
|
|
|
6460
5960
|
shorthand: ${shorthand2}
|
|
6461
5961
|
description: ${name} shard
|
|
6462
5962
|
`;
|
|
6463
|
-
await
|
|
5963
|
+
await writeFile8(join13(shardPath, "shard.yaml"), yaml);
|
|
6464
5964
|
},
|
|
6465
5965
|
actionLabel: `Create shard.yaml`
|
|
6466
5966
|
});
|
|
@@ -6524,21 +6024,21 @@ description: ${name} shard
|
|
|
6524
6024
|
const mode = decl ? resolveShardMode(decl) : void 0;
|
|
6525
6025
|
const expectedDirs = mode === "dev" ? DEV_DIRS : CONSUMER_DIRS;
|
|
6526
6026
|
for (const dir of expectedDirs) {
|
|
6527
|
-
const dirPath =
|
|
6027
|
+
const dirPath = join13(shardPath, dir);
|
|
6528
6028
|
if (!await exists(dirPath)) {
|
|
6529
6029
|
results.push({
|
|
6530
6030
|
check: `${dir}/`,
|
|
6531
6031
|
status: "warning",
|
|
6532
6032
|
message: "Missing directory",
|
|
6533
6033
|
action: async () => {
|
|
6534
|
-
await
|
|
6034
|
+
await mkdir10(dirPath, { recursive: true });
|
|
6535
6035
|
},
|
|
6536
6036
|
actionLabel: `Create ${dir}/`
|
|
6537
6037
|
});
|
|
6538
6038
|
}
|
|
6539
6039
|
}
|
|
6540
6040
|
const shorthand = manifest?.shorthand || kebab.replace(/-/g, "").slice(0, 4);
|
|
6541
|
-
const initFile =
|
|
6041
|
+
const initFile = join13(shardPath, `init-${shorthand}.md`);
|
|
6542
6042
|
if (!await exists(initFile)) {
|
|
6543
6043
|
results.push({
|
|
6544
6044
|
check: `init-${shorthand}.md`,
|
|
@@ -6550,21 +6050,21 @@ description: ${name} shard
|
|
|
6550
6050
|
|
|
6551
6051
|
Describe the shard context here.
|
|
6552
6052
|
`;
|
|
6553
|
-
await
|
|
6053
|
+
await writeFile8(initFile, content);
|
|
6554
6054
|
},
|
|
6555
6055
|
actionLabel: `Create init-${shorthand}.md`
|
|
6556
6056
|
});
|
|
6557
6057
|
}
|
|
6558
6058
|
if (manifest?.folders) {
|
|
6559
6059
|
for (const folder of manifest.folders) {
|
|
6560
|
-
const meshPath =
|
|
6060
|
+
const meshPath = join13(flintPath, folder);
|
|
6561
6061
|
if (!await exists(meshPath)) {
|
|
6562
6062
|
results.push({
|
|
6563
6063
|
check: `${folder}`,
|
|
6564
6064
|
status: "warning",
|
|
6565
6065
|
message: "Declared Mesh folder missing",
|
|
6566
6066
|
action: async () => {
|
|
6567
|
-
await
|
|
6067
|
+
await mkdir10(meshPath, { recursive: true });
|
|
6568
6068
|
},
|
|
6569
6069
|
actionLabel: `Create ${folder}`
|
|
6570
6070
|
});
|
|
@@ -6573,7 +6073,7 @@ Describe the shard context here.
|
|
|
6573
6073
|
}
|
|
6574
6074
|
const checkFilePrefix = async (dir, prefix) => {
|
|
6575
6075
|
try {
|
|
6576
|
-
const entries = await
|
|
6076
|
+
const entries = await readdir52(join13(shardPath, dir), { withFileTypes: true });
|
|
6577
6077
|
for (const entry of entries) {
|
|
6578
6078
|
if (entry.isFile() && entry.name.endsWith(".md") && !entry.name.startsWith(prefix)) {
|
|
6579
6079
|
results.push({
|
|
@@ -6588,7 +6088,7 @@ Describe the shard context here.
|
|
|
6588
6088
|
};
|
|
6589
6089
|
const checkInstallNaming = async (shorthandValue) => {
|
|
6590
6090
|
try {
|
|
6591
|
-
const entries = await
|
|
6091
|
+
const entries = await readdir52(join13(shardPath, "install"), { withFileTypes: true });
|
|
6592
6092
|
for (const entry of entries) {
|
|
6593
6093
|
if (!entry.isFile()) continue;
|
|
6594
6094
|
const expectedPrefix = entry.name.startsWith("type-") ? `type-${shorthandValue}-` : entry.name.startsWith("inst-") ? `inst-${shorthandValue}-` : null;
|
|
@@ -6639,7 +6139,7 @@ async function getShardInfo(flintPath, identifier) {
|
|
|
6639
6139
|
const installed = await getInstalledShardsWithVersions(flintPath);
|
|
6640
6140
|
const match = resolveInstalledShardInfo(installed, identifier);
|
|
6641
6141
|
if (match) {
|
|
6642
|
-
const shardPath =
|
|
6142
|
+
const shardPath = join13(flintPath, "Shards", match.folderName);
|
|
6643
6143
|
const manifest = await readShardManifest(shardPath);
|
|
6644
6144
|
const decl = declarations[match.name];
|
|
6645
6145
|
return {
|
|
@@ -6651,10 +6151,10 @@ async function getShardInfo(flintPath, identifier) {
|
|
|
6651
6151
|
dev: decl ? resolveShardMode(decl) === "dev" : false,
|
|
6652
6152
|
mode: decl ? resolveShardMode(decl) || "normal" : "normal",
|
|
6653
6153
|
folderName: match.folderName,
|
|
6654
|
-
skillCount: await countFiles2(
|
|
6655
|
-
templateCount: await countFiles2(
|
|
6656
|
-
workflowCount: await countFiles2(
|
|
6657
|
-
knowledgeCount: await countFiles2(
|
|
6154
|
+
skillCount: await countFiles2(join13(shardPath, "skills")),
|
|
6155
|
+
templateCount: await countFiles2(join13(shardPath, "templates")),
|
|
6156
|
+
workflowCount: await countFiles2(join13(shardPath, "workflows")),
|
|
6157
|
+
knowledgeCount: await countFiles2(join13(shardPath, "knowledge"))
|
|
6658
6158
|
};
|
|
6659
6159
|
}
|
|
6660
6160
|
return null;
|
|
@@ -6664,7 +6164,7 @@ async function findShardFolder(flintPath, identifier) {
|
|
|
6664
6164
|
return resolveInstalledShardInfo(installed, identifier)?.folderName ?? null;
|
|
6665
6165
|
}
|
|
6666
6166
|
function getShardScriptsDir(flintPath, shardFolder) {
|
|
6667
|
-
return
|
|
6167
|
+
return join14(flintPath, "Shards", shardFolder, "scripts");
|
|
6668
6168
|
}
|
|
6669
6169
|
async function listShardScripts(flintPath, shardIdentifier) {
|
|
6670
6170
|
const shardFolder = await findShardFolder(flintPath, shardIdentifier);
|
|
@@ -6673,14 +6173,14 @@ async function listShardScripts(flintPath, shardIdentifier) {
|
|
|
6673
6173
|
}
|
|
6674
6174
|
const scriptsDir = getShardScriptsDir(flintPath, shardFolder);
|
|
6675
6175
|
try {
|
|
6676
|
-
const entries = await
|
|
6176
|
+
const entries = await readdir62(scriptsDir, { withFileTypes: true });
|
|
6677
6177
|
const scripts = [];
|
|
6678
6178
|
for (const entry of entries) {
|
|
6679
6179
|
if (entry.isFile()) {
|
|
6680
6180
|
const name = entry.name.replace(/\.[^.]+$/, "");
|
|
6681
6181
|
scripts.push({
|
|
6682
6182
|
name,
|
|
6683
|
-
path:
|
|
6183
|
+
path: join14(scriptsDir, entry.name)
|
|
6684
6184
|
});
|
|
6685
6185
|
}
|
|
6686
6186
|
}
|
|
@@ -6691,15 +6191,15 @@ async function listShardScripts(flintPath, shardIdentifier) {
|
|
|
6691
6191
|
}
|
|
6692
6192
|
async function findScript(scriptsDir, scriptName) {
|
|
6693
6193
|
try {
|
|
6694
|
-
const entries = await
|
|
6194
|
+
const entries = await readdir62(scriptsDir);
|
|
6695
6195
|
if (entries.includes(scriptName)) {
|
|
6696
|
-
return
|
|
6196
|
+
return join14(scriptsDir, scriptName);
|
|
6697
6197
|
}
|
|
6698
6198
|
const extensions = [".sh", ".js", ".ts", ".mjs", ".py", ""];
|
|
6699
6199
|
for (const ext of extensions) {
|
|
6700
6200
|
const filename = scriptName + ext;
|
|
6701
6201
|
if (entries.includes(filename)) {
|
|
6702
|
-
return
|
|
6202
|
+
return join14(scriptsDir, filename);
|
|
6703
6203
|
}
|
|
6704
6204
|
}
|
|
6705
6205
|
return null;
|
|
@@ -6749,11 +6249,11 @@ async function runShardScript(flintPath, shardIdentifier, scriptName, args = [])
|
|
|
6749
6249
|
const scriptNames = available.map((s) => s.name).join(", ");
|
|
6750
6250
|
throw new Error(`Script "${scriptName}" not found. Available: ${scriptNames}`);
|
|
6751
6251
|
}
|
|
6752
|
-
const resolvedFlintPath =
|
|
6252
|
+
const resolvedFlintPath = resolve6(flintPath);
|
|
6753
6253
|
const runner = await getScriptRunner(scriptPath);
|
|
6754
6254
|
const fullArgs = [...runner.args, ...args];
|
|
6755
|
-
return new Promise((
|
|
6756
|
-
const child =
|
|
6255
|
+
return new Promise((resolve8, reject) => {
|
|
6256
|
+
const child = spawn(runner.command, fullArgs, {
|
|
6757
6257
|
cwd: resolvedFlintPath,
|
|
6758
6258
|
env: {
|
|
6759
6259
|
...process.env,
|
|
@@ -6774,7 +6274,7 @@ async function runShardScript(flintPath, shardIdentifier, scriptName, args = [])
|
|
|
6774
6274
|
reject(new Error(`Failed to run script: ${err.message}`));
|
|
6775
6275
|
});
|
|
6776
6276
|
child.on("close", (code) => {
|
|
6777
|
-
|
|
6277
|
+
resolve8({
|
|
6778
6278
|
exitCode: code ?? 1,
|
|
6779
6279
|
stdout: stdout.trim(),
|
|
6780
6280
|
stderr: stderr.trim()
|
|
@@ -6848,23 +6348,23 @@ function buildSourcesEntries(config) {
|
|
|
6848
6348
|
}
|
|
6849
6349
|
async function shardHasGitRemote(shardPath) {
|
|
6850
6350
|
try {
|
|
6851
|
-
const configPath =
|
|
6852
|
-
const config = await
|
|
6351
|
+
const configPath = join15(shardPath, ".git", "config");
|
|
6352
|
+
const config = await readFile8(configPath, "utf-8");
|
|
6853
6353
|
return config.includes("[remote");
|
|
6854
6354
|
} catch {
|
|
6855
6355
|
return false;
|
|
6856
6356
|
}
|
|
6857
6357
|
}
|
|
6858
6358
|
async function buildShardEntries(flintPath) {
|
|
6859
|
-
const shardsDir =
|
|
6359
|
+
const shardsDir = join15(flintPath, "Shards");
|
|
6860
6360
|
if (!await exists(shardsDir)) return [];
|
|
6861
6361
|
const entries = [];
|
|
6862
6362
|
try {
|
|
6863
|
-
const folders = await
|
|
6363
|
+
const folders = await readdir72(shardsDir, { withFileTypes: true });
|
|
6864
6364
|
for (const folder of folders) {
|
|
6865
6365
|
if (!folder.isDirectory() || folder.name.startsWith("(System)")) continue;
|
|
6866
|
-
const gitDir =
|
|
6867
|
-
if (await exists(gitDir) && await shardHasGitRemote(
|
|
6366
|
+
const gitDir = join15(shardsDir, folder.name, ".git");
|
|
6367
|
+
if (await exists(gitDir) && await shardHasGitRemote(join15(shardsDir, folder.name))) {
|
|
6868
6368
|
entries.push(`Shards/${folder.name}/`);
|
|
6869
6369
|
}
|
|
6870
6370
|
}
|
|
@@ -6877,10 +6377,10 @@ function formatManagedContent(sections) {
|
|
|
6877
6377
|
${section.entries.join("\n")}`).join("\n\n");
|
|
6878
6378
|
}
|
|
6879
6379
|
async function createGitignore(flintPath) {
|
|
6880
|
-
const gitignorePath =
|
|
6380
|
+
const gitignorePath = join15(flintPath, ".gitignore");
|
|
6881
6381
|
const sections = await buildGitignoreEntries(flintPath);
|
|
6882
6382
|
const content = formatManagedContent(sections);
|
|
6883
|
-
await
|
|
6383
|
+
await writeFile9(
|
|
6884
6384
|
gitignorePath,
|
|
6885
6385
|
`${MANAGED_SECTION_START}
|
|
6886
6386
|
${content}
|
|
@@ -6889,10 +6389,10 @@ ${MANAGED_SECTION_END}
|
|
|
6889
6389
|
);
|
|
6890
6390
|
}
|
|
6891
6391
|
async function updateGitignore(flintPath) {
|
|
6892
|
-
const gitignorePath =
|
|
6392
|
+
const gitignorePath = join15(flintPath, ".gitignore");
|
|
6893
6393
|
let existing = "";
|
|
6894
6394
|
try {
|
|
6895
|
-
existing = await
|
|
6395
|
+
existing = await readFile8(gitignorePath, "utf-8");
|
|
6896
6396
|
} catch {
|
|
6897
6397
|
await createGitignore(flintPath);
|
|
6898
6398
|
return;
|
|
@@ -6911,15 +6411,15 @@ ${MANAGED_SECTION_END}`;
|
|
|
6911
6411
|
} else {
|
|
6912
6412
|
existing = existing.trim() + "\n\n" + managedSection + "\n";
|
|
6913
6413
|
}
|
|
6914
|
-
await
|
|
6414
|
+
await writeFile9(gitignorePath, existing.trim() + "\n");
|
|
6915
6415
|
}
|
|
6916
6416
|
function escapeRegex(str) {
|
|
6917
6417
|
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
6918
6418
|
}
|
|
6919
|
-
var
|
|
6419
|
+
var execAsync4 = promisify5(exec4);
|
|
6920
6420
|
async function isGitInitialized(flintPath) {
|
|
6921
6421
|
try {
|
|
6922
|
-
await
|
|
6422
|
+
await execAsync4("git rev-parse --git-dir", { cwd: flintPath });
|
|
6923
6423
|
return true;
|
|
6924
6424
|
} catch {
|
|
6925
6425
|
return false;
|
|
@@ -6927,7 +6427,7 @@ async function isGitInitialized(flintPath) {
|
|
|
6927
6427
|
}
|
|
6928
6428
|
async function initGit(flintPath) {
|
|
6929
6429
|
try {
|
|
6930
|
-
await
|
|
6430
|
+
await execAsync4("git init", { cwd: flintPath });
|
|
6931
6431
|
await createGitignore(flintPath);
|
|
6932
6432
|
return { success: true, output: "Git initialized with .gitignore" };
|
|
6933
6433
|
} catch (err) {
|
|
@@ -6950,10 +6450,10 @@ async function getGitStatus(flintPath) {
|
|
|
6950
6450
|
};
|
|
6951
6451
|
}
|
|
6952
6452
|
try {
|
|
6953
|
-
const { stdout: branchOut } = await
|
|
6453
|
+
const { stdout: branchOut } = await execAsync4("git branch --show-current", {
|
|
6954
6454
|
cwd: flintPath
|
|
6955
6455
|
});
|
|
6956
|
-
const { stdout: statusOut } = await
|
|
6456
|
+
const { stdout: statusOut } = await execAsync4("git status --porcelain", {
|
|
6957
6457
|
cwd: flintPath
|
|
6958
6458
|
});
|
|
6959
6459
|
const lines = statusOut.trim().split("\n").filter(Boolean);
|
|
@@ -6995,7 +6495,7 @@ async function runGit(flintPath, args, options) {
|
|
|
6995
6495
|
const quotedArgs = args.map(
|
|
6996
6496
|
(arg) => arg.includes(" ") ? `"${arg}"` : arg
|
|
6997
6497
|
);
|
|
6998
|
-
const { stdout, stderr } = await
|
|
6498
|
+
const { stdout, stderr } = await execAsync4(`git ${quotedArgs.join(" ")}`, {
|
|
6999
6499
|
cwd: flintPath,
|
|
7000
6500
|
env: options?.env ? { ...process.env, ...options.env } : void 0
|
|
7001
6501
|
});
|
|
@@ -7072,11 +6572,11 @@ async function isRebaseInProgress(cwd) {
|
|
|
7072
6572
|
async function getRebaseBranch(cwd) {
|
|
7073
6573
|
const result = await runGit(cwd, ["rev-parse", "--git-path", "rebase-merge/head-name"]);
|
|
7074
6574
|
if (result.success) {
|
|
7075
|
-
const { readFile:
|
|
6575
|
+
const { readFile: readFile10 } = await import("fs/promises");
|
|
7076
6576
|
const path = await import("path");
|
|
7077
6577
|
const headNamePath = path.resolve(cwd, result.output.trim());
|
|
7078
6578
|
try {
|
|
7079
|
-
const ref = (await
|
|
6579
|
+
const ref = (await readFile10(headNamePath, "utf-8")).trim();
|
|
7080
6580
|
return ref.replace(/^refs\/heads\//, "");
|
|
7081
6581
|
} catch {
|
|
7082
6582
|
}
|
|
@@ -7091,7 +6591,7 @@ async function getConflictFiles(cwd) {
|
|
|
7091
6591
|
return [];
|
|
7092
6592
|
}
|
|
7093
6593
|
async function hasConflictMarkers(cwd, files) {
|
|
7094
|
-
const { readFile:
|
|
6594
|
+
const { readFile: readFile10 } = await import("fs/promises");
|
|
7095
6595
|
const path = await import("path");
|
|
7096
6596
|
let filesToCheck = files;
|
|
7097
6597
|
if (!filesToCheck || filesToCheck.length === 0) {
|
|
@@ -7110,7 +6610,7 @@ async function hasConflictMarkers(cwd, files) {
|
|
|
7110
6610
|
const conflicted = [];
|
|
7111
6611
|
for (const file of filesToCheck) {
|
|
7112
6612
|
try {
|
|
7113
|
-
const content = await
|
|
6613
|
+
const content = await readFile10(path.resolve(cwd, file), "utf-8");
|
|
7114
6614
|
if (content.includes("<<<<<<<") && content.includes("=======") && content.includes(">>>>>>>")) {
|
|
7115
6615
|
conflicted.push(file);
|
|
7116
6616
|
}
|
|
@@ -7147,10 +6647,10 @@ async function syncFlint(flintPath, progress) {
|
|
|
7147
6647
|
};
|
|
7148
6648
|
const flintConfigDir = getFlintConfigDir(flintPath);
|
|
7149
6649
|
try {
|
|
7150
|
-
await
|
|
6650
|
+
await stat72(flintConfigDir);
|
|
7151
6651
|
} catch {
|
|
7152
6652
|
try {
|
|
7153
|
-
await
|
|
6653
|
+
await mkdir11(flintConfigDir, { recursive: true });
|
|
7154
6654
|
result.bootstrap.created = true;
|
|
7155
6655
|
} catch (err) {
|
|
7156
6656
|
result.errors.push({
|
|
@@ -7160,11 +6660,11 @@ async function syncFlint(flintPath, progress) {
|
|
|
7160
6660
|
}
|
|
7161
6661
|
}
|
|
7162
6662
|
for (const dir of STANDARD_DIRECTORIES) {
|
|
7163
|
-
const dirPath =
|
|
6663
|
+
const dirPath = join16(flintPath, dir);
|
|
7164
6664
|
try {
|
|
7165
|
-
await
|
|
6665
|
+
await stat72(dirPath);
|
|
7166
6666
|
} catch {
|
|
7167
|
-
await
|
|
6667
|
+
await mkdir11(dirPath, { recursive: true });
|
|
7168
6668
|
result.bootstrap.directories.push(dir);
|
|
7169
6669
|
}
|
|
7170
6670
|
}
|
|
@@ -7183,9 +6683,9 @@ async function syncFlint(flintPath, progress) {
|
|
|
7183
6683
|
error: `Failed to sync metadata: ${err instanceof Error ? err.message : String(err)}`
|
|
7184
6684
|
});
|
|
7185
6685
|
}
|
|
7186
|
-
const obsidianDir =
|
|
6686
|
+
const obsidianDir = join16(flintPath, ".obsidian");
|
|
7187
6687
|
try {
|
|
7188
|
-
await
|
|
6688
|
+
await stat72(obsidianDir);
|
|
7189
6689
|
result.obsidian.existed = true;
|
|
7190
6690
|
} catch {
|
|
7191
6691
|
try {
|
|
@@ -7209,8 +6709,8 @@ async function syncFlint(flintPath, progress) {
|
|
|
7209
6709
|
const shardsToUninstall = installedShards.filter((s) => !requiredShardSet.has(s.name)).map((s) => s.name);
|
|
7210
6710
|
{
|
|
7211
6711
|
const { exec: execCb } = await import("child_process");
|
|
7212
|
-
const { promisify:
|
|
7213
|
-
const
|
|
6712
|
+
const { promisify: promisify6 } = await import("util");
|
|
6713
|
+
const execAsync5 = promisify6(execCb);
|
|
7214
6714
|
const shardTasks = [];
|
|
7215
6715
|
for (const kebabName of shardsToInstall) {
|
|
7216
6716
|
const declaration = shardDeclarations[kebabName];
|
|
@@ -7233,9 +6733,9 @@ async function syncFlint(flintPath, progress) {
|
|
|
7233
6733
|
throw new Error(`Dev shard source is not a GitHub source: ${source}`);
|
|
7234
6734
|
}
|
|
7235
6735
|
const folderName = `(Dev) ${kebabName.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ")}`;
|
|
7236
|
-
const devPath =
|
|
6736
|
+
const devPath = join16(flintPath, "Shards", folderName);
|
|
7237
6737
|
const cloneUrl = `https://github.com/${parsed.owner}/${parsed.repo}.git`;
|
|
7238
|
-
await
|
|
6738
|
+
await execAsync5(`git clone "${cloneUrl}" "${devPath}"`, { timeout: 6e4 });
|
|
7239
6739
|
await pullShard(flintPath, folderName, { force: true });
|
|
7240
6740
|
}
|
|
7241
6741
|
});
|
|
@@ -7292,28 +6792,28 @@ async function syncFlint(flintPath, progress) {
|
|
|
7292
6792
|
}
|
|
7293
6793
|
}
|
|
7294
6794
|
const requiredMeshExports = config.sources?.meshexports || [];
|
|
7295
|
-
const { getFlintRegistry: getFlintRegistry2 } = await import("./registry-
|
|
7296
|
-
const { readdir:
|
|
7297
|
-
const { syncSourceMeshExportMetadata: syncSourceMeshExportMetadata2 } = await import("./metadata-
|
|
6795
|
+
const { getFlintRegistry: getFlintRegistry2 } = await import("./registry-5CNUVQN3-PCQZRXLB.js");
|
|
6796
|
+
const { readdir: readdir9, readFile: fsReadFile, rm: rm7, stat: fsStat, mkdir: fsMkdir, copyFile: fsCopyFile } = await import("fs/promises");
|
|
6797
|
+
const { syncSourceMeshExportMetadata: syncSourceMeshExportMetadata2 } = await import("./metadata-FASTWX6A-ITKM6C62.js");
|
|
7298
6798
|
const requiredMeshExportSet = new Set(requiredMeshExports);
|
|
7299
|
-
const sourcesFlintDir =
|
|
6799
|
+
const sourcesFlintDir = join16(flintPath, "Sources", "Flints");
|
|
7300
6800
|
try {
|
|
7301
|
-
const flintFolders = await
|
|
6801
|
+
const flintFolders = await readdir9(sourcesFlintDir, { withFileTypes: true });
|
|
7302
6802
|
for (const flintFolder of flintFolders) {
|
|
7303
6803
|
if (!flintFolder.isDirectory()) continue;
|
|
7304
6804
|
const flintFolderName = flintFolder.name;
|
|
7305
6805
|
const flintName = flintFolderName.replace(/^\(Flint\)\s*/, "");
|
|
7306
|
-
const flintSourcePath =
|
|
7307
|
-
const exportFolders = await
|
|
6806
|
+
const flintSourcePath = join16(sourcesFlintDir, flintFolderName);
|
|
6807
|
+
const exportFolders = await readdir9(flintSourcePath, { withFileTypes: true });
|
|
7308
6808
|
for (const exportFolder of exportFolders) {
|
|
7309
6809
|
if (!exportFolder.isDirectory()) continue;
|
|
7310
6810
|
const exportFolderName = exportFolder.name;
|
|
7311
6811
|
const exportName = exportFolderName.replace(/^\(Mesh Export\)\s*/, "");
|
|
7312
6812
|
const ref = `${flintName}/${exportName}`;
|
|
7313
6813
|
if (!requiredMeshExportSet.has(ref)) {
|
|
7314
|
-
const exportPath =
|
|
6814
|
+
const exportPath = join16(flintSourcePath, exportFolderName);
|
|
7315
6815
|
try {
|
|
7316
|
-
await
|
|
6816
|
+
await rm7(exportPath, { recursive: true });
|
|
7317
6817
|
result.meshexports.push({ ref, status: "removed" });
|
|
7318
6818
|
} catch (err) {
|
|
7319
6819
|
result.meshexports.push({
|
|
@@ -7324,10 +6824,10 @@ async function syncFlint(flintPath, progress) {
|
|
|
7324
6824
|
}
|
|
7325
6825
|
}
|
|
7326
6826
|
}
|
|
7327
|
-
const remaining = await
|
|
6827
|
+
const remaining = await readdir9(flintSourcePath);
|
|
7328
6828
|
if (remaining.length === 0) {
|
|
7329
6829
|
try {
|
|
7330
|
-
await
|
|
6830
|
+
await rm7(flintSourcePath, { recursive: true });
|
|
7331
6831
|
} catch {
|
|
7332
6832
|
}
|
|
7333
6833
|
}
|
|
@@ -7336,7 +6836,7 @@ async function syncFlint(flintPath, progress) {
|
|
|
7336
6836
|
}
|
|
7337
6837
|
if (requiredMeshExports.length > 0) {
|
|
7338
6838
|
const registry = await getFlintRegistry2();
|
|
7339
|
-
const { buildExportByName: buildExportByName2, scanExports: scanExports2 } = await import("./exports-
|
|
6839
|
+
const { buildExportByName: buildExportByName2, scanExports: scanExports2 } = await import("./exports-VR7XB6MC-5N77WY3S.js");
|
|
7340
6840
|
for (const ref of requiredMeshExports) {
|
|
7341
6841
|
const parts = ref.split("/");
|
|
7342
6842
|
if (parts.length !== 2) {
|
|
@@ -7353,7 +6853,7 @@ async function syncFlint(flintPath, progress) {
|
|
|
7353
6853
|
return simpleName === flintName || f.name === flintName;
|
|
7354
6854
|
});
|
|
7355
6855
|
if (!sourceFlint) {
|
|
7356
|
-
const destDir2 =
|
|
6856
|
+
const destDir2 = join16(flintPath, "Sources", "Flints", `(Flint) ${flintName}`, `(Mesh Export) ${exportName}`);
|
|
7357
6857
|
try {
|
|
7358
6858
|
await fsStat(destDir2);
|
|
7359
6859
|
result.meshexports.push({ ref, status: "unavailable" });
|
|
@@ -7381,34 +6881,34 @@ async function syncFlint(flintPath, progress) {
|
|
|
7381
6881
|
});
|
|
7382
6882
|
continue;
|
|
7383
6883
|
}
|
|
7384
|
-
const exportDir =
|
|
7385
|
-
const destDir =
|
|
6884
|
+
const exportDir = join16(sourceFlint.path, "Exports", `(Mesh Export) ${exportName}`);
|
|
6885
|
+
const destDir = join16(flintPath, "Sources", "Flints", `(Flint) ${flintName}`, `(Mesh Export) ${exportName}`);
|
|
7386
6886
|
try {
|
|
7387
6887
|
try {
|
|
7388
|
-
await
|
|
6888
|
+
await rm7(destDir, { recursive: true });
|
|
7389
6889
|
} catch {
|
|
7390
6890
|
}
|
|
7391
6891
|
let fileCount = 0;
|
|
7392
|
-
const meshSourceDir =
|
|
7393
|
-
const meshDestDir =
|
|
6892
|
+
const meshSourceDir = join16(exportDir, "Mesh");
|
|
6893
|
+
const meshDestDir = join16(destDir, "Mesh");
|
|
7394
6894
|
try {
|
|
7395
6895
|
await fsStat(meshSourceDir);
|
|
7396
6896
|
await fsMkdir(meshDestDir, { recursive: true });
|
|
7397
|
-
const meshFiles = await
|
|
6897
|
+
const meshFiles = await readdir9(meshSourceDir);
|
|
7398
6898
|
for (const file of meshFiles) {
|
|
7399
|
-
await fsCopyFile(
|
|
6899
|
+
await fsCopyFile(join16(meshSourceDir, file), join16(meshDestDir, file));
|
|
7400
6900
|
fileCount++;
|
|
7401
6901
|
}
|
|
7402
6902
|
} catch {
|
|
7403
6903
|
}
|
|
7404
|
-
const mediaSourceDir =
|
|
7405
|
-
const mediaDestDir =
|
|
6904
|
+
const mediaSourceDir = join16(exportDir, "Media");
|
|
6905
|
+
const mediaDestDir = join16(destDir, "Media");
|
|
7406
6906
|
try {
|
|
7407
6907
|
await fsStat(mediaSourceDir);
|
|
7408
6908
|
await fsMkdir(mediaDestDir, { recursive: true });
|
|
7409
|
-
const mediaFiles = await
|
|
6909
|
+
const mediaFiles = await readdir9(mediaSourceDir);
|
|
7410
6910
|
for (const file of mediaFiles) {
|
|
7411
|
-
await fsCopyFile(
|
|
6911
|
+
await fsCopyFile(join16(mediaSourceDir, file), join16(mediaDestDir, file));
|
|
7412
6912
|
fileCount++;
|
|
7413
6913
|
}
|
|
7414
6914
|
} catch {
|
|
@@ -7480,10 +6980,23 @@ async function syncFlint(flintPath, progress) {
|
|
|
7480
6980
|
error: `Failed to sync source repo metadata: ${err instanceof Error ? err.message : String(err)}`
|
|
7481
6981
|
});
|
|
7482
6982
|
}
|
|
7483
|
-
const { getPlateDeclarationsFromConfig } = await import("./mesh-config-
|
|
6983
|
+
const { getPlateDeclarationsFromConfig } = await import("./mesh-config-NTGFUNZL-BZ2GO3JY.js");
|
|
7484
6984
|
const plateDeclarations = getPlateDeclarationsFromConfig(config);
|
|
6985
|
+
const hasSourcePlates = Object.values(plateDeclarations).some((d) => d.source);
|
|
7485
6986
|
const hasRepoPlates = Object.values(plateDeclarations).some((d) => d.repo);
|
|
7486
|
-
if (
|
|
6987
|
+
if (hasSourcePlates) {
|
|
6988
|
+
const { syncDeclaredPlates: syncDeclaredPlates2 } = await import("./plates-UD55BGK4-HV7L7MQX.js");
|
|
6989
|
+
const plateResults = await syncDeclaredPlates2(flintPath, plateDeclarations);
|
|
6990
|
+
result.plates = plateResults;
|
|
6991
|
+
for (const pr of plateResults) {
|
|
6992
|
+
if (pr.status === "error") {
|
|
6993
|
+
result.errors.push({
|
|
6994
|
+
name: `plate:${pr.name}`,
|
|
6995
|
+
error: pr.error || "Unknown error"
|
|
6996
|
+
});
|
|
6997
|
+
}
|
|
6998
|
+
}
|
|
6999
|
+
} else if (hasRepoPlates) {
|
|
7487
7000
|
const plateResults = await syncPlateRepos(flintPath, plateDeclarations);
|
|
7488
7001
|
result.plates = plateResults;
|
|
7489
7002
|
for (const pr of plateResults) {
|
|
@@ -7500,11 +7013,11 @@ async function syncFlint(flintPath, progress) {
|
|
|
7500
7013
|
if (tomlName) {
|
|
7501
7014
|
try {
|
|
7502
7015
|
const registryEntry = await findFlintByPath(flintPath);
|
|
7503
|
-
const currentFolderName =
|
|
7016
|
+
const currentFolderName = basename3(flintPath);
|
|
7504
7017
|
const expectedFolderName = `(Flint) ${tomlName}`;
|
|
7505
7018
|
if (currentFolderName !== expectedFolderName) {
|
|
7506
7019
|
const parentDir = dirname5(flintPath);
|
|
7507
|
-
const newPath =
|
|
7020
|
+
const newPath = join16(parentDir, expectedFolderName);
|
|
7508
7021
|
try {
|
|
7509
7022
|
await rename32(flintPath, newPath);
|
|
7510
7023
|
currentFlintPath = newPath;
|
|
@@ -7550,11 +7063,11 @@ async function syncFlint(flintPath, progress) {
|
|
|
7550
7063
|
console.warn(`Registry sync warning: ${err instanceof Error ? err.message : String(err)}`);
|
|
7551
7064
|
}
|
|
7552
7065
|
}
|
|
7553
|
-
const inboxDir =
|
|
7066
|
+
const inboxDir = join16(currentFlintPath, "Inbox");
|
|
7554
7067
|
try {
|
|
7555
|
-
const inboxEntries = await
|
|
7068
|
+
const inboxEntries = await readdir9(inboxDir);
|
|
7556
7069
|
if (inboxEntries.length === 0) {
|
|
7557
|
-
await
|
|
7070
|
+
await rm7(inboxDir, { recursive: true });
|
|
7558
7071
|
}
|
|
7559
7072
|
} catch {
|
|
7560
7073
|
}
|
|
@@ -7583,23 +7096,23 @@ async function syncFlint(flintPath, progress) {
|
|
|
7583
7096
|
var __dirname = dirname6(fileURLToPath(import.meta.url));
|
|
7584
7097
|
var presetsCache = null;
|
|
7585
7098
|
function getBuiltinPresetsDir() {
|
|
7586
|
-
return
|
|
7099
|
+
return join17(__dirname, "presets");
|
|
7587
7100
|
}
|
|
7588
7101
|
function getUserPresetsDir() {
|
|
7589
|
-
return
|
|
7102
|
+
return join17(getGlobalFlintDir(), "presets");
|
|
7590
7103
|
}
|
|
7591
7104
|
function resolvePresetTarget(flintPath, targetPath) {
|
|
7592
|
-
const resolvedRoot =
|
|
7593
|
-
const resolvedTarget =
|
|
7105
|
+
const resolvedRoot = resolve7(flintPath);
|
|
7106
|
+
const resolvedTarget = resolve7(flintPath, targetPath);
|
|
7594
7107
|
if (!resolvedTarget.startsWith(resolvedRoot + sep)) {
|
|
7595
7108
|
throw new Error(`Preset template target escapes flint root: ${targetPath}`);
|
|
7596
7109
|
}
|
|
7597
7110
|
return resolvedTarget;
|
|
7598
7111
|
}
|
|
7599
7112
|
async function loadPresetFromDir(presetDir) {
|
|
7600
|
-
const tomlPath =
|
|
7113
|
+
const tomlPath = join17(presetDir, "preset.toml");
|
|
7601
7114
|
try {
|
|
7602
|
-
const content = await
|
|
7115
|
+
const content = await readFile9(tomlPath, "utf-8");
|
|
7603
7116
|
const parsed = parse(content);
|
|
7604
7117
|
return {
|
|
7605
7118
|
name: parsed.preset.name,
|
|
@@ -7615,10 +7128,10 @@ async function loadPresetFromDir(presetDir) {
|
|
|
7615
7128
|
async function discoverPresetsFromDir(presetsDir) {
|
|
7616
7129
|
const presets = /* @__PURE__ */ new Map();
|
|
7617
7130
|
try {
|
|
7618
|
-
const entries = await
|
|
7131
|
+
const entries = await readdir82(presetsDir, { withFileTypes: true });
|
|
7619
7132
|
for (const entry of entries) {
|
|
7620
7133
|
if (!entry.isDirectory()) continue;
|
|
7621
|
-
const presetDir =
|
|
7134
|
+
const presetDir = join17(presetsDir, entry.name);
|
|
7622
7135
|
const preset = await loadPresetFromDir(presetDir);
|
|
7623
7136
|
if (preset) {
|
|
7624
7137
|
presets.set(preset.name, preset);
|
|
@@ -7662,21 +7175,21 @@ async function hasPreset(name) {
|
|
|
7662
7175
|
async function applyPresetTemplates(flintPath, preset, flintName) {
|
|
7663
7176
|
for (const template of preset.templates) {
|
|
7664
7177
|
const templateUuid = randomUUID4();
|
|
7665
|
-
const sourcePath =
|
|
7178
|
+
const sourcePath = join17(preset.basePath, template.source);
|
|
7666
7179
|
const renderedTarget = template.target.replace(/\{\{name\}\}/g, flintName).replace(/\{\{uuid\}\}/g, templateUuid).replace(/\{\{date\}\}/g, (/* @__PURE__ */ new Date()).toISOString().split("T")[0]);
|
|
7667
7180
|
const resolvedTargetPath = resolvePresetTarget(flintPath, renderedTarget);
|
|
7668
|
-
await
|
|
7669
|
-
let content = await
|
|
7181
|
+
await mkdir12(dirname6(resolvedTargetPath), { recursive: true });
|
|
7182
|
+
let content = await readFile9(sourcePath, "utf-8");
|
|
7670
7183
|
content = content.replace(/\{\{name\}\}/g, flintName).replace(/\{\{uuid\}\}/g, templateUuid).replace(/\{\{date\}\}/g, (/* @__PURE__ */ new Date()).toISOString().split("T")[0]);
|
|
7671
|
-
const { writeFile:
|
|
7672
|
-
await
|
|
7184
|
+
const { writeFile: writeFile10 } = await import("fs/promises");
|
|
7185
|
+
await writeFile10(resolvedTargetPath, content);
|
|
7673
7186
|
}
|
|
7674
7187
|
}
|
|
7675
7188
|
function getSessionsDir(flintPath) {
|
|
7676
|
-
return
|
|
7189
|
+
return join18(flintPath, ".orbh", "sessions");
|
|
7677
7190
|
}
|
|
7678
7191
|
function getSessionPath(flintPath, sessionId) {
|
|
7679
|
-
return
|
|
7192
|
+
return join18(getSessionsDir(flintPath), `${sessionId}.json`);
|
|
7680
7193
|
}
|
|
7681
7194
|
function ensureSessionsDir(flintPath) {
|
|
7682
7195
|
const dir = getSessionsDir(flintPath);
|
|
@@ -7825,7 +7338,7 @@ function listSessions(flintPath) {
|
|
|
7825
7338
|
const sessions = [];
|
|
7826
7339
|
for (const file of files) {
|
|
7827
7340
|
try {
|
|
7828
|
-
const content = readFileSync2(
|
|
7341
|
+
const content = readFileSync2(join18(dir, file), "utf-8");
|
|
7829
7342
|
sessions.push(JSON.parse(content));
|
|
7830
7343
|
} catch {
|
|
7831
7344
|
}
|
|
@@ -8043,7 +7556,7 @@ function parseJsonl(text) {
|
|
|
8043
7556
|
}
|
|
8044
7557
|
function resolveTranscriptPath(cwd, nativeSessionId) {
|
|
8045
7558
|
const sanitized = cwd.replace(/[^a-zA-Z0-9\-_]/g, "-");
|
|
8046
|
-
return
|
|
7559
|
+
return join19(homedir3(), ".claude", "projects", sanitized, `${nativeSessionId}.jsonl`);
|
|
8047
7560
|
}
|
|
8048
7561
|
var TranscriptWatcher = class {
|
|
8049
7562
|
transcriptPath = null;
|
|
@@ -8384,19 +7897,6 @@ export {
|
|
|
8384
7897
|
getConfigValue,
|
|
8385
7898
|
setConfigValue,
|
|
8386
7899
|
getOpenApps,
|
|
8387
|
-
readPlateManifest,
|
|
8388
|
-
initPlateRepo,
|
|
8389
|
-
clonePlateFromRepo,
|
|
8390
|
-
updatePlateFromRepo,
|
|
8391
|
-
syncPlateRepos,
|
|
8392
|
-
listPlates,
|
|
8393
|
-
getPlate,
|
|
8394
|
-
createPlate,
|
|
8395
|
-
installPlateDeps,
|
|
8396
|
-
buildPlate,
|
|
8397
|
-
runPlateTool,
|
|
8398
|
-
listPlateTools,
|
|
8399
|
-
spawnPlateDevServer,
|
|
8400
7900
|
getIdentityStatePath,
|
|
8401
7901
|
getPersonFilePath,
|
|
8402
7902
|
readIdentityState,
|
|
@@ -8436,7 +7936,7 @@ export {
|
|
|
8436
7936
|
fulfillCodebase,
|
|
8437
7937
|
fulfillFlint,
|
|
8438
7938
|
unfulfill,
|
|
8439
|
-
|
|
7939
|
+
resolve2,
|
|
8440
7940
|
getStatus,
|
|
8441
7941
|
getUnfulfilled,
|
|
8442
7942
|
getUnfulfilledCodebases,
|